From 614f10630426294548f9fed35595d75bc3c83a53 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sat, 17 Jul 2010 18:24:14 +0200 Subject: [PATCH] arrows can target players; card attachment works --- cockatrice/src/abstractcarditem.cpp | 4 +- cockatrice/src/abstractcarditem.h | 3 +- cockatrice/src/arrowitem.cpp | 98 ++++++- cockatrice/src/arrowitem.h | 13 +- cockatrice/src/arrowtarget.cpp | 14 +- cockatrice/src/arrowtarget.h | 21 +- cockatrice/src/carddragitem.cpp | 4 +- cockatrice/src/carddragitem.h | 4 +- cockatrice/src/carditem.cpp | 43 ++- cockatrice/src/carditem.h | 11 +- cockatrice/src/cardzone.cpp | 10 +- cockatrice/src/deckview.cpp | 2 +- cockatrice/src/messagelogwidget.cpp | 12 + cockatrice/src/messagelogwidget.h | 2 + cockatrice/src/player.cpp | 121 ++++++-- cockatrice/src/player.h | 6 + cockatrice/src/playertarget.cpp | 5 +- cockatrice/src/playertarget.h | 4 +- cockatrice/src/tab_game.cpp | 44 ++- cockatrice/src/tab_game.h | 3 + cockatrice/src/tablezone.cpp | 78 ++++- cockatrice/src/tablezone.h | 1 + cockatrice/translations/cockatrice_de.ts | 299 ++++++++++--------- cockatrice/translations/cockatrice_en.ts | 357 ++++++++++++----------- common/protocol_datastructures.cpp | 5 +- common/protocol_datastructures.h | 5 +- common/server_card.cpp | 15 + common/server_card.h | 6 +- common/server_game.cpp | 10 +- common/server_protocolhandler.cpp | 81 ++++- common/server_protocolhandler.h | 2 + oracle/sets.xml | 4 + 32 files changed, 885 insertions(+), 402 deletions(-) diff --git a/cockatrice/src/abstractcarditem.cpp b/cockatrice/src/abstractcarditem.cpp index b2b474ef..62be0113 100644 --- a/cockatrice/src/abstractcarditem.cpp +++ b/cockatrice/src/abstractcarditem.cpp @@ -8,8 +8,8 @@ #include "main.h" #include -AbstractCardItem::AbstractCardItem(const QString &_name, QGraphicsItem *parent) - : ArrowTarget(parent), info(db->getCard(_name)), name(_name), tapped(false) +AbstractCardItem::AbstractCardItem(const QString &_name, Player *_owner, QGraphicsItem *parent) + : ArrowTarget(_owner, parent), info(db->getCard(_name)), name(_name), tapped(false) { setCursor(Qt::OpenHandCursor); setFlag(ItemIsSelectable); diff --git a/cockatrice/src/abstractcarditem.h b/cockatrice/src/abstractcarditem.h index d3f869f6..6d77f6f3 100644 --- a/cockatrice/src/abstractcarditem.h +++ b/cockatrice/src/abstractcarditem.h @@ -4,6 +4,7 @@ #include "arrowtarget.h" class CardInfo; +class Player; const int CARD_WIDTH = 72; const int CARD_HEIGHT = 102; @@ -22,7 +23,7 @@ signals: public: enum { Type = typeCard }; int type() const { return Type; } - AbstractCardItem(const QString &_name = QString(), QGraphicsItem *parent = 0); + AbstractCardItem(const QString &_name = QString(), Player *_owner = 0, QGraphicsItem *parent = 0); ~AbstractCardItem(); QRectF boundingRect() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); diff --git a/cockatrice/src/arrowitem.cpp b/cockatrice/src/arrowitem.cpp index f141e589..7eecba46 100644 --- a/cockatrice/src/arrowitem.cpp +++ b/cockatrice/src/arrowitem.cpp @@ -8,15 +8,34 @@ #include #include #include +#include ArrowItem::ArrowItem(Player *_player, int _id, ArrowTarget *_startItem, ArrowTarget *_targetItem, const QColor &_color) : QGraphicsItem(), player(_player), id(_id), startItem(_startItem), targetItem(_targetItem), color(_color), fullColor(true) { setZValue(2000000005); + + if (startItem) + startItem->addArrowFrom(this); + if (targetItem) + targetItem->addArrowTo(this); + if (startItem && targetItem) updatePath(); } +ArrowItem::~ArrowItem() +{ + qDebug() << "ArrowItem destructor"; + if (startItem) + startItem->removeArrowFrom(this); + + if (targetItem) { + targetItem->setBeingPointedAt(false); + targetItem->removeArrowTo(this); + } +} + void ArrowItem::updatePath() { QPointF endPoint = targetItem->mapToScene(QPointF(targetItem->boundingRect().width() / 2, targetItem->boundingRect().height() / 2)); @@ -97,8 +116,8 @@ void ArrowItem::mousePressEvent(QGraphicsSceneMouseEvent *event) player->sendGameCommand(new Command_DeleteArrow(-1, id)); } -ArrowDragItem::ArrowDragItem(ArrowTarget *_startItem, const QColor &_color) - : ArrowItem(static_cast(_startItem->parentItem())->getPlayer(), -1, _startItem, 0, _color) +ArrowDragItem::ArrowDragItem(Player *_owner, ArrowTarget *_startItem, const QColor &_color) + : ArrowItem(_owner, -1, _startItem, 0, _color) { } @@ -118,17 +137,23 @@ void ArrowDragItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) cursorItem = static_cast(colliding.at(i)); break; } - if ((cursorItem != targetItem) && targetItem) + if ((cursorItem != targetItem) && targetItem) { targetItem->setBeingPointedAt(false); + targetItem->removeArrowTo(this); + } if (!cursorItem) { fullColor = false; targetItem = 0; updatePath(endPos); } else { - fullColor = true; - if (cursorItem != startItem) - cursorItem->setBeingPointedAt(true); - targetItem = cursorItem; + if (cursorItem != targetItem) { + fullColor = true; + if (cursorItem != startItem) { + cursorItem->setBeingPointedAt(true); + cursorItem->addArrowTo(this); + } + targetItem = cursorItem; + } updatePath(); } update(); @@ -140,14 +165,13 @@ void ArrowDragItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) void ArrowDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { if (targetItem && (targetItem != startItem)) { - targetItem->setBeingPointedAt(false); - CardZone *startZone = static_cast(startItem->parentItem()); + CardZone *startZone = static_cast(startItem)->getZone(); // For now, we can safely assume that the start item is always a card. // The target item can be a player as well. CardItem *startCard = qgraphicsitem_cast(startItem); CardItem *targetCard = qgraphicsitem_cast(targetItem); if (targetCard) { - CardZone *targetZone = static_cast(targetItem->parentItem()); + CardZone *targetZone = targetCard->getZone(); player->sendGameCommand(new Command_CreateArrow( -1, startZone->getPlayer()->getId(), @@ -165,7 +189,7 @@ void ArrowDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) startZone->getPlayer()->getId(), startZone->getName(), startCard->getId(), - static_cast(targetPlayer->parentItem())->getId(), + targetPlayer->getOwner()->getId(), QString(), -1, color @@ -177,3 +201,55 @@ void ArrowDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) for (int i = 0; i < childArrows.size(); ++i) childArrows[i]->mouseReleaseEvent(event); } + +ArrowAttachItem::ArrowAttachItem(ArrowTarget *_startItem) + : ArrowItem(_startItem->getOwner(), -1, _startItem, 0, Qt::green) +{ +} + +void ArrowAttachItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + QPointF endPos = event->scenePos(); + + QList colliding = scene()->items(endPos); + ArrowTarget *cursorItem = 0; + for (int i = colliding.size() - 1; i >= 0; i--) + if (qgraphicsitem_cast(colliding.at(i))) { + cursorItem = static_cast(colliding.at(i)); + break; + } + if ((cursorItem != targetItem) && targetItem) + targetItem->setBeingPointedAt(false); + if (!cursorItem) { + fullColor = false; + targetItem = 0; + updatePath(endPos); + } else { + fullColor = true; + if (cursorItem != startItem) + cursorItem->setBeingPointedAt(true); + targetItem = cursorItem; + updatePath(); + } + update(); +} + +void ArrowAttachItem::mouseReleaseEvent(QGraphicsSceneMouseEvent * /*event*/) +{ + if (targetItem && (targetItem != startItem)) { + CardItem *startCard = qgraphicsitem_cast(startItem); + CardZone *startZone = startCard->getZone(); + CardItem *targetCard = qgraphicsitem_cast(targetItem); + CardZone *targetZone = targetCard->getZone(); + + player->sendGameCommand(new Command_AttachCard( + -1, + startZone->getName(), + startCard->getId(), + targetZone->getPlayer()->getId(), + targetZone->getName(), + targetCard->getId() + )); + } + deleteLater(); +} diff --git a/cockatrice/src/arrowitem.h b/cockatrice/src/arrowitem.h index ffb90d1d..ae931715 100644 --- a/cockatrice/src/arrowitem.h +++ b/cockatrice/src/arrowitem.h @@ -23,6 +23,7 @@ protected: void mousePressEvent(QGraphicsSceneMouseEvent *event); public: ArrowItem(Player *_player, int _id, ArrowTarget *_startItem, ArrowTarget *_targetItem, const QColor &color); + ~ArrowItem(); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); QRectF boundingRect() const { return path.boundingRect(); } QPainterPath shape() const { return path; } @@ -30,6 +31,7 @@ public: void updatePath(const QPointF &endPoint); int getId() const { return id; } + Player *getPlayer() const { return player; } void setStartItem(ArrowTarget *_item) { startItem = _item; } void setTargetItem(ArrowTarget *_item) { targetItem = _item; } ArrowTarget *getStartItem() const { return startItem; } @@ -41,11 +43,20 @@ class ArrowDragItem : public ArrowItem { private: QList childArrows; public: - ArrowDragItem(ArrowTarget *_startItem, const QColor &_color); + ArrowDragItem(Player *_owner, ArrowTarget *_startItem, const QColor &_color); void addChildArrow(ArrowDragItem *childArrow); protected: void mouseMoveEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); }; +class ArrowAttachItem : public ArrowItem { + Q_OBJECT +public: + ArrowAttachItem(ArrowTarget *_startItem); +protected: + void mouseMoveEvent(QGraphicsSceneMouseEvent *event); + void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); +}; + #endif // ARROWITEM_H diff --git a/cockatrice/src/arrowtarget.cpp b/cockatrice/src/arrowtarget.cpp index e333087a..1edf926b 100644 --- a/cockatrice/src/arrowtarget.cpp +++ b/cockatrice/src/arrowtarget.cpp @@ -1,10 +1,20 @@ #include "arrowtarget.h" +#include "arrowitem.h" +#include "player.h" -ArrowTarget::ArrowTarget(QGraphicsItem *parent) - : AbstractGraphicsItem(parent), beingPointedAt(false) +ArrowTarget::ArrowTarget(Player *_owner, QGraphicsItem *parent) + : AbstractGraphicsItem(parent), owner(_owner), beingPointedAt(false) { } +ArrowTarget::~ArrowTarget() +{ + while (!arrowsFrom.isEmpty()) + arrowsFrom.first()->getPlayer()->delArrow(arrowsFrom.first()->getId()); + while (!arrowsTo.isEmpty()) + arrowsTo.first()->getPlayer()->delArrow(arrowsTo.first()->getId()); +} + void ArrowTarget::setBeingPointedAt(bool _beingPointedAt) { beingPointedAt = _beingPointedAt; diff --git a/cockatrice/src/arrowtarget.h b/cockatrice/src/arrowtarget.h index 8dbed0fb..dc3e2036 100644 --- a/cockatrice/src/arrowtarget.h +++ b/cockatrice/src/arrowtarget.h @@ -2,14 +2,33 @@ #define ARROWTARGET_H #include "abstractgraphicsitem.h" +#include + +class Player; +class ArrowItem; class ArrowTarget : public AbstractGraphicsItem { +protected: + Player *owner; private: bool beingPointedAt; + QList arrowsFrom, arrowsTo; public: - ArrowTarget(QGraphicsItem *parent = 0); + ArrowTarget(Player *_owner, QGraphicsItem *parent = 0); + ~ArrowTarget(); + + Player *getOwner() const { return owner; } + void setBeingPointedAt(bool _beingPointedAt); bool getBeingPointedAt() const { return beingPointedAt; } + + const QList &getArrowsFrom() const { return arrowsFrom; } + void addArrowFrom(ArrowItem *arrow) { arrowsFrom.append(arrow); } + void removeArrowFrom(ArrowItem *arrow) { arrowsFrom.removeAt(arrowsFrom.indexOf(arrow)); } + + const QList &getArrowsTo() const { return arrowsTo; } + void addArrowTo(ArrowItem *arrow) { arrowsTo.append(arrow); } + void removeArrowTo(ArrowItem *arrow) { arrowsTo.removeAt(arrowsTo.indexOf(arrow)); } }; #endif \ No newline at end of file diff --git a/cockatrice/src/carddragitem.cpp b/cockatrice/src/carddragitem.cpp index 6625234a..53094d20 100644 --- a/cockatrice/src/carddragitem.cpp +++ b/cockatrice/src/carddragitem.cpp @@ -6,7 +6,7 @@ #include #include -CardDragItem::CardDragItem(AbstractCardItem *_item, int _id, const QPointF &_hotSpot, bool _faceDown, AbstractCardDragItem *parentDrag) +CardDragItem::CardDragItem(CardItem *_item, int _id, const QPointF &_hotSpot, bool _faceDown, AbstractCardDragItem *parentDrag) : AbstractCardDragItem(_item, _hotSpot, parentDrag), id(_id), faceDown(_faceDown), currentZone(0) { } @@ -53,7 +53,7 @@ void CardDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) sc->removeItem(this); if (currentZone) { - CardZone *startZone = qgraphicsitem_cast(item->parentItem()); + CardZone *startZone = static_cast(item)->getZone(); currentZone->handleDropEvent(id, startZone, (sp - currentZone->scenePos()).toPoint(), faceDown); for (int i = 0; i < childDrags.size(); i++) { CardDragItem *c = static_cast(childDrags[i]); diff --git a/cockatrice/src/carddragitem.h b/cockatrice/src/carddragitem.h index d1095f1d..dcaa13b8 100644 --- a/cockatrice/src/carddragitem.h +++ b/cockatrice/src/carddragitem.h @@ -3,13 +3,15 @@ #include "abstractcarddragitem.h" +class CardItem; + class CardDragItem : public AbstractCardDragItem { private: int id; bool faceDown; CardZone *currentZone; public: - CardDragItem(AbstractCardItem *_item, int _id, const QPointF &_hotSpot, bool _faceDown, AbstractCardDragItem *parentDrag = 0); + CardDragItem(CardItem *_item, int _id, const QPointF &_hotSpot, bool _faceDown, AbstractCardDragItem *parentDrag = 0); void updatePosition(const QPointF &cursorScenePos); protected: void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); diff --git a/cockatrice/src/carditem.cpp b/cockatrice/src/carditem.cpp index a8353fdf..bc9a3162 100644 --- a/cockatrice/src/carditem.cpp +++ b/cockatrice/src/carditem.cpp @@ -10,9 +10,10 @@ #include "main.h" #include "protocol_datastructures.h" #include "settingscache.h" +#include "tab_game.h" CardItem::CardItem(Player *_owner, const QString &_name, int _cardid, QGraphicsItem *parent) - : AbstractCardItem(_name, parent), owner(_owner), id(_cardid), attacking(false), facedown(false), destroyOnZoneChange(false), doesntUntap(false), dragItem(NULL) + : AbstractCardItem(_name, _owner, parent), id(_cardid), attacking(false), facedown(false), destroyOnZoneChange(false), doesntUntap(false), dragItem(0), attachedTo(0) { owner->addCard(this); @@ -106,6 +107,14 @@ CardItem::~CardItem() owner->setCardMenu(0); delete cardMenu; + while (!attachedCards.isEmpty()) { + attachedCards.first()->setZone(0); // so that it won't try to call reorganizeCards() + attachedCards.first()->setAttachedTo(0); + } + + if (attachedTo) + attachedTo->removeAttachedCard(this); + deleteDragItem(); } @@ -118,6 +127,7 @@ void CardItem::retranslateUi() aFlip->setText(tr("&Flip")); aClone->setText(tr("&Clone")); aAttach->setText(tr("&Attach to card...")); + aAttach->setShortcut(tr("Ctrl+A")); aUnattach->setText(tr("Unattac&h")); aSetPT->setText(tr("Set &P/T...")); aSetAnnotation->setText(tr("&Set annotation...")); @@ -214,6 +224,23 @@ void CardItem::setPT(const QString &_pt) update(); } +void CardItem::setAttachedTo(CardItem *_attachedTo) +{ + if (attachedTo) + attachedTo->removeAttachedCard(this); + + gridPoint.setX(-1); + attachedTo = _attachedTo; + if (attachedTo) { + attachedTo->addAttachedCard(this); + if (zone != attachedTo->getZone()) + attachedTo->getZone()->reorganizeCards(); + } + + if (zone) + zone->reorganizeCards(); +} + void CardItem::resetState() { attacking = false; @@ -221,6 +248,8 @@ void CardItem::resetState() counters.clear(); pt.clear(); annotation.clear(); + attachedTo = 0; + attachedCards.clear(); setTapped(false); setDoesntUntap(false); update(); @@ -273,7 +302,8 @@ void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) else if (event->modifiers().testFlag(Qt::ShiftModifier)) arrowColor = Qt::green; - ArrowDragItem *arrow = new ArrowDragItem(this, arrowColor); + Player *arrowOwner = static_cast(owner->parent())->getActiveLocalPlayer(); + ArrowDragItem *arrow = new ArrowDragItem(arrowOwner, this, arrowColor); scene()->addItem(arrow); arrow->grabMouse(); @@ -282,10 +312,10 @@ void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) CardItem *c = qgraphicsitem_cast(itemIterator.next()); if (!c || (c == this)) continue; - if (c->parentItem() != parentItem()) + if (c->getZone() != zone) continue; - ArrowDragItem *childArrow = new ArrowDragItem(c, arrowColor); + ArrowDragItem *childArrow = new ArrowDragItem(arrowOwner, c, arrowColor); scene()->addItem(childArrow); arrow->addChildArrow(childArrow); } @@ -300,8 +330,6 @@ void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) createDragItem(id, event->pos(), event->scenePos(), faceDown); dragItem->grabMouse(); - CardZone *zone = static_cast(parentItem()); - QList sel = scene()->selectedItems(); int j = 0; for (int i = 0; i < sel.size(); i++) { @@ -324,9 +352,8 @@ void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) void CardItem::playCard(QGraphicsSceneMouseEvent *event) { - CardZone *zone = static_cast(parentItem()); // Do nothing if the card belongs to another player - if (!zone->getPlayer()->getLocal()) + if (!owner->getLocal()) return; TableZone *tz = qobject_cast(zone); diff --git a/cockatrice/src/carditem.h b/cockatrice/src/carditem.h index 26e218af..586d2147 100644 --- a/cockatrice/src/carditem.h +++ b/cockatrice/src/carditem.h @@ -15,7 +15,7 @@ const int MAX_COUNTERS_ON_CARD = 999; class CardItem : public AbstractCardItem { Q_OBJECT private: - Player *owner; + CardZone *zone; int id; bool attacking; bool facedown; @@ -26,6 +26,8 @@ private: bool doesntUntap; QPoint gridPoint; CardDragItem *dragItem; + CardItem *attachedTo; + QList attachedCards; QList aAddCounter, aSetCounter, aRemoveCounter; QAction *aTap, *aUntap, *aDoesntUntap, *aAttach, *aUnattach, *aSetPT, *aSetAnnotation, *aFlip, *aClone, @@ -39,6 +41,8 @@ public: CardItem(Player *_owner, const QString &_name = QString(), int _cardid = -1, QGraphicsItem *parent = 0); ~CardItem(); void retranslateUi(); + CardZone *getZone() const { return zone; } + void setZone(CardZone *_zone) { zone = _zone; } QMenu *getCardMenu() const { return cardMenu; } void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); QPoint getGridPoint() const { return gridPoint; } @@ -61,6 +65,11 @@ public: void setPT(const QString &_pt); bool getDestroyOnZoneChange() const { return destroyOnZoneChange; } void setDestroyOnZoneChange(bool _destroy) { destroyOnZoneChange = _destroy; } + CardItem *getAttachedTo() const { return attachedTo; } + void setAttachedTo(CardItem *_attachedTo); + void addAttachedCard(CardItem *card) { attachedCards.append(card); } + void removeAttachedCard(CardItem *card) { attachedCards.removeAt(attachedCards.indexOf(card)); } + const QList &getAttachedCards() const { return attachedCards; } void resetState(); void processCardInfo(ServerInfo_Card *info); diff --git a/cockatrice/src/cardzone.cpp b/cockatrice/src/cardzone.cpp index ad6f2725..f572af1c 100644 --- a/cockatrice/src/cardzone.cpp +++ b/cockatrice/src/cardzone.cpp @@ -27,8 +27,15 @@ void CardZone::retranslateUi() void CardZone::clearContents() { - for (int i = 0; i < cards.size(); i++) + for (int i = 0; i < cards.size(); i++) { + // If an incorrectly implemented server doesn't return attached cards to whom they belong before dropping a player, + // we have to return them to avoid a crash. + const QList &attachedCards = cards[i]->getAttachedCards(); + for (int j = 0; j < attachedCards.size(); ++j) + attachedCards[j]->setParentItem(attachedCards[j]->getZone()); + delete cards.at(i); + } cards.clear(); emit cardCountChanged(); } @@ -93,6 +100,7 @@ void CardZone::addCard(CardItem *card, bool reorganize, int x, int y) if ((x <= view->getCards().size()) || (view->getNumberCards() == -1)) view->addCard(new CardItem(player, card->getName(), card->getId()), reorganize, x, y); + card->setZone(this); addCardImpl(card, x, y); if (reorganize) diff --git a/cockatrice/src/deckview.cpp b/cockatrice/src/deckview.cpp index 1790bb25..56988e11 100644 --- a/cockatrice/src/deckview.cpp +++ b/cockatrice/src/deckview.cpp @@ -60,7 +60,7 @@ void DeckViewCardDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) } DeckViewCard::DeckViewCard(const QString &_name, const QString &_originZone, QGraphicsItem *parent) - : AbstractCardItem(_name, parent), originZone(_originZone), dragItem(0) + : AbstractCardItem(_name, 0, parent), originZone(_originZone), dragItem(0) { } diff --git a/cockatrice/src/messagelogwidget.cpp b/cockatrice/src/messagelogwidget.cpp index 759ef1ea..caf9bc4d 100644 --- a/cockatrice/src/messagelogwidget.cpp +++ b/cockatrice/src/messagelogwidget.cpp @@ -207,6 +207,16 @@ void MessageLogWidget::logDestroyCard(Player *player, QString cardName) append(tr("%1 destroys %2.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName)))); } +void MessageLogWidget::logAttachCard(Player *player, QString cardName, Player *targetPlayer, QString targetCardName) +{ + append(tr("%1 attaches %2 to %3's %4.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName))).arg(sanitizeHtml(targetPlayer->getName())).arg(QString("%1").arg(sanitizeHtml(targetCardName)))); +} + +void MessageLogWidget::logUnattachCard(Player *player, QString cardName) +{ + append(tr("%1 unattaches %2.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName)))); +} + void MessageLogWidget::logCreateToken(Player *player, QString cardName, QString pt) { append(tr("%1 creates token: %2%3.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName))).arg(pt.isEmpty() ? QString() : QString(" (%1)").arg(sanitizeHtml(pt)))); @@ -341,6 +351,8 @@ void MessageLogWidget::connectToPlayer(Player *player) connect(player, SIGNAL(logSetAnnotation(Player *, QString, QString)), this, SLOT(logSetAnnotation(Player *, QString, QString))); connect(player, SIGNAL(logMoveCard(Player *, QString, CardZone *, int, CardZone *, int)), this, SLOT(logMoveCard(Player *, QString, CardZone *, int, CardZone *, int))); connect(player, SIGNAL(logDestroyCard(Player *, QString)), this, SLOT(logDestroyCard(Player *, QString))); + connect(player, SIGNAL(logAttachCard(Player *, QString, Player *, QString)), this, SLOT(logAttachCard(Player *, QString, Player *, QString))); + connect(player, SIGNAL(logUnattachCard(Player *, QString)), this, SLOT(logUnattachCard(Player *, QString))); connect(player, SIGNAL(logDumpZone(Player *, CardZone *, int)), this, SLOT(logDumpZone(Player *, CardZone *, int))); connect(player, SIGNAL(logStopDumpZone(Player *, CardZone *)), this, SLOT(logStopDumpZone(Player *, CardZone *))); connect(player, SIGNAL(logDrawCards(Player *, int)), this, SLOT(logDrawCards(Player *, int))); diff --git a/cockatrice/src/messagelogwidget.h b/cockatrice/src/messagelogwidget.h index 49fde3ee..c8787b57 100644 --- a/cockatrice/src/messagelogwidget.h +++ b/cockatrice/src/messagelogwidget.h @@ -40,6 +40,8 @@ public slots: void logDrawCards(Player *player, int number); void logMoveCard(Player *player, QString cardName, CardZone *startZone, int oldX, CardZone *targetZone, int newX); void logDestroyCard(Player *player, QString cardName); + void logAttachCard(Player *player, QString cardName, Player *targetPlayer, QString targetCardName); + void logUnattachCard(Player *player, QString cardName); void logCreateToken(Player *player, QString cardName, QString pt); void logCreateArrow(Player *player, Player *startPlayer, QString startCard, Player *targetPlayer, QString targetCard, bool playerTarget); void logSetCardCounter(Player *player, QString cardName, int counterId, int value, int oldValue); diff --git a/cockatrice/src/player.cpp b/cockatrice/src/player.cpp index f1ef06fa..a64666a0 100644 --- a/cockatrice/src/player.cpp +++ b/cockatrice/src/player.cpp @@ -224,12 +224,13 @@ Player::~Player() static_cast(scene())->removePlayer(this); + clearArrows(); + QMapIterator i(zones); while (i.hasNext()) delete i.next().value(); clearCounters(); - clearArrows(); delete playerMenu; } @@ -501,7 +502,7 @@ void Player::eventCreateArrows(Event_CreateArrows *event) if (targetCard) emit logCreateArrow(this, startCard->getOwner(), startCard->getName(), targetCard->getOwner(), targetCard->getName(), false); else - emit logCreateArrow(this, startCard->getOwner(), startCard->getName(), static_cast(arrow->getTargetItem()->parentItem()), QString(), true); + emit logCreateArrow(this, startCard->getOwner(), startCard->getName(), arrow->getTargetItem()->getOwner(), QString(), true); } } @@ -677,6 +678,43 @@ void Player::eventDestroyCard(Event_DestroyCard *event) delete card; } +void Player::eventAttachCard(Event_AttachCard *event) +{ + const QMap &playerList = static_cast(parent())->getPlayers(); + int targetPlayerId = event->getTargetPlayerId(); + Player *targetPlayer = 0; + CardZone *targetZone = 0; + CardItem *targetCard = 0; + if (targetPlayerId != -1) + targetPlayer = playerList.value(targetPlayerId, 0); + if (targetPlayer) + targetZone = targetPlayer->getZones().value(event->getTargetZone(), 0); + if (targetZone) + targetCard = targetZone->getCard(event->getTargetCardId(), QString()); + + CardZone *startZone = getZones().value(event->getStartZone(), 0); + if (!startZone) + return; + + CardItem *startCard = startZone->getCard(event->getCardId(), QString()); + if (!startCard) + return; + + if (targetZone) + startCard->setParentItem(targetZone); + else + startCard->setParentItem(startZone); + startCard->setAttachedTo(targetCard); + startZone->reorganizeCards(); + if ((startZone != targetZone) && targetZone) + targetZone->reorganizeCards(); + + if (targetCard) + emit logAttachCard(this, startCard->getName(), targetPlayer, targetCard->getName()); + else + emit logUnattachCard(this, startCard->getName()); +} + void Player::eventDrawCards(Event_DrawCards *event) { CardZone *deck = zones.value("deck"); @@ -712,6 +750,7 @@ void Player::processGameEvent(GameEvent *event, GameEventContext *context) case ItemId_Event_StopDumpZone: eventStopDumpZone(qobject_cast(event)); break; case ItemId_Event_MoveCard: eventMoveCard(qobject_cast(event)); break; case ItemId_Event_DestroyCard: eventDestroyCard(qobject_cast(event)); break; + case ItemId_Event_AttachCard: eventAttachCard(qobject_cast(event)); break; case ItemId_Event_DrawCards: eventDrawCards(qobject_cast(event)); break; default: { qDebug() << "unhandled game event"; @@ -746,8 +785,12 @@ void Player::processPlayerInfo(ServerInfo_Player *info) while (zoneIt.hasNext()) zoneIt.next().value()->clearContents(); - for (int i = 0; i < info->getZoneList().size(); ++i) { - ServerInfo_Zone *zoneInfo = info->getZoneList()[i]; + clearCounters(); + clearArrows(); + + QList zl = info->getZoneList(); + for (int i = 0; i < zl.size(); ++i) { + ServerInfo_Zone *zoneInfo = zl[i]; CardZone *zone = zones.value(zoneInfo->getName(), 0); if (!zone) continue; @@ -766,14 +809,38 @@ void Player::processPlayerInfo(ServerInfo_Player *info) zone->reorganizeCards(); } - clearCounters(); - for (int i = 0; i < info->getCounterList().size(); ++i) { - addCounter(info->getCounterList().at(i)); + QList cl = info->getCounterList(); + for (int i = 0; i < cl.size(); ++i) { + addCounter(cl.at(i)); } - clearArrows(); - for (int i = 0; i < info->getArrowList().size(); ++i) - addArrow(info->getArrowList().at(i)); + QList al = info->getArrowList(); + for (int i = 0; i < al.size(); ++i) + addArrow(al.at(i)); +} + +void Player::processCardAttachment(ServerInfo_Player *info) +{ + QList zl = info->getZoneList(); + for (int i = 0; i < zl.size(); ++i) { + ServerInfo_Zone *zoneInfo = zl[i]; + CardZone *zone = zones.value(zoneInfo->getName(), 0); + if (!zone) + continue; + + const QList &cardList = zoneInfo->getCardList(); + for (int j = 0; j < cardList.size(); ++j) { + ServerInfo_Card *cardInfo = cardList[j]; + if (cardInfo->getAttachPlayerId() != -1) { + CardItem *startCard = zone->getCard(cardInfo->getId(), QString()); + CardItem *targetCard = static_cast(parent())->getCard(cardInfo->getAttachPlayerId(), cardInfo->getAttachZone(), cardInfo->getAttachCardId()); + if (!targetCard) + continue; + + startCard->setAttachedTo(targetCard); + } + } + } } void Player::addCard(CardItem *c) @@ -924,34 +991,34 @@ void Player::cardMenuAction() switch (a->data().toInt()) { case 0: if (!card->getTapped()) - commandList.append(new Command_SetCardAttr(-1, qgraphicsitem_cast(card->parentItem())->getName(), card->getId(), "tapped", "1")); + commandList.append(new Command_SetCardAttr(-1, card->getZone()->getName(), card->getId(), "tapped", "1")); break; case 1: if (card->getTapped()) - commandList.append(new Command_SetCardAttr(-1, qgraphicsitem_cast(card->parentItem())->getName(), card->getId(), "tapped", "0")); + commandList.append(new Command_SetCardAttr(-1, card->getZone()->getName(), card->getId(), "tapped", "0")); break; case 2: - commandList.append(new Command_SetCardAttr(-1, qgraphicsitem_cast(card->parentItem())->getName(), card->getId(), "doesnt_untap", QString::number(!card->getDoesntUntap()))); + commandList.append(new Command_SetCardAttr(-1, card->getZone()->getName(), card->getId(), "doesnt_untap", QString::number(!card->getDoesntUntap()))); break; case 3: { - QString zone = qgraphicsitem_cast(card->parentItem())->getName(); + QString zone = card->getZone()->getName(); commandList.append(new Command_MoveCard(-1, zone, card->getId(), zone, card->getGridPoint().x(), card->getGridPoint().y(), !card->getFaceDown())); break; } case 4: - commandList.append(new Command_CreateToken(-1, static_cast(card->parentItem())->getName(), card->getName(), card->getColor(), card->getPT(), card->getAnnotation(), card->getDestroyOnZoneChange(), -1, card->getGridPoint().y())); + commandList.append(new Command_CreateToken(-1, card->getZone()->getName(), card->getName(), card->getColor(), card->getPT(), card->getAnnotation(), card->getDestroyOnZoneChange(), -1, card->getGridPoint().y())); break; case 5: - commandList.append(new Command_MoveCard(-1, static_cast(card->parentItem())->getName(), card->getId(), "deck", 0, 0, false)); + commandList.append(new Command_MoveCard(-1, card->getZone()->getName(), card->getId(), "deck", 0, 0, false)); break; case 6: - commandList.append(new Command_MoveCard(-1, static_cast(card->parentItem())->getName(), card->getId(), "deck", -1, 0, false)); + commandList.append(new Command_MoveCard(-1, card->getZone()->getName(), card->getId(), "deck", -1, 0, false)); break; case 7: - commandList.append(new Command_MoveCard(-1, static_cast(card->parentItem())->getName(), card->getId(), "grave", 0, 0, false)); + commandList.append(new Command_MoveCard(-1, card->getZone()->getName(), card->getId(), "grave", 0, 0, false)); break; case 8: - commandList.append(new Command_MoveCard(-1, static_cast(card->parentItem())->getName(), card->getId(), "rfg", 0, 0, false)); + commandList.append(new Command_MoveCard(-1, card->getZone()->getName(), card->getId(), "rfg", 0, 0, false)); break; default: ; } @@ -976,7 +1043,7 @@ void Player::actSetPT() i.toFront(); while (i.hasNext()) { CardItem *card = static_cast(i.next()); - sendGameCommand(new Command_SetCardAttr(-1, qgraphicsitem_cast(card->parentItem())->getName(), card->getId(), "pt", pt)); + sendGameCommand(new Command_SetCardAttr(-1, card->getZone()->getName(), card->getId(), "pt", pt)); } } @@ -998,16 +1065,22 @@ void Player::actSetAnnotation() i.toFront(); while (i.hasNext()) { CardItem *card = static_cast(i.next()); - sendGameCommand(new Command_SetCardAttr(-1, qgraphicsitem_cast(card->parentItem())->getName(), card->getId(), "annotation", annotation)); + sendGameCommand(new Command_SetCardAttr(-1, card->getZone()->getName(), card->getId(), "annotation", annotation)); } } void Player::actAttach() { + CardItem *card = static_cast(sender()->parent()); + ArrowAttachItem *arrow = new ArrowAttachItem(card); + scene()->addItem(arrow); + arrow->grabMouse(); } void Player::actUnattach() { + CardItem *card = static_cast(sender()->parent()); + sendGameCommand(new Command_AttachCard(-1, card->getZone()->getName(), card->getId(), -1, QString(), -1)); } void Player::actCardCounterTrigger() @@ -1022,7 +1095,7 @@ void Player::actCardCounterTrigger() while (i.hasNext()) { CardItem *card = static_cast(i.next()); if (card->getCounters().value(counterId, 0) < MAX_COUNTERS_ON_CARD) - sendGameCommand(new Command_SetCardCounter(-1, qgraphicsitem_cast(card->parentItem())->getName(), card->getId(), counterId, card->getCounters().value(counterId, 0) + 1)); + sendGameCommand(new Command_SetCardCounter(-1, card->getZone()->getName(), card->getId(), counterId, card->getCounters().value(counterId, 0) + 1)); } break; } @@ -1031,7 +1104,7 @@ void Player::actCardCounterTrigger() while (i.hasNext()) { CardItem *card = static_cast(i.next()); if (card->getCounters().value(counterId, 0)) - sendGameCommand(new Command_SetCardCounter(-1, qgraphicsitem_cast(card->parentItem())->getName(), card->getId(), counterId, card->getCounters().value(counterId, 0) - 1)); + sendGameCommand(new Command_SetCardCounter(-1, card->getZone()->getName(), card->getId(), counterId, card->getCounters().value(counterId, 0) - 1)); } break; } @@ -1044,7 +1117,7 @@ void Player::actCardCounterTrigger() QListIterator i(scene()->selectedItems()); while (i.hasNext()) { CardItem *card = static_cast(i.next()); - sendGameCommand(new Command_SetCardCounter(-1, qgraphicsitem_cast(card->parentItem())->getName(), card->getId(), counterId, number)); + sendGameCommand(new Command_SetCardCounter(-1, card->getZone()->getName(), card->getId(), counterId, number)); } break; } diff --git a/cockatrice/src/player.h b/cockatrice/src/player.h index f5874af3..0dfa5028 100644 --- a/cockatrice/src/player.h +++ b/cockatrice/src/player.h @@ -40,6 +40,7 @@ class Event_DumpZone; class Event_StopDumpZone; class Event_MoveCard; class Event_DestroyCard; +class Event_AttachCard; class Event_DrawCards; class Player : public QObject, public QGraphicsItem { @@ -55,6 +56,8 @@ signals: void logDrawCards(Player *player, int number); void logMoveCard(Player *player, QString cardName, CardZone *startZone, int oldX, CardZone *targetZone, int newX); void logDestroyCard(Player *player, QString cardName); + void logAttachCard(Player *player, QString cardName, Player *targetPlayer, QString targetCardName); + void logUnattachCard(Player *player, QString cardName); void logSetCardCounter(Player *player, QString cardName, int counterId, int value, int oldValue); void logSetTapped(Player *player, QString cardName, bool tapped); void logSetCounter(Player *player, QString counterName, int value, int oldValue); @@ -144,6 +147,7 @@ private: void eventStopDumpZone(Event_StopDumpZone *event); void eventMoveCard(Event_MoveCard *event); void eventDestroyCard(Event_DestroyCard *event); + void eventAttachCard(Event_AttachCard *event); void eventDrawCards(Event_DrawCards *event); public: static const int counterAreaWidth = 65; @@ -189,6 +193,8 @@ public: void processSceneSizeChange(const QSizeF &newSize); void processPlayerInfo(ServerInfo_Player *info); + void processCardAttachment(ServerInfo_Player *info); + void processGameEvent(GameEvent *event, GameEventContext *context); void sendGameCommand(GameCommand *command); void sendCommandContainer(CommandContainer *cont); diff --git a/cockatrice/src/playertarget.cpp b/cockatrice/src/playertarget.cpp index aecde601..b8d6ab3f 100644 --- a/cockatrice/src/playertarget.cpp +++ b/cockatrice/src/playertarget.cpp @@ -1,8 +1,9 @@ #include "playertarget.h" +#include "player.h" #include -PlayerTarget::PlayerTarget(const QString &_name, int _maxWidth, QGraphicsItem *parent) - : ArrowTarget(parent), name(_name), maxWidth(_maxWidth) +PlayerTarget::PlayerTarget(const QString &_name, int _maxWidth, Player *_owner) + : ArrowTarget(_owner, _owner), name(_name), maxWidth(_maxWidth) { font = QFont("Times"); font.setStyleHint(QFont::Serif); diff --git a/cockatrice/src/playertarget.h b/cockatrice/src/playertarget.h index ad9b9b52..b6eb9534 100644 --- a/cockatrice/src/playertarget.h +++ b/cockatrice/src/playertarget.h @@ -4,6 +4,8 @@ #include "arrowtarget.h" #include +class Player; + class PlayerTarget : public ArrowTarget { private: QString name; @@ -13,7 +15,7 @@ public: enum { Type = typePlayerTarget }; int type() const { return Type; } - PlayerTarget(const QString &_name, int _maxWidth, QGraphicsItem *parent = 0); + PlayerTarget(const QString &_name, int _maxWidth, Player *parent = 0); QRectF boundingRect() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); }; diff --git a/cockatrice/src/tab_game.cpp b/cockatrice/src/tab_game.cpp index ae352fbe..c588a96b 100644 --- a/cockatrice/src/tab_game.cpp +++ b/cockatrice/src/tab_game.cpp @@ -316,7 +316,8 @@ void TabGame::startGame() void TabGame::stopGame() { currentPhase = -1; - + activePlayer = -1; + playerListWidget->setActivePlayer(-1); playerListWidget->setGameStarted(false); started = false; @@ -365,6 +366,16 @@ void TabGame::eventGameStateChanged(Event_GameStateChanged *event, GameEventCont } } } + for (int i = 0; i < plList.size(); ++i) { + ServerInfo_Player *pl = plList[i]; + ServerInfo_PlayerProperties *prop = pl->getProperties(); + if (!prop->getSpectator()) { + Player *player = players.value(prop->getPlayerId(), 0); + if (!player) + continue; + player->processCardAttachment(pl); + } + } if (event->getGameStarted() && !started) { startGame(); if (!resuming) @@ -444,6 +455,7 @@ Player *TabGame::setActivePlayer(int id) Player *player = players.value(id, 0); if (!player) return 0; + activePlayer = id; playerListWidget->setActivePlayer(id); QMapIterator i(players); while (i.hasNext()) { @@ -547,3 +559,33 @@ void TabGame::sideboardPlanChanged() QList newPlan = deckView->getSideboardPlan(); client->sendCommand(new Command_SetSideboardPlan(gameId, newPlan)); } + +CardItem *TabGame::getCard(int playerId, const QString &zoneName, int cardId) const +{ + Player *player = players.value(playerId, 0); + if (!player) + return 0; + + CardZone *zone = player->getZones().value(zoneName, 0); + if (!zone) + return 0; + + return zone->getCard(cardId, QString()); +} + +Player *TabGame::getActiveLocalPlayer() const +{ + Player *active = players.value(activePlayer, 0); + if (active) + if (active->getLocal()) + return active; + + QMapIterator playerIterator(players); + while (playerIterator.hasNext()) { + Player *temp = playerIterator.next().value(); + if (temp->getLocal()) + return temp; + } + + return 0; +} diff --git a/cockatrice/src/tab_game.h b/cockatrice/src/tab_game.h index 24d33448..f09692aa 100644 --- a/cockatrice/src/tab_game.h +++ b/cockatrice/src/tab_game.h @@ -66,6 +66,7 @@ private: bool started; bool resuming; int currentPhase; + int activePlayer; QPushButton *loadLocalButton, *loadRemoteButton; ReadyStartButton *readyStartButton; @@ -123,11 +124,13 @@ public: ~TabGame(); void retranslateUi(); const QMap &getPlayers() const { return players; } + CardItem *getCard(int playerId, const QString &zoneName, int cardId) const; int getGameId() const { return gameId; } QString getTabText() const { return tr("Game %1: %2").arg(gameId).arg(gameDescription); } bool getSpectator() const { return spectator; } bool getSpectatorsCanTalk() const { return spectatorsCanTalk; } bool getSpectatorsSeeEverything() const { return spectatorsSeeEverything; } + Player *getActiveLocalPlayer() const; void processGameEventContainer(GameEventContainer *cont); public slots: diff --git a/cockatrice/src/tablezone.cpp b/cockatrice/src/tablezone.cpp index cba76b07..dc63259a 100644 --- a/cockatrice/src/tablezone.cpp +++ b/cockatrice/src/tablezone.cpp @@ -4,6 +4,7 @@ #include "client.h" #include "protocol_items.h" #include "settingscache.h" +#include "arrowitem.h" TableZone::TableZone(Player *_p, QGraphicsItem *parent) : CardZone(_p, "table", true, false, true, parent), active(false) @@ -91,17 +92,61 @@ void TableZone::handleDropEventByGrid(int cardId, CardZone *startZone, const QPo void TableZone::reorganizeCards() { + QList arrowsToUpdate; + + // Calculate table grid distortion so that the mapping functions work properly + gridPointWidth.clear(); for (int i = 0; i < cards.size(); ++i) { - QPointF mapPoint = mapFromGrid(cards[i]->getGridPos()); + QPoint gridPoint = cards[i]->getGridPos(); + if (gridPoint.x() == -1) + continue; + + gridPointWidth.insert(gridPoint.x() + gridPoint.y() * 1000, CARD_WIDTH * (1 + cards[i]->getAttachedCards().size() / 3.0)); + } + + for (int i = 0; i < cards.size(); ++i) { + QPoint gridPoint = cards[i]->getGridPos(); + if (gridPoint.x() == -1) + continue; + + QPointF mapPoint = mapFromGrid(gridPoint); qreal x = mapPoint.x(); qreal y = mapPoint.y(); if (player->getMirrored()) y = height - CARD_HEIGHT - y; - cards[i]->setPos(x, y); - cards[i]->setZValue((y + CARD_HEIGHT) * 10000000 + x + 1000); + + int numberAttachedCards = cards[i]->getAttachedCards().size(); + qreal actualX = x + numberAttachedCards * CARD_WIDTH / 3.0; + qreal actualY = y; + if (numberAttachedCards) + actualY += 5; + + cards[i]->setPos(actualX, actualY); + cards[i]->setZValue((actualY + CARD_HEIGHT) * 10000000 + (actualX + 1) * 10000); + + QListIterator attachedCardIterator(cards[i]->getAttachedCards()); + int j = 0; + while (attachedCardIterator.hasNext()) { + ++j; + CardItem *attachedCard = attachedCardIterator.next(); + qreal childX = actualX - j * CARD_WIDTH / 3.0; + qreal childY = y - 5; + attachedCard->setPos(childX, childY); + attachedCard->setZValue((childY + CARD_HEIGHT) * 10000000 + (childX + 1) * 10000); + + arrowsToUpdate.append(attachedCard->getArrowsFrom()); + arrowsToUpdate.append(attachedCard->getArrowsTo()); + } + + arrowsToUpdate.append(cards[i]->getArrowsFrom()); + arrowsToUpdate.append(cards[i]->getArrowsTo()); } + QSetIterator arrowIterator(QSet::fromList(arrowsToUpdate)); + while (arrowIterator.hasNext()) + arrowIterator.next()->updatePath(); + resizeToContents(); update(); } @@ -164,11 +209,16 @@ QPointF TableZone::mapFromGrid(const QPoint &gridPoint) const marginX + (CARD_WIDTH * gridPoint.x() + CARD_WIDTH * (gridPoint.x() / 3)) / 2, boxLineWidth + (CARD_HEIGHT + paddingY) * gridPoint.y() + (gridPoint.x() % 3 * CARD_HEIGHT) / 3 ); - else + else { + qreal x = marginX + 0.5 * CARD_WIDTH * gridPoint.x(); + for (int i = 0; i < gridPoint.x(); ++i) + x += gridPointWidth.value(gridPoint.y() * 1000 + i, CARD_WIDTH); + return QPointF( - marginX + 3 * CARD_WIDTH * gridPoint.x() / 2, + x, boxLineWidth + (CARD_HEIGHT + paddingY) * gridPoint.y() ); + } } QPoint TableZone::mapToGrid(const QPointF &mapPoint) const @@ -184,18 +234,22 @@ QPoint TableZone::mapToGrid(const QPointF &mapPoint) const else if (y > height - CARD_HEIGHT) y = height - CARD_HEIGHT; - QPoint result = QPoint( - (int) (x / (1.5 * CARD_WIDTH)), - (int) (y / (CARD_HEIGHT + paddingY)) - ); + int resultY = (int) (y / (CARD_HEIGHT + paddingY)); - if ((result.y() == 3) && (settingsCache->getEconomicGrid())) + if ((resultY == 3) && (settingsCache->getEconomicGrid())) return QPoint( (int) (x * 2 / CARD_WIDTH - floor(x / (2 * CARD_WIDTH))), 3 ); - else - return result; + else { + int resultX = -1; + qreal tempX = 0; + do { + ++resultX; + tempX += gridPointWidth.value(resultY * 1000 + resultX, CARD_WIDTH) + 0.5 * CARD_WIDTH; + } while (tempX < x + 1); + return QPoint(resultX, resultY); + } } QPointF TableZone::closestGridPoint(const QPointF &point) diff --git a/cockatrice/src/tablezone.h b/cockatrice/src/tablezone.h index 215d5f80..3bef1229 100644 --- a/cockatrice/src/tablezone.h +++ b/cockatrice/src/tablezone.h @@ -13,6 +13,7 @@ private: static const int marginX = 20; static const int minWidth = 20 * CARD_WIDTH / 2; + QMap gridPointWidth; int width, height; int currentMinimumWidth; QPixmap bgPixmap; diff --git a/cockatrice/translations/cockatrice_de.ts b/cockatrice/translations/cockatrice_de.ts index e8d56851..86bd809c 100644 --- a/cockatrice/translations/cockatrice_de.ts +++ b/cockatrice/translations/cockatrice_de.ts @@ -155,107 +155,112 @@ CardItem - + &Tap &Tappen - + &Untap E&nttappen - + Toggle &normal untapping N&ormales Enttappen umschalten - + &Flip &Umdrehen - + &Clone &Kopieren - + &Attach to card... &An Karte anlegen... - + + Ctrl+A + Ctrl+A + + + Unattac&h &Von Karte lösen - + Set &P/T... &Kampfwerte setzen... - + &Set annotation... &Hinweis setzen... - + red rot - + yellow gelb - + green grün - + &Add counter (%1) Zählmarke &hinzufügen (%1) - + &Remove counter (%1) Zählmarke &entfernen (%1) - + &Set counters (%1)... Zählmarken &setzen (%1)... - + &top of library &auf die Bibliothek - + &bottom of library &unter die Bibliothek - + &graveyard in den &Friedhof - + Ctrl+Del Ctrl+Del - + &exile ins &Exil - + &Move to &Verschieben @@ -263,112 +268,112 @@ CardZone - - + + his hand seine Hand - - + + %1's hand %1s Hand - + of his hand seiner Hand - + of %1's hand von %1s Hand - - + + his library seine Bibliothek - - + + %1's library %1s Bibliothek - + of his library seiner Bibliothek - + of %1's library von %1s Bibliothek - - + + his graveyard sein Friedhof - - + + %1's graveyard %1s Friedhof - + of his graveyard seines Friedhofs - + of %1's graveyard von %1s Friedhof - - + + his exile sein Exil - - + + %1's exile %1s Exil - + of his exile seines Exils - + of %1's exile von %1s Exil - - + + his sideboard sein Sideboard - - + + %1's sideboard %1s Sideboard - + of his sideboard seines Sideboards - + of %1's sideboard von %1s Sideboard @@ -1762,11 +1767,21 @@ + %1 attaches %2 to %3's %4. + %1 legt %2 an %3s %4 an. + + + + %1 unattaches %2. + %1 löst %2 ab. + + + %1 creates token: %2%3. %1 erstellt Token: %2%3. - + %1 points from %2's %3 to %4. %1 zeigt von %2s %3 auf %4. @@ -1775,12 +1790,12 @@ %1 erstellt einen Spielstein: %2 (%3). - + %1 points from %2's %3 to %4's %5. %1 zeigt von %2s %3 auf %4s %5. - + %1 places %n counter(s) (%2) on %3 (now %4). %1 legt eine Marke (%2) auf %3 (jetzt %4). @@ -1788,7 +1803,7 @@ - + %1 removes %n counter(s) (%2) from %3 (now %4). %1 entfernt eine Marke (%2) von %3 (jetzt %4). @@ -1796,37 +1811,37 @@ - + red rot - + yellow gelb - + green grün - + %1 sets counter %2 to %3 (%4%5). %1 setzt Zähler %2 auf %3 (%4%5). - + %1 sets PT of %2 to %3. %1 setzt Kampfwerte von %2 auf %3. - + %1 sets annotation of %2 to %3. %1 versieht %2 mit dem Hinweis %3. - + %1 is looking at the top %2 cards %3. %1 sieht sich die obersten %2 Karten %3 an. @@ -1923,7 +1938,7 @@ %1 entfernt %2 Zählmarken von %3 (jetzt %4). - + %1 %2 %3. %1 %2 %3. @@ -1936,17 +1951,17 @@ %1 sieht sich die obersten %2 Karten %3 an. - + %1 is looking at %2. %1 sieht sich %2 an. - + %1 stops looking at %2. %1 sieht sich %2 nicht mehr an. - + ending phase die Zugendphase @@ -1975,57 +1990,57 @@ %1 sieht sich %2s %3 nicht mehr an - + It is now %1's turn. %1 ist am Zug. - + untap step das Enttappsegment - + upkeep step das Versorgungssegment - + draw step das Ziehsegment - + first main phase die erste Hauptphase - + beginning of combat step das Anfangssegment der Kampfphase - + declare attackers step das Angreifer-Deklarieren-Segment - + declare blockers step das Blocker-Deklarieren-Segment - + combat damage step das Kampfschadenssegment - + end of combat step das Endsegment der Kampfphase - + second main phase die zweite Hauptphase @@ -2034,7 +2049,7 @@ das Ende-des-Zuges-Segment - + It is now the %1. Es ist nun %1. @@ -2043,12 +2058,12 @@ %1 bewegt %2 %3 nach %4 - + taps tappt - + untaps enttappt @@ -2073,7 +2088,7 @@ %1 entfernt %2 Zählmarken von %3 (jetzt %4) - + his permanents seine bleibenden Karten @@ -2086,12 +2101,12 @@ %1 setzt Zähler "%2" auf %3 (%4%5) - + %1 sets %2 to not untap normally. %1 setzt %2 auf explizites Enttappen. - + %1 sets %2 to untap normally. %1 setzt %2 auf normales Enttappen. @@ -2196,41 +2211,41 @@ Player - - - + + + Move to &top of library Oben auf die Biblio&thek legen - - - + + + Move to &bottom of library Unter die &Bibliothek legen - + &View library &Zeige Bibliothek - + F3 F3 - + View &top cards of library... Zeige die oberen Kar&ten der Bibliothek... - + &View graveyard &Zeige Friedhof - + F4 F4 @@ -2239,32 +2254,32 @@ Zeige ent&fernte Karten - + &View sideboard Zeige &Sideboard - + Player "%1" Spieler "%1" - + Take &mulligan &Mulligan nehmen - + &Hand &Hand - + &Library Bib&liothek - + &Graveyard &Friedhof @@ -2273,7 +2288,7 @@ Entfe&rnte Karten - + &Sideboard &Sideboard @@ -2286,65 +2301,65 @@ &Hinweis setzen... - + View top cards of library Zeige die obersten Karten der Bibliothek - + Number of cards: Anzahl der Karten: - + &Draw card Karte &ziehen - + &View exile &Zeige Exil - + &Exile &Exil - - + + Move to &hand auf die &Hand nehmen - - + + Move to g&raveyard auf den &Friedhof legen - - + + Move to &exile ins &Exil schicken - + Ctrl+W Ctrl+W - + Ctrl+D Ctrl+D - + D&raw cards... Ka&rten ziehen... - + Ctrl+E Ctrl+E @@ -2353,32 +2368,32 @@ &Mulligan nehmen... - + Ctrl+M Ctrl+M - + &Shuffle Mi&schen - + Ctrl+S Ctrl+S - + &Counters &Zähler - + &Untap all permanents &Enttappe alle bleibenden Karten - + Ctrl+U Ctrl+U @@ -2407,42 +2422,42 @@ Ctrl+L - + R&oll die... &Würfeln... - + Ctrl+I Ctrl+I - + &Create token... Spiels&tein erstellen... - + Ctrl+T Ctrl+T - + C&reate another token &Noch einen Spielstein erstellen - + Ctrl+G Ctrl+G - + S&ay S&agen - + C&ard &Karte @@ -2535,38 +2550,38 @@ F10 - + Draw cards Karten ziehen - - + + Number: Anzahl: - + Set power/toughness Kampfwerte setzen - + Please enter the new PT: Bitte die neuen Kampfwerte eingeben: - + Set annotation Hinweis setzen - + Please enter the new annotation: Bitte den Hinweis eingeben: - + Set counters Setze Zählmarken @@ -2579,12 +2594,12 @@ Neue Lebenspunkte insgesamt: - + Roll die Würfeln - + Number of sides: Anzahl der Seiten: @@ -2905,12 +2920,12 @@ Bitte geben Sie einen Namen ein: Sind Sie sicher, dass Sie das Spiel verlassen möchten? - + Load deck Deck laden - + Game %1: %2 Spiel %1: %2 diff --git a/cockatrice/translations/cockatrice_en.ts b/cockatrice/translations/cockatrice_en.ts index 56bc29d9..d9a69770 100644 --- a/cockatrice/translations/cockatrice_en.ts +++ b/cockatrice/translations/cockatrice_en.ts @@ -120,107 +120,112 @@ CardItem - + &Tap - + &Untap - + Toggle &normal untapping - + &Flip - + &Clone - + &Attach to card... - - Unattac&h - - - - - Set &P/T... - - - - - &Set annotation... - - - - - red - - - - - yellow - - - - - green - - - - - &Add counter (%1) + + Ctrl+A - &Remove counter (%1) + Unattac&h + + + + + Set &P/T... - &Set counters (%1)... - - - - - &top of library + &Set annotation... - &bottom of library + red - &graveyard + yellow + green + + + + + &Add counter (%1) + + + + + &Remove counter (%1) + + + + + &Set counters (%1)... + + + + + &top of library + + + + + &bottom of library + + + + + &graveyard + + + + Ctrl+Del - + &exile - + &Move to @@ -228,112 +233,112 @@ CardZone - - + + his hand - - + + %1's hand - + of his hand - + of %1's hand - - + + his library - - + + %1's library - + of his library - + of %1's library - - + + his graveyard - - + + %1's graveyard - + of his graveyard - + of %1's graveyard - - + + his exile - - + + %1's exile - + of his exile - + of %1's exile - - + + his sideboard - - + + %1's sideboard - + of his sideboard - + of %1's sideboard @@ -1166,12 +1171,22 @@ - + + %1 attaches %2 to %3's %4. + + + + + %1 unattaches %2. + + + + %1 points from %2's %3 to %4's %5. - + %1 places %n counter(s) (%2) on %3 (now %4). %1 places a counter (%2) on %3 (now %4). @@ -1179,7 +1194,7 @@ - + %1 removes %n counter(s) (%2) from %3 (now %4). %1 removes a counter (%2) from %3 (now %4). @@ -1187,37 +1202,37 @@ - + red - + yellow - + green - + %1 sets counter %2 to %3 (%4%5). - + %1 sets PT of %2 to %3. - + %1 sets annotation of %2 to %3. - + %1 is looking at the top %2 cards %3. @@ -1287,37 +1302,37 @@ - + %1 creates token: %2%3. - + %1 points from %2's %3 to %4. - + %1 %2 %3. - + %1 is looking at %2. - + %1 stops looking at %2. - + ending phase - + It is now %1's turn. @@ -1327,82 +1342,82 @@ - + untap step - + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + It is now the %1. - + taps - + untaps - + %1 sets %2 to not untap normally. - + %1 sets %2 to untap normally. - + his permanents @@ -1491,255 +1506,255 @@ Player - - - + + + Move to &top of library - - - + + + Move to &bottom of library - + &View library - + F3 - + View &top cards of library... - + &View graveyard - + F4 - + &View sideboard - + Player "%1" - + &Hand - + &Library - + &Graveyard - + &Sideboard - + View top cards of library - + Number of cards: - + &Draw card - + &View exile - + &Exile - - + + Move to &hand - - + + Move to g&raveyard - - + + Move to &exile - + Ctrl+W - + Ctrl+D - + D&raw cards... - + Ctrl+E - + Take &mulligan - + Ctrl+M - + &Shuffle - + Ctrl+S - + &Counters - + &Untap all permanents - + Ctrl+U - + R&oll die... - + Ctrl+I - + &Create token... - + Ctrl+T - + C&reate another token - + Ctrl+G - + S&ay - + C&ard - + Draw cards - - + + Number: - + Roll die - + Number of sides: - + Set power/toughness - + Please enter the new PT: - + Set annotation - + Please enter the new annotation: - + Set counters @@ -2027,12 +2042,12 @@ Please enter a name: - + Load deck - + Game %1: %2 diff --git a/common/protocol_datastructures.cpp b/common/protocol_datastructures.cpp index 30ca8ec1..0aa7575f 100644 --- a/common/protocol_datastructures.cpp +++ b/common/protocol_datastructures.cpp @@ -39,7 +39,7 @@ ServerInfo_CardCounter::ServerInfo_CardCounter(int _id, int _value) insertItem(new SerializableItem_Int("value", _value)); } -ServerInfo_Card::ServerInfo_Card(int _id, const QString &_name, int _x, int _y, bool _tapped, bool _attacking, const QString &_color, const QString &_pt, const QString &_annotation, bool _destroyOnZoneChange, const QList &_counters) +ServerInfo_Card::ServerInfo_Card(int _id, const QString &_name, int _x, int _y, bool _tapped, bool _attacking, const QString &_color, const QString &_pt, const QString &_annotation, bool _destroyOnZoneChange, const QList &_counters, int _attachPlayerId, const QString &_attachZone, int _attachCardId) : SerializableItem_Map("card") { insertItem(new SerializableItem_Int("id", _id)); @@ -52,6 +52,9 @@ ServerInfo_Card::ServerInfo_Card(int _id, const QString &_name, int _x, int _y, insertItem(new SerializableItem_String("pt", _pt)); insertItem(new SerializableItem_String("annotation", _annotation)); insertItem(new SerializableItem_Bool("destroy_on_zone_change", _destroyOnZoneChange)); + insertItem(new SerializableItem_Int("attach_player_id", _attachPlayerId)); + insertItem(new SerializableItem_String("attach_zone", _attachZone)); + insertItem(new SerializableItem_Int("attach_card_id", _attachCardId)); for (int i = 0; i < _counters.size(); ++i) itemList.append(_counters[i]); diff --git a/common/protocol_datastructures.h b/common/protocol_datastructures.h index 950b0275..147cc97e 100644 --- a/common/protocol_datastructures.h +++ b/common/protocol_datastructures.h @@ -62,7 +62,7 @@ public: class ServerInfo_Card : public SerializableItem_Map { public: - ServerInfo_Card(int _id = -1, const QString &_name = QString(), int _x = -1, int _y = -1, bool _tapped = false, bool _attacking = false, const QString &_color = QString(), const QString &_pt = QString(), const QString &_annotation = QString(), bool _destroyOnZoneChange = false, const QList &_counterList = QList()); + ServerInfo_Card(int _id = -1, const QString &_name = QString(), int _x = -1, int _y = -1, bool _tapped = false, bool _attacking = false, const QString &_color = QString(), const QString &_pt = QString(), const QString &_annotation = QString(), bool _destroyOnZoneChange = false, const QList &_counterList = QList(), int attachPlayerId = -1, const QString &_attachZone = QString(), int attachCardId = -1); static SerializableItem *newItem() { return new ServerInfo_Card; } int getId() const { return static_cast(itemMap.value("id"))->getData(); } QString getName() const { return static_cast(itemMap.value("name"))->getData(); } @@ -75,6 +75,9 @@ public: QString getAnnotation() const { return static_cast(itemMap.value("annotation"))->getData(); } bool getDestroyOnZoneChange() const { return static_cast(itemMap.value("destroy_on_zone_change"))->getData(); } QList getCounters() const { return typecastItemList(); } + int getAttachPlayerId() const { return static_cast(itemMap.value("attach_player_id"))->getData(); } + QString getAttachZone() const { return static_cast(itemMap.value("attach_zone"))->getData(); } + int getAttachCardId() const { return static_cast(itemMap.value("attach_card_id"))->getData(); } }; class ServerInfo_Zone : public SerializableItem_Map { diff --git a/common/server_card.cpp b/common/server_card.cpp index f627baa0..6c332b93 100644 --- a/common/server_card.cpp +++ b/common/server_card.cpp @@ -27,6 +27,12 @@ Server_Card::Server_Card(QString _name, int _id, int _coord_x, int _coord_y) Server_Card::~Server_Card() { + // setParentCard(0) leads to the item being removed from our list, so we can't iterate properly + while (!attachedCards.isEmpty()) + attachedCards.first()->setParentCard(0); + + if (parentCard) + parentCard->removeAttachedCard(this); } void Server_Card::resetState() @@ -74,3 +80,12 @@ void Server_Card::setCounter(int id, int value) else counters.remove(id); } + +void Server_Card::setParentCard(Server_Card *_parentCard) +{ + if (parentCard) + parentCard->removeAttachedCard(this); + parentCard = _parentCard; + if (parentCard) + parentCard->addAttachedCard(this); +} diff --git a/common/server_card.h b/common/server_card.h index 9db3f15a..0895b126 100644 --- a/common/server_card.h +++ b/common/server_card.h @@ -44,6 +44,7 @@ private: bool doesntUntap; Server_Card *parentCard; + QList attachedCards; public: Server_Card(QString _name, int _id, int _coord_x, int _coord_y); ~Server_Card(); @@ -66,6 +67,7 @@ public: bool getDoesntUntap() const { return doesntUntap; } bool getDestroyOnZoneChange() const { return destroyOnZoneChange; } Server_Card *getParentCard() const { return parentCard; } + const QList &getAttachedCards() const { return attachedCards; } void setId(int _id) { id = _id; } void setCoords(int x, int y) { coord_x = x; coord_y = y; } @@ -79,7 +81,9 @@ public: void setAnnotation(const QString &_annotation) { annotation = _annotation; } void setDestroyOnZoneChange(bool _destroy) { destroyOnZoneChange = _destroy; } void setDoesntUntap(bool _doesntUntap) { doesntUntap = _doesntUntap; } - void setParentCard(Server_Card *_parentCard) { parentCard = _parentCard; } + void setParentCard(Server_Card *_parentCard); + void addAttachedCard(Server_Card *card) { attachedCards.append(card); } + void removeAttachedCard(Server_Card *card) { attachedCards.removeAt(attachedCards.indexOf(card)); } void resetState(); bool setAttribute(const QString &aname, const QString &avalue, bool allCards); diff --git a/common/server_game.cpp b/common/server_game.cpp index 93dd54cc..85db1171 100644 --- a/common/server_game.cpp +++ b/common/server_game.cpp @@ -318,7 +318,15 @@ QList Server_Game::getGameState(Server_Player *playerWhosAs cardCounterList.append(new ServerInfo_CardCounter(cardCounterIterator.key(), cardCounterIterator.value())); } - cardList.append(new ServerInfo_Card(card->getId(), displayedName, card->getX(), card->getY(), card->getTapped(), card->getAttacking(), card->getColor(), card->getPT(), card->getAnnotation(), card->getDestroyOnZoneChange(), cardCounterList)); + int attachPlayerId = -1; + QString attachZone; + int attachCardId = -1; + if (card->getParentCard()) { + attachPlayerId = card->getParentCard()->getZone()->getPlayer()->getPlayerId(); + attachZone = card->getParentCard()->getZone()->getName(); + attachCardId = card->getParentCard()->getId(); + } + cardList.append(new ServerInfo_Card(card->getId(), displayedName, card->getX(), card->getY(), card->getTapped(), card->getAttacking(), card->getColor(), card->getPT(), card->getAnnotation(), card->getDestroyOnZoneChange(), cardCounterList, attachPlayerId, attachZone, attachCardId)); } } zoneList.append(new ServerInfo_Zone(zone->getName(), zone->getType(), zone->hasCoords(), zone->cards.size(), cardList)); diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index c4e62374..1df72ee4 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -517,6 +517,12 @@ ResponseCode Server_ProtocolHandler::moveCard(Server_Game *game, Server_Player * if (!card) return RespNameNotFound; + if (startzone != targetzone) { + const QList &attachedCards = card->getAttachedCards(); + for (int i = 0; i < attachedCards.size(); ++i) + unattachCard(game, attachedCards[i]->getZone()->getPlayer(), cont, attachedCards[i]); + } + if (card->getDestroyOnZoneChange() && (startzone != targetzone)) { cont->enqueueGameEventPrivate(new Event_DestroyCard(player->getPlayerId(), startzone->getName(), card->getId()), game->getGameId()); cont->enqueueGameEventPublic(new Event_DestroyCard(player->getPlayerId(), startzone->getName(), card->getId()), game->getGameId()); @@ -609,6 +615,17 @@ ResponseCode Server_ProtocolHandler::cmdMoveCard(Command_MoveCard *cmd, CommandC return moveCard(game, player, cont, cmd->getStartZone(), cmd->getCardId(), cmd->getTargetZone(), cmd->getX(), cmd->getY(), cmd->getFaceDown(), cmd->getTapped()); } +void Server_ProtocolHandler::unattachCard(Server_Game *game, Server_Player *player, CommandContainer *cont, Server_Card *card) +{ + Server_CardZone *zone = card->getZone(); + + card->setParentCard(0); + cont->enqueueGameEventPrivate(new Event_AttachCard(player->getPlayerId(), zone->getName(), card->getId(), -1, QString(), -1), game->getGameId()); + cont->enqueueGameEventPublic(new Event_AttachCard(player->getPlayerId(), zone->getName(), card->getId(), -1, QString(), -1), game->getGameId()); + + moveCard(game, player, cont, zone->getName(), card->getId(), zone->getName(), -1, card->getY(), card->getFaceDown(), card->getTapped()); +} + ResponseCode Server_ProtocolHandler::cmdAttachCard(Command_AttachCard *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player) { if (player->getSpectator()) @@ -625,21 +642,49 @@ ResponseCode Server_ProtocolHandler::cmdAttachCard(Command_AttachCard *cmd, Comm if (!card) return RespNameNotFound; - Server_Player *targetPlayer = game->getPlayer(cmd->getTargetPlayerId()); - if (!targetPlayer) - return RespNameNotFound; + int playerId = cmd->getTargetPlayerId(); + Server_Player *targetPlayer = 0; + Server_CardZone *targetzone = 0; + Server_Card *targetCard = 0; - Server_CardZone *targetzone = targetPlayer->getZones().value(cmd->getTargetZone()); - if (!targetzone) - return RespNameNotFound; + if (playerId != -1) { + targetPlayer = game->getPlayer(cmd->getTargetPlayerId()); + if (!targetPlayer) + return RespNameNotFound; + } else if (!card->getParentCard()) + return RespContextError; + if (targetPlayer) + targetzone = targetPlayer->getZones().value(cmd->getTargetZone()); + if (targetzone) + targetCard = targetzone->getCard(cmd->getTargetCardId(), false); + + // Get all arrows pointing to or originating from the card being attached and delete them. + QMapIterator playerIterator(game->getPlayers()); + while (playerIterator.hasNext()) { + Server_Player *p = playerIterator.next().value(); + QList arrows = p->getArrows().values(); + QList toDelete; + for (int i = 0; i < arrows.size(); ++i) { + Server_Arrow *a = arrows[i]; + Server_Card *tCard = qobject_cast(a->getTargetItem()); + if ((tCard == card) || (a->getStartCard() == card)) + toDelete.append(a); + } + for (int i = 0; i < toDelete.size(); ++i) { + cont->enqueueGameEventPrivate(new Event_DeleteArrow(p->getPlayerId(), toDelete[i]->getId()), game->getGameId()); + cont->enqueueGameEventPublic(new Event_DeleteArrow(p->getPlayerId(), toDelete[i]->getId()), game->getGameId()); + p->deleteArrow(toDelete[i]->getId()); + } + } - Server_Card *targetCard = targetzone->getCard(cmd->getTargetCardId(), false); - if (!targetCard) - return RespNameNotFound; + if (targetCard) { + card->setParentCard(targetCard); + card->setCoords(-1, card->getY()); + cont->enqueueGameEventPrivate(new Event_AttachCard(player->getPlayerId(), startzone->getName(), card->getId(), targetPlayer->getPlayerId(), targetzone->getName(), targetCard->getId()), game->getGameId()); + cont->enqueueGameEventPublic(new Event_AttachCard(player->getPlayerId(), startzone->getName(), card->getId(), targetPlayer->getPlayerId(), targetzone->getName(), targetCard->getId()), game->getGameId()); + } else + unattachCard(game, player, cont, card); - card->setParentCard(targetCard); - cont->enqueueGameEventPrivate(new Event_AttachCard(player->getPlayerId(), startzone->getName(), card->getId(), targetPlayer->getPlayerId(), targetzone->getName(), targetCard->getId()), game->getGameId()); - cont->enqueueGameEventPublic(new Event_AttachCard(player->getPlayerId(), startzone->getName(), card->getId(), targetPlayer->getPlayerId(), targetzone->getName(), targetCard->getId()), game->getGameId()); return RespOk; } @@ -956,7 +1001,17 @@ ResponseCode Server_ProtocolHandler::cmdDumpZone(Command_DumpZone *cmd, CommandC cardCounterIterator.next(); cardCounterList.append(new ServerInfo_CardCounter(cardCounterIterator.key(), cardCounterIterator.value())); } - respCardList.append(new ServerInfo_Card(card->getId(), displayedName, card->getX(), card->getY(), card->getTapped(), card->getAttacking(), card->getColor(), card->getPT(), card->getAnnotation(), card->getDestroyOnZoneChange(), cardCounterList)); + + int attachPlayerId = -1; + QString attachZone; + int attachCardId = -1; + if (card->getParentCard()) { + attachPlayerId = card->getParentCard()->getZone()->getPlayer()->getPlayerId(); + attachZone = card->getParentCard()->getZone()->getName(); + attachCardId = card->getParentCard()->getId(); + } + + respCardList.append(new ServerInfo_Card(card->getId(), displayedName, card->getX(), card->getY(), card->getTapped(), card->getAttacking(), card->getColor(), card->getPT(), card->getAnnotation(), card->getDestroyOnZoneChange(), cardCounterList, attachPlayerId, attachZone, attachCardId)); } } if (zone->getType() == HiddenZone) { diff --git a/common/server_protocolhandler.h b/common/server_protocolhandler.h index 74704b1b..725920b0 100644 --- a/common/server_protocolhandler.h +++ b/common/server_protocolhandler.h @@ -8,6 +8,7 @@ #include "protocol_items.h" class Server_Player; +class Server_Card; class QTimer; class Server_ProtocolHandler : public QObject { @@ -61,6 +62,7 @@ private: ResponseCode cmdDrawCards(Command_DrawCards *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player); ResponseCode moveCard(Server_Game *game, Server_Player *player, CommandContainer *cont, const QString &_startZone, int _cardId, const QString &_targetZone, int _x, int _y, bool _faceDown, bool _tapped); ResponseCode cmdMoveCard(Command_MoveCard *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player); + void unattachCard(Server_Game *game, Server_Player *player, CommandContainer *cont, Server_Card *card); ResponseCode cmdAttachCard(Command_AttachCard *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player); ResponseCode cmdCreateToken(Command_CreateToken *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player); ResponseCode cmdCreateArrow(Command_CreateArrow *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player); diff --git a/oracle/sets.xml b/oracle/sets.xml index db13d023..3da1df34 100644 --- a/oracle/sets.xml +++ b/oracle/sets.xml @@ -130,6 +130,10 @@ M10 Magic 2010 + + M11 + Magic 2011 + MM Mercadian Masques