diff --git a/cockatrice/cockatrice.pro b/cockatrice/cockatrice.pro index 5c222ee9..1de17096 100644 --- a/cockatrice/cockatrice.pro +++ b/cockatrice/cockatrice.pro @@ -40,7 +40,8 @@ HEADERS += src/counter.h \ src/dlg_settings.h \ src/phasestoolbar.h \ src/chatwidget.h \ - src/gamescene.h + src/gamescene.h \ + src/arrowitem.h SOURCES += src/counter.cpp \ src/gameselector.cpp \ src/dlg_creategame.cpp \ @@ -76,6 +77,7 @@ SOURCES += src/counter.cpp \ src/dlg_settings.cpp \ src/phasestoolbar.cpp \ src/chatwidget.cpp \ - src/gamescene.cpp + src/gamescene.cpp \ + src/arrowitem.cpp TRANSLATIONS += translations/cockatrice_de.ts translations/cockatrice_en.ts CONFIG += qt debug diff --git a/cockatrice/src/arrowitem.cpp b/cockatrice/src/arrowitem.cpp new file mode 100644 index 00000000..7ab664b6 --- /dev/null +++ b/cockatrice/src/arrowitem.cpp @@ -0,0 +1,95 @@ +#include "arrowitem.h" +#include "carditem.h" +#include "cardzone.h" +#include "player.h" +#include "math.h" +#include +#include +#include + +ArrowItem::ArrowItem(CardItem *_startItem, CardItem *_targetItem) + : QGraphicsItem(), startItem(_startItem), targetItem(_targetItem) +{ + setZValue(2000000005); + if (startItem && targetItem) + updatePath(); +} + +void ArrowItem::updatePath() +{ + color = QColor(255, 0, 0, 200); + QPointF endPoint = targetItem->mapToScene(QPointF(targetItem->boundingRect().width() / 2, targetItem->boundingRect().height() / 2)); + updatePath(endPoint); +} + +void ArrowItem::updatePath(const QPointF &endPoint) +{ + const double arrowWidth = 15.0; + const double headWidth = 40.0; + const double headLength = headWidth / sqrt(2); + + QPointF startPoint = startItem->mapToScene(QPointF(startItem->boundingRect().width() / 2, startItem->boundingRect().height() / 2)); + QLineF line(startPoint, endPoint); + qreal lineLength = line.length(); + + path = QPainterPath(QPointF(0, -arrowWidth / 2)); + path.lineTo(0, arrowWidth / 2); + path.lineTo(lineLength - headLength, arrowWidth / 2); + path.lineTo(lineLength - headLength, headWidth / 2); + path.lineTo(lineLength, 0); + path.lineTo(lineLength - headLength, -headWidth / 2); + path.lineTo(lineLength - headLength, -arrowWidth / 2); + path.lineTo(0, -arrowWidth / 2); + + setPos(startPoint); + setTransform(QTransform().rotate(-line.angle())); +} + +void ArrowItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/) +{ + painter->setBrush(color); + painter->drawPath(path); +} + +ArrowDragItem::ArrowDragItem(CardItem *_startItem) + : ArrowItem(_startItem) +{ +} + +void ArrowDragItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + event->accept(); + QPointF endPos = event->scenePos(); + + QList colliding = scene()->items(endPos); + CardItem *cursorItem = 0; + for (int i = colliding.size() - 1; i >= 0; i--) + if ((cursorItem = qgraphicsitem_cast(colliding.at(i)))) + break; + if (!cursorItem) { + targetItem = 0; + updatePath(endPos); + color = QColor(190, 0, 0, 150); + } else { + targetItem = cursorItem; + updatePath(); + } + update(); +} + +void ArrowDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent * /*event*/) +{ + if (targetItem) { + CardZone *startZone = static_cast(startItem->parentItem()); + CardZone *targetZone = static_cast(targetItem->parentItem()); + startZone->getPlayer()->client->createArrow( + startZone->getPlayer()->getId(), + startZone->getName(), + startItem->getId(), + targetZone->getPlayer()->getId(), + targetZone->getName(), + targetItem->getId() + ); + } + deleteLater(); +} diff --git a/cockatrice/src/arrowitem.h b/cockatrice/src/arrowitem.h new file mode 100644 index 00000000..1d8a054e --- /dev/null +++ b/cockatrice/src/arrowitem.h @@ -0,0 +1,33 @@ +#ifndef ARROWITEM_H +#define ARROWITEM_H + +#include + +class CardItem; +class QGraphicsSceneMouseEvent; + +class ArrowItem : public QObject, public QGraphicsItem { + Q_OBJECT +private: + QPainterPath path; +protected: + QColor color; + CardItem *startItem, *targetItem; +public: + ArrowItem(CardItem *_startItem = 0, CardItem *_targetItem = 0); + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + QRectF boundingRect() const { return path.boundingRect(); } + void updatePath(); + void updatePath(const QPointF &endPoint); +}; + +class ArrowDragItem : public ArrowItem { + Q_OBJECT +public: + ArrowDragItem(CardItem *_startItem); +protected: + void mouseMoveEvent(QGraphicsSceneMouseEvent *event); + void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); +}; + +#endif // ARROWITEM_H diff --git a/cockatrice/src/carditem.cpp b/cockatrice/src/carditem.cpp index 48415bb7..0cc2d6c2 100644 --- a/cockatrice/src/carditem.cpp +++ b/cockatrice/src/carditem.cpp @@ -7,6 +7,7 @@ #include "tablezone.h" #include "player.h" #include "game.h" +#include "arrowitem.h" CardItem::CardItem(CardDatabase *_db, const QString &_name, int _cardid, QGraphicsItem *parent) : AbstractGraphicsItem(parent), db(_db), info(db->getCard(_name)), name(_name), id(_cardid), tapped(false), attacking(false), facedown(false), counters(0), doesntUntap(false), dragItem(NULL) @@ -193,46 +194,53 @@ void CardItem::mousePressEvent(QGraphicsSceneMouseEvent *event) scene()->clearSelection(); setSelected(true); } - if (event->button() == Qt::LeftButton) { + if (event->button() == Qt::LeftButton) setCursor(Qt::ClosedHandCursor); - } else if (event->button() == Qt::RightButton) { - qgraphicsitem_cast(parentItem())->getPlayer()->showCardMenu(event->screenPos()); - } event->accept(); } void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { - if ((event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() < QApplication::startDragDistance()) - return; - bool faceDown = event->modifiers().testFlag(Qt::ShiftModifier) || facedown; - - createDragItem(id, event->pos(), event->scenePos(), faceDown); - dragItem->grabMouse(); + if (event->buttons().testFlag(Qt::RightButton)) { + if ((event->screenPos() - event->buttonDownScreenPos(Qt::RightButton)).manhattanLength() < 2 * QApplication::startDragDistance()) + return; + ArrowDragItem *arrow = new ArrowDragItem(this); + scene()->addItem(arrow); + arrow->grabMouse(); + } else { + if ((event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() < 2 * QApplication::startDragDistance()) + return; + bool faceDown = event->modifiers().testFlag(Qt::ShiftModifier) || facedown; - CardZone *zone = (CardZone *) parentItem(); - - QList sel = scene()->selectedItems(); - int j = 0; - for (int i = 0; i < sel.size(); i++) { - CardItem *c = (CardItem *) sel.at(i); - if (c == this) - continue; - ++j; - QPointF childPos; - if (zone->getHasCardAttr()) - childPos = c->pos() - pos(); - else - childPos = QPointF(j * CARD_WIDTH / 2, 0); - CardDragItem *drag = new CardDragItem(c, c->getId(), childPos, false, dragItem); - drag->setPos(dragItem->pos() + childPos); - scene()->addItem(drag); + createDragItem(id, event->pos(), event->scenePos(), faceDown); + dragItem->grabMouse(); + + CardZone *zone = (CardZone *) parentItem(); + + QList sel = scene()->selectedItems(); + int j = 0; + for (int i = 0; i < sel.size(); i++) { + CardItem *c = (CardItem *) sel.at(i); + if (c == this) + continue; + ++j; + QPointF childPos; + if (zone->getHasCardAttr()) + childPos = c->pos() - pos(); + else + childPos = QPointF(j * CARD_WIDTH / 2, 0); + CardDragItem *drag = new CardDragItem(c, c->getId(), childPos, false, dragItem); + drag->setPos(dragItem->pos() + childPos); + scene()->addItem(drag); + } } setCursor(Qt::OpenHandCursor); } -void CardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent */*event*/) +void CardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { + if (event->button() == Qt::RightButton) + qgraphicsitem_cast(parentItem())->getPlayer()->showCardMenu(event->screenPos()); setCursor(Qt::OpenHandCursor); } diff --git a/cockatrice/src/client.cpp b/cockatrice/src/client.cpp index f470160f..3b751c70 100644 --- a/cockatrice/src/client.cpp +++ b/cockatrice/src/client.cpp @@ -22,6 +22,7 @@ ServerEventData::ServerEventData(const QString &line) eventHash.insert("draw", eventDraw); eventHash.insert("move_card", eventMoveCard); eventHash.insert("create_token", eventCreateToken); + eventHash.insert("create_arrow", eventCreateArrow); eventHash.insert("set_card_attr", eventSetCardAttr); eventHash.insert("add_counter", eventAddCounter); eventHash.insert("set_counter", eventSetCounter); @@ -497,6 +498,11 @@ PendingCommand *Client::createToken(const QString &zone, const QString &name, co return cmd(QString("create_token|%1|%2|%3|%4|%5").arg(zone).arg(name).arg(powtough).arg(x).arg(y)); } +PendingCommand *Client::createArrow(int startPlayerId, const QString &startZone, int startCardId, int targetPlayerId, const QString &targetPlayerZone, int targetCardId) +{ + return cmd(QString("create_arrow|%1|%2|%3|%4|%5|%6").arg(startPlayerId).arg(startZone).arg(startCardId).arg(targetPlayerId).arg(targetPlayerZone).arg(targetCardId)); +} + PendingCommand *Client::setCardAttr(const QString &zone, int cardid, const QString &aname, const QString &avalue) { return cmd(QString("set_card_attr|%1|%2|%3|%4").arg(zone).arg(cardid).arg(aname).arg(avalue)); diff --git a/cockatrice/src/client.h b/cockatrice/src/client.h index 853dc2a2..4883d57d 100644 --- a/cockatrice/src/client.h +++ b/cockatrice/src/client.h @@ -44,6 +44,7 @@ enum ServerEventType { eventDraw, eventMoveCard, eventCreateToken, + eventCreateArrow, eventSetCardAttr, eventAddCounter, eventSetCounter, @@ -325,7 +326,7 @@ private slots: void enterGameResponse(ServerResponse response); void leaveGameResponse(ServerResponse response); private: - static const int protocolVersion = 1; + static const int protocolVersion = 2; static const int maxTimeout = 10; QTimer *timer; @@ -363,6 +364,7 @@ public slots: PendingCommand *drawCards(unsigned int number); PendingCommand *moveCard(int cardid, const QString &startzone, const QString &targetzone, int x, int y = 0, bool faceDown = false); PendingCommand *createToken(const QString &zone, const QString &name, const QString &powtough, int x, int y); + PendingCommand *createArrow(int startPlayerId, const QString &startZone, int startCardId, int targetPlayerId, const QString &targetPlayerZone, int targetCardId); PendingCommand *setCardAttr(const QString &zone, int cardid, const QString &aname, const QString &avalue); PendingCommand *readyStart(); PendingCommand *incCounter(int counterId, int delta); diff --git a/cockatrice/src/game.cpp b/cockatrice/src/game.cpp index 6af95afd..9f3cbc6e 100644 --- a/cockatrice/src/game.cpp +++ b/cockatrice/src/game.cpp @@ -12,6 +12,7 @@ #include "counter.h" #include "gamescene.h" #include "player.h" +#include "arrowitem.h" Game::Game(CardDatabase *_db, Client *_client, GameScene *_scene, QMenuBar *menuBar, QObject *parent) : QObject(parent), db(_db), client(_client), scene(_scene), started(false), currentPhase(-1) @@ -320,7 +321,26 @@ void Game::gameEvent(const ServerEventData &msg) } break; } - + case eventCreateArrow: { + const QStringList &data = msg.getEventData(); + Player *startPlayer = players.value(data[0].toInt(), 0); + Player *targetPlayer = players.value(data[3].toInt(), 0); + if (!startPlayer || !targetPlayer) + break; + CardZone *startZone = startPlayer->getZones().value(data[1], 0); + CardZone *targetZone = targetPlayer->getZones().value(data[4], 0); + if (!startZone || !targetZone) + break; + CardItem *startCard = startZone->getCard(data[2].toInt(), QString()); + CardItem *targetCard = targetZone->getCard(data[5].toInt(), QString()); + if (!startCard || !targetCard) + break; + + emit logCreateArrow(p, startPlayer, startCard->getName(), targetPlayer, targetCard->getName()); + ArrowItem *arrow = new ArrowItem(startCard, targetCard); + scene->addItem(arrow); + break; + } case eventCreateToken: case eventSetupZones: case eventSetCardAttr: diff --git a/cockatrice/src/game.h b/cockatrice/src/game.h index c7dab5bb..07d7544c 100644 --- a/cockatrice/src/game.h +++ b/cockatrice/src/game.h @@ -91,6 +91,7 @@ signals: void logDraw(Player *player, int number); void logMoveCard(Player *player, QString cardName, CardZone *startZone, int oldX, CardZone *targetZone, int newX); void logCreateToken(Player *player, QString cardName); + void logCreateArrow(Player *player, Player *startPlayer, QString startCard, Player *targetPlayer, QString targetCard); void logSetCardCounters(Player *player, QString cardName, int value, int oldValue); void logSetTapped(Player *player, QString cardName, bool tapped); void logSetCounter(Player *player, QString counterName, int value, int oldValue); diff --git a/cockatrice/src/messagelogwidget.cpp b/cockatrice/src/messagelogwidget.cpp index 87bd88df..0555dc48 100644 --- a/cockatrice/src/messagelogwidget.cpp +++ b/cockatrice/src/messagelogwidget.cpp @@ -189,6 +189,17 @@ void MessageLogWidget::logCreateToken(Player *player, QString cardName) append(tr("%1 creates token: %2.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName)))); } +void MessageLogWidget::logCreateArrow(Player *player, Player *startPlayer, QString startCard, Player *targetPlayer, QString targetCard) +{ + append(tr("%1 points from %2's %3 to %4's %5.") + .arg(sanitizeHtml(player->getName())) + .arg(sanitizeHtml(startPlayer->getName())) + .arg(sanitizeHtml(startCard)) + .arg(sanitizeHtml(targetPlayer->getName())) + .arg(sanitizeHtml(targetCard)) + ); +} + void MessageLogWidget::logSetCardCounters(Player *player, QString cardName, int value, int oldValue) { QString finalStr; @@ -280,6 +291,7 @@ void MessageLogWidget::connectToGame(Game *game) connect(game, SIGNAL(logDraw(Player *, int)), this, SLOT(logDraw(Player *, int))); connect(game, SIGNAL(logMoveCard(Player *, QString, CardZone *, int, CardZone *, int)), this, SLOT(logMoveCard(Player *, QString, CardZone *, int, CardZone *, int))); connect(game, SIGNAL(logCreateToken(Player *, QString)), this, SLOT(logCreateToken(Player *, QString))); + connect(game, SIGNAL(logCreateArrow(Player *, Player *, QString, Player *, QString)), this, SLOT(logCreateArrow(Player *, Player *, QString, Player *, QString))); connect(game, SIGNAL(logSetCardCounters(Player *, QString, int, int)), this, SLOT(logSetCardCounters(Player *, QString, int, int))); connect(game, SIGNAL(logSetTapped(Player *, QString, bool)), this, SLOT(logSetTapped(Player *, QString, bool))); connect(game, SIGNAL(logSetCounter(Player *, QString, int, int)), this, SLOT(logSetCounter(Player *, QString, int, int))); diff --git a/cockatrice/src/messagelogwidget.h b/cockatrice/src/messagelogwidget.h index 507ae575..200c499a 100644 --- a/cockatrice/src/messagelogwidget.h +++ b/cockatrice/src/messagelogwidget.h @@ -38,6 +38,7 @@ private slots: void logDraw(Player *player, int number); void logMoveCard(Player *player, QString cardName, CardZone *startZone, int oldX, CardZone *targetZone, int newX); void logCreateToken(Player *player, QString cardName); + void logCreateArrow(Player *player, Player *startPlayer, QString startCard, Player *targetPlayer, QString targetCard); void logSetCardCounters(Player *player, QString cardName, int value, int oldValue); void logSetTapped(Player *player, QString cardName, bool tapped); void logSetCounter(Player *player, QString counterName, int value, int oldValue); diff --git a/cockatrice/src/window_main.cpp b/cockatrice/src/window_main.cpp index 3e78a110..c85bacfc 100644 --- a/cockatrice/src/window_main.cpp +++ b/cockatrice/src/window_main.cpp @@ -55,8 +55,7 @@ void PingWidget::paintEvent(QPaintEvent */*event*/) QRadialGradient g(QPointF((double) width() / 2, (double) height() / 2), qMin(width(), height()) / 2.0); g.setColorAt(0, color); g.setColorAt(1, Qt::transparent); - painter.setBrush(QBrush(g)); - painter.setPen(Qt::black); + painter.fillRect(0, 0, width(), height(), QBrush(g)); } void PingWidget::setPercentage(int value, int max) diff --git a/servatrice/src/serversocket.cpp b/servatrice/src/serversocket.cpp index 3f27b741..5fd01153 100644 --- a/servatrice/src/serversocket.cpp +++ b/servatrice/src/serversocket.cpp @@ -83,6 +83,13 @@ ServerSocket::ServerSocket(Server *_server, QObject *parent) << QVariant::String << QVariant::Int << QVariant::Int, &ServerSocket::cmdCreateToken)); + commandHash.insert("create_arrow", CommandProperties(true, true, true, false, QList() + << QVariant::Int + << QVariant::String + << QVariant::Int + << QVariant::Int + << QVariant::String + << QVariant::Int, &ServerSocket::cmdCreateArrow)); commandHash.insert("set_card_attr", CommandProperties(true, true, true, false, QList() << QVariant::String << QVariant::Int @@ -562,6 +569,32 @@ ReturnMessage::ReturnCode ServerSocket::cmdCreateToken(const QList &pa return ReturnMessage::ReturnOk; } +ReturnMessage::ReturnCode ServerSocket::cmdCreateArrow(const QList ¶ms) +{ + ServerSocket *startPlayer = game->getPlayer(params[0].toInt()); + ServerSocket *targetPlayer = game->getPlayer(params[3].toInt()); + if (!startPlayer || !targetPlayer) + return ReturnMessage::ReturnContextError; + PlayerZone *startZone = startPlayer->getZone(params[1].toString()); + PlayerZone *targetZone = targetPlayer->getZone(params[4].toString()); + if (!startZone || !targetZone) + return ReturnMessage::ReturnContextError; + Card *startCard = startZone->getCard(params[2].toInt(), false); + Card *targetCard = targetZone->getCard(params[5].toInt(), false); + if (!startCard || !targetCard) + return ReturnMessage::ReturnContextError; + + emit broadcastEvent(QString("create_arrow|%1|%2|%3|%4|%5|%6") + .arg(startPlayer->getPlayerId()) + .arg(startZone->getName()) + .arg(startCard->getId()) + .arg(targetPlayer->getPlayerId()) + .arg(targetZone->getName()) + .arg(targetCard->getId()), this + ); + return ReturnMessage::ReturnOk; +} + ReturnMessage::ReturnCode ServerSocket::cmdSetCardAttr(const QList ¶ms) { // zone, card id, attr name, attr value diff --git a/servatrice/src/serversocket.h b/servatrice/src/serversocket.h index d427121c..36ef233e 100644 --- a/servatrice/src/serversocket.h +++ b/servatrice/src/serversocket.h @@ -90,6 +90,7 @@ private: ReturnMessage::ReturnCode cmdRevealCard(const QList ¶ms); ReturnMessage::ReturnCode cmdMoveCard(const QList ¶ms); ReturnMessage::ReturnCode cmdCreateToken(const QList ¶ms); + ReturnMessage::ReturnCode cmdCreateArrow(const QList ¶ms); ReturnMessage::ReturnCode cmdSetCardAttr(const QList ¶ms); ReturnMessage::ReturnCode cmdIncCounter(const QList ¶ms); ReturnMessage::ReturnCode cmdAddCounter(const QList ¶ms); diff --git a/servatrice/src/version.h b/servatrice/src/version.h index 2c3cba09..65088a48 100644 --- a/servatrice/src/version.h +++ b/servatrice/src/version.h @@ -18,5 +18,5 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ -static const int PROTOCOL_VERSION = 1; -static const char *VERSION_STRING = "Servatrice 0.20090928"; +static const int PROTOCOL_VERSION = 2; +static const char *VERSION_STRING = "Servatrice 0.20091017";