servatrice/cockatrice/src/game.cpp
2009-08-12 19:27:41 +02:00

413 lines
12 KiB
C++

#include <QGraphicsScene>
#include <QMenu>
#include <QMessageBox>
#include <QSettings>
#include "serverplayer.h"
#include "game.h"
#include "servereventdata.h"
#include "client.h"
#include "tablezone.h"
#include "handzone.h"
#include "carddatabase.h"
#include "dlg_startgame.h"
#include "playerarea.h"
#include "counter.h"
Game::Game(CardDatabase *_db, Client *_client, QGraphicsScene *_scene, QMenu *_actionsMenu, QMenu *_cardMenu, int playerId, const QString &playerName, QObject *parent)
: QObject(parent), actionsMenu(_actionsMenu), cardMenu(_cardMenu), db(_db), client(_client), scene(_scene), started(false)
{
QRectF sr = scene->sceneRect();
localPlayer = addPlayer(playerId, playerName, QPointF(0, sr.y() + sr.height() / 2 + 2), true);
connect(client, SIGNAL(gameEvent(const ServerEventData &)), this, SLOT(gameEvent(const ServerEventData &)));
connect(client, SIGNAL(playerListReceived(QList<ServerPlayer *>)), this, SLOT(playerListReceived(QList<ServerPlayer *>)));
aUntapAll = new QAction(tr("&Untap all permanents"), this);
aUntapAll->setShortcut(tr("Ctrl+U"));
connect(aUntapAll, SIGNAL(triggered()), this, SLOT(actUntapAll()));
aDecLife = new QAction(tr("&Decrement life"), this);
aDecLife->setShortcut(tr("F11"));
connect(aDecLife, SIGNAL(triggered()), this, SLOT(actDecLife()));
aIncLife = new QAction(tr("&Increment life"), this);
aIncLife->setShortcut(tr("F12"));
connect(aIncLife, SIGNAL(triggered()), this, SLOT(actIncLife()));
aSetLife = new QAction(tr("&Set life"), this);
aSetLife->setShortcut(tr("Ctrl+L"));
connect(aSetLife, SIGNAL(triggered()), this, SLOT(actSetLife()));
aShuffle = new QAction(tr("&Shuffle"), this);
aShuffle->setShortcut(tr("Ctrl+S"));
connect(aShuffle, SIGNAL(triggered()), this, SLOT(actShuffle()));
aDraw = new QAction(tr("&Draw a card"), this);
aDraw->setShortcut(tr("Ctrl+D"));
connect(aDraw, SIGNAL(triggered()), this, SLOT(actDrawCard()));
aDrawCards = new QAction(tr("D&raw cards..."), this);
connect(aDrawCards, SIGNAL(triggered()), this, SLOT(actDrawCards()));
aDrawCards->setShortcut(tr("Ctrl+E"));
aRollDice = new QAction(tr("R&oll dice..."), this);
aRollDice->setShortcut(tr("Ctrl+I"));
connect(aRollDice, SIGNAL(triggered()), this, SLOT(actRollDice()));
aCreateToken = new QAction(tr("&Create token..."), this);
aCreateToken->setShortcut(tr("Ctrl+T"));
connect(aCreateToken, SIGNAL(triggered()), this, SLOT(actCreateToken()));
actionsMenu->addAction(aUntapAll);
actionsMenu->addSeparator();
actionsMenu->addAction(aDecLife);
actionsMenu->addAction(aIncLife);
actionsMenu->addAction(aSetLife);
actionsMenu->addSeparator();
actionsMenu->addAction(aShuffle);
actionsMenu->addAction(aDraw);
actionsMenu->addAction(aDrawCards);
actionsMenu->addAction(aRollDice);
actionsMenu->addSeparator();
actionsMenu->addAction(aCreateToken);
actionsMenu->addSeparator();
sayMenu = actionsMenu->addMenu(tr("S&ay"));
initSayMenu();
aTap = new QAction(tr("&Tap"), this);
connect(aTap, SIGNAL(triggered()), this, SLOT(actTap()));
aUntap = new QAction(tr("&Untap"), this);
connect(aUntap, SIGNAL(triggered()), this, SLOT(actUntap()));
aDoesntUntap = new QAction(tr("Toggle &normal untapping"), this);
connect(aDoesntUntap, SIGNAL(triggered()), this, SLOT(actDoesntUntap()));
aFlip = new QAction(tr("&Flip"), this);
connect(aFlip, SIGNAL(triggered()), this, SLOT(actFlip()));
aAddCounter = new QAction(tr("&Add counter"), this);
connect(aAddCounter, SIGNAL(triggered()), this, SLOT(actAddCounter()));
aRemoveCounter = new QAction(tr("&Remove counter"), this);
connect(aRemoveCounter, SIGNAL(triggered()), this, SLOT(actRemoveCounter()));
aSetCounters = new QAction(tr("&Set counters..."), this);
connect(aSetCounters, SIGNAL(triggered()), this, SLOT(actSetCounters()));
cardMenu->addAction(aTap);
cardMenu->addAction(aUntap);
cardMenu->addAction(aDoesntUntap);
cardMenu->addSeparator();
cardMenu->addAction(aFlip);
cardMenu->addSeparator();
cardMenu->addAction(aAddCounter);
cardMenu->addAction(aRemoveCounter);
cardMenu->addAction(aSetCounters);
dlgStartGame = new DlgStartGame(db);
connect(dlgStartGame, SIGNAL(newDeckLoaded(const QStringList &)), client, SLOT(submitDeck(const QStringList &)));
connect(dlgStartGame, SIGNAL(finished(int)), this, SLOT(readyStart()));
}
Game::~Game()
{
qDebug("Game destructor");
for (int i = 0; i < players.size(); i++) {
emit playerRemoved(players.at(i));
delete players.at(i);
}
}
void Game::initSayMenu()
{
sayMenu->clear();
QSettings settings;
settings.beginGroup("messages");
int count = settings.value("count", 0).toInt();
for (int i = 0; i < count; i++) {
QAction *newAction = new QAction(settings.value(QString("msg%1").arg(i)).toString(), this);
QString shortcut;
switch (i) {
case 0: shortcut = tr("F5"); break;
case 1: shortcut = tr("F6"); break;
case 2: shortcut = tr("F7"); break;
case 3: shortcut = tr("F8"); break;
case 4: shortcut = tr("F9"); break;
case 5: shortcut = tr("F10"); break;
}
newAction->setShortcut(shortcut);
connect(newAction, SIGNAL(triggered()), this, SLOT(actSayMessage()));
sayMenu->addAction(newAction);
}
}
Player *Game::addPlayer(int playerId, const QString &playerName, QPointF base, bool local)
{
Player *newPlayer = new Player(playerName, playerId, base, local, db, client, scene, this);
connect(newPlayer, SIGNAL(sigShowCardMenu(QPoint)), this, SLOT(showCardMenu(QPoint)));
connect(newPlayer, SIGNAL(logMoveCard(Player *, QString, CardZone *, int, CardZone *, int)), this, SIGNAL(logMoveCard(Player *, QString, CardZone *, int, CardZone *, int)));
connect(newPlayer, SIGNAL(logCreateToken(Player *, QString)), this, SIGNAL(logCreateToken(Player *, QString)));
connect(newPlayer, SIGNAL(logSetCardCounters(Player *, QString, int, int)), this, SIGNAL(logSetCardCounters(Player *, QString, int, int)));
connect(newPlayer, SIGNAL(logSetTapped(Player *, QString, bool)), this, SIGNAL(logSetTapped(Player *, QString, bool)));
connect(newPlayer, SIGNAL(logSetCounter(Player *, QString, int, int)), this, SIGNAL(logSetCounter(Player *, QString, int, int)));
connect(newPlayer, SIGNAL(logSetDoesntUntap(Player *, QString, bool)), this, SIGNAL(logSetDoesntUntap(Player *, QString, bool)));
players << newPlayer;
emit playerAdded(newPlayer);
return newPlayer;
}
void Game::playerListReceived(QList<ServerPlayer *> playerList)
{
QListIterator<ServerPlayer *> i(playerList);
QStringList nameList;
while (i.hasNext()) {
ServerPlayer *temp = i.next();
nameList << temp->getName();
int id = temp->getPlayerId();
if (id != localPlayer->getId())
addPlayer(id, temp->getName(), QPointF(0, 0), false);
delete temp;
}
emit logPlayerListReceived(nameList);
restartGameDialog();
}
void Game::readyStart()
{
client->readyStart();
}
void Game::restartGameDialog()
{
dlgStartGame->show();
}
void Game::gameEvent(const ServerEventData &msg)
{
qDebug(QString("game::gameEvent: public=%1, player=%2, name=%3, type=%4, data=%5").arg(msg.getPublic()).arg(msg.getPlayerId()).arg(msg.getPlayerName()).arg(msg.getEventType()).arg(msg.getEventData().join("/")).toLatin1());
if (!msg.getPublic())
localPlayer->gameEvent(msg);
else {
Player *p = players.findPlayer(msg.getPlayerId());
if ((!p) && (msg.getEventType() != eventJoin)) {
// XXX
}
switch(msg.getEventType()) {
case eventSay:
emit logSay(p, msg.getEventData()[0]);
break;
case eventJoin: {
Player *newPlayer = addPlayer(msg.getPlayerId(), msg.getPlayerName(), QPointF(0, 0), false);
emit logJoin(newPlayer);
break;
}
case eventLeave:
emit logLeave(p);
// XXX Spieler natürlich noch rauswerfen
break;
case eventReadyStart:
if (started) {
started = false;
emit logReadyStart(p);
if (!p->getLocal())
restartGameDialog();
}
break;
case eventGameStart:
started = true;
emit logGameStart();
break;
case eventShuffle:
emit logShuffle(p);
break;
case eventRollDice: {
QStringList data = msg.getEventData();
int sides = data[0].toInt();
int roll = data[1].toInt();
emit logRollDice(p, sides, roll);
break;
}
case eventSetActivePlayer:
break;
case eventSetActivePhase:
break;
case eventName:
case eventCreateToken:
case eventSetupZones:
case eventSetCardAttr:
case eventAddCounter:
case eventSetCounter:
case eventDelCounter:
case eventPlayerId: {
p->gameEvent(msg);
break;
}
case eventDumpZone: {
QStringList data = msg.getEventData();
emit logDumpZone(p, data[1], players.findPlayer(data[0].toInt())->getName(), data[2].toInt());
break;
}
case eventStopDumpZone: {
QStringList data = msg.getEventData();
emit logStopDumpZone(p, data[1], players.findPlayer(data[0].toInt())->getName());
break;
}
case eventMoveCard: {
if (msg.getPlayerId() == localPlayer->getId())
break;
p->gameEvent(msg);
break;
}
case eventDraw: {
emit logDraw(p, msg.getEventData()[0].toInt());
if (msg.getPlayerId() == localPlayer->getId())
break;
p->gameEvent(msg);
break;
}
case eventInvalid:
qDebug("Unhandled global event");
}
}
}
void Game::actUntapAll()
{
client->setCardAttr("table", -1, "tapped", "false");
}
void Game::actIncLife()
{
client->incCounter("life", 1);
}
void Game::actDecLife()
{
client->incCounter("life", -1);
}
void Game::actSetLife()
{
bool ok;
int life = QInputDialog::getInteger(0, tr("Set life"), tr("New life total:"), localPlayer->area->getCounter("life")->getValue(), 0, 2000000000, 1, &ok);
if (ok)
client->setCounter("life", life);
}
void Game::actShuffle()
{
client->shuffle();
}
void Game::actRollDice()
{
bool ok;
int sides = QInputDialog::getInteger(0, tr("Roll dice"), tr("Number of sides:"), 20, 2, 1000, 1, &ok);
if (ok)
client->rollDice(sides);
}
void Game::actDrawCard()
{
client->drawCards(1);
}
void Game::actDrawCards()
{
int number = QInputDialog::getInteger(0, tr("Draw cards"), tr("Number:"));
if (number)
client->drawCards(number);
}
void Game::actCreateToken()
{
QString cardname = QInputDialog::getText(0, tr("Create token"), tr("Name:"));
client->createToken("table", cardname, QString(), 0, 0);
}
void Game::showCardMenu(QPoint p)
{
cardMenu->exec(p);
}
void Game::actTap()
{
QListIterator<QGraphicsItem *> i(scene->selectedItems());
while (i.hasNext()) {
CardItem *temp = (CardItem *) i.next();
if (!temp->getTapped())
client->setCardAttr(qgraphicsitem_cast<CardZone *>(temp->parentItem())->getName(), temp->getId(), "tapped", "1");
}
}
void Game::actUntap()
{
QListIterator<QGraphicsItem *> i(scene->selectedItems());
while (i.hasNext()) {
CardItem *temp = (CardItem *) i.next();
if (temp->getTapped())
client->setCardAttr(qgraphicsitem_cast<CardZone *>(temp->parentItem())->getName(), temp->getId(), "tapped", "0");
}
}
void Game::actDoesntUntap()
{
QListIterator<QGraphicsItem *> i(scene->selectedItems());
while (i.hasNext()) {
CardItem *temp = (CardItem *) i.next();
client->setCardAttr(qgraphicsitem_cast<CardZone *>(temp->parentItem())->getName(), temp->getId(), "doesnt_untap", QString::number(!temp->getDoesntUntap()));
}
}
void Game::actFlip()
{
QListIterator<QGraphicsItem *> i(scene->selectedItems());
while (i.hasNext()) {
CardItem *temp = (CardItem *) i.next();
QString zone = qgraphicsitem_cast<CardZone *>(temp->parentItem())->getName();
client->moveCard(temp->getId(), zone, zone, temp->getGridPoint().x(), temp->getGridPoint().y(), !temp->getFaceDown());
}
}
void Game::actAddCounter()
{
QListIterator<QGraphicsItem *> i(scene->selectedItems());
while (i.hasNext()) {
CardItem *temp = (CardItem *) i.next();
if (temp->getCounters() < MAX_COUNTERS_ON_CARD)
client->setCardAttr(qgraphicsitem_cast<CardZone *>(temp->parentItem())->getName(), temp->getId(), "counters", QString::number(temp->getCounters() + 1));
}
}
void Game::actRemoveCounter()
{
QListIterator<QGraphicsItem *> i(scene->selectedItems());
while (i.hasNext()) {
CardItem *temp = (CardItem *) i.next();
if (temp->getCounters())
client->setCardAttr(qgraphicsitem_cast<CardZone *>(temp->parentItem())->getName(), temp->getId(), "counters", QString::number(temp->getCounters() - 1));
}
}
void Game::actSetCounters()
{
bool ok;
int number = QInputDialog::getInteger(0, tr("Set counters"), tr("Number:"), 0, 0, MAX_COUNTERS_ON_CARD, 1, &ok);
if (!ok)
return;
QListIterator<QGraphicsItem *> i(scene->selectedItems());
while (i.hasNext()) {
CardItem *temp = (CardItem *) i.next();
client->setCardAttr(qgraphicsitem_cast<CardZone *>(temp->parentItem())->getName(), temp->getId(), "counters", QString::number(number));
}
}
void Game::actSayMessage()
{
QAction *a = qobject_cast<QAction *>(sender());
client->say(a->text());
}
void Game::hoverCardEvent(CardItem *card)
{
emit hoverCard(card->getName());
}