diff --git a/cockatrice/src/messagelogwidget.cpp b/cockatrice/src/messagelogwidget.cpp index a6448087..3a677ab3 100644 --- a/cockatrice/src/messagelogwidget.cpp +++ b/cockatrice/src/messagelogwidget.cpp @@ -434,10 +434,13 @@ void MessageLogWidget::logMulligan(Player *player, int number) if (!player) { return; } - if (number > -1) { - appendHtmlServerMessage(tr("%1 takes a mulligan to %2.").arg(sanitizeHtml(player->getName())).arg(number)); + if (number > 0) { + appendHtmlServerMessage(tr("%1 shuffles their deck and draws a new hand of %2 card(s).", "", number) + .arg(sanitizeHtml(player->getName())) + .arg(number)); } else { - appendHtmlServerMessage(tr("%1 draws their initial hand.").arg(sanitizeHtml(player->getName()))); + appendHtmlServerMessage( + tr("%1 shuffles their deck and draws a new hand.").arg(sanitizeHtml(player->getName()))); } } diff --git a/cockatrice/src/player.cpp b/cockatrice/src/player.cpp index 7a92b4ec..7ad482e9 100644 --- a/cockatrice/src/player.cpp +++ b/cockatrice/src/player.cpp @@ -1009,7 +1009,29 @@ void Player::actDrawCard() void Player::actMulligan() { - sendGameCommand(Command_Mulligan()); + int startSize = settingsCache->getStartingHandSize(); + int handSize = zones.value("hand")->getCards().size(); + int deckSize = zones.value("deck")->getCards().size() + handSize; + bool ok; + int number = QInputDialog::getInt( + game, tr("Draw hand"), tr("Number of cards:") + '\n' + tr("0 and lower are in comparison to current hand size"), + startSize, -handSize, deckSize, 1, &ok); + if (!ok) { + return; + } + Command_Mulligan cmd; + if (number < 1) { + if (handSize == 0) { + return; + } + cmd.set_number(handSize + number); + } else { + cmd.set_number(number); + } + sendGameCommand(cmd); + if (startSize != number) { + settingsCache->setStartingHandSize(number); + } } void Player::actDrawCards() diff --git a/cockatrice/src/settingscache.cpp b/cockatrice/src/settingscache.cpp index 01b68657..46304f2a 100644 --- a/cockatrice/src/settingscache.cpp +++ b/cockatrice/src/settingscache.cpp @@ -228,6 +228,7 @@ SettingsCache::SettingsCache() spectatorNotificationsEnabled = settings->value("interface/specnotificationsenabled", false).toBool(); doubleClickToPlay = settings->value("interface/doubleclicktoplay", true).toBool(); playToStack = settings->value("interface/playtostack", true).toBool(); + startingHandSize = settings->value("interface/startinghandsize", 7).toInt(); annotateTokens = settings->value("interface/annotatetokens", false).toBool(); tabGameSplitterSizes = settings->value("interface/tabgame_splittersizes").toByteArray(); displayCardNames = settings->value("cards/displaycardnames", true).toBool(); @@ -439,6 +440,12 @@ void SettingsCache::setPlayToStack(int _playToStack) settings->setValue("interface/playtostack", playToStack); } +void SettingsCache::setStartingHandSize(int _startingHandSize) +{ + startingHandSize = _startingHandSize; + settings->setValue("interface/startinghandsize", startingHandSize); +} + void SettingsCache::setAnnotateTokens(int _annotateTokens) { annotateTokens = static_cast(_annotateTokens); diff --git a/cockatrice/src/settingscache.h b/cockatrice/src/settingscache.h index ca951cd7..fc75fd54 100644 --- a/cockatrice/src/settingscache.h +++ b/cockatrice/src/settingscache.h @@ -78,6 +78,7 @@ private: bool spectatorNotificationsEnabled; bool doubleClickToPlay; bool playToStack; + int startingHandSize; bool annotateTokens; QByteArray tabGameSplitterSizes; bool displayCardNames; @@ -232,6 +233,10 @@ public: { return playToStack; } + int getStartingHandSize() const + { + return startingHandSize; + } bool getAnnotateTokens() const { return annotateTokens; @@ -466,6 +471,7 @@ public slots: void setSpectatorNotificationsEnabled(int _spectatorNotificationsEnabled); void setDoubleClickToPlay(int _doubleClickToPlay); void setPlayToStack(int _playToStack); + void setStartingHandSize(int _startingHandSize); void setAnnotateTokens(int _annotateTokens); void setTabGameSplitterSizes(const QByteArray &_tabGameSplitterSizes); void setDisplayCardNames(int _displayCardNames); diff --git a/common/pb/command_mulligan.proto b/common/pb/command_mulligan.proto index f0ffb87c..38ed5a36 100644 --- a/common/pb/command_mulligan.proto +++ b/common/pb/command_mulligan.proto @@ -4,6 +4,6 @@ message Command_Mulligan { extend GameCommand { optional Command_Mulligan ext = 1004; } + optional uint32 number = 7; } - diff --git a/common/server_player.cpp b/common/server_player.cpp index 1c9d21dc..3d3a17f3 100644 --- a/common/server_player.cpp +++ b/common/server_player.cpp @@ -90,8 +90,8 @@ Server_Player::Server_Player(Server_Game *_game, bool _judge, Server_AbstractUserInterface *_userInterface) : ServerInfo_User_Container(_userInfo), game(_game), userInterface(_userInterface), deck(nullptr), pingTime(0), - playerId(_playerId), spectator(_spectator), judge(_judge), initialCards(0), nextCardId(0), readyStart(false), - conceded(false), sideboardLocked(true) + playerId(_playerId), spectator(_spectator), judge(_judge), nextCardId(0), readyStart(false), conceded(false), + sideboardLocked(true) { } @@ -166,8 +166,6 @@ void Server_Player::setupZones() addCounter(new Server_Counter(6, "x", makeColor(255, 255, 255), 20, 0)); addCounter(new Server_Counter(7, "storm", makeColor(255, 150, 30), 20, 0)); - initialCards = 7; - // ------------------------------------------------------------------ // Assign card ids and create deck from deck list @@ -980,7 +978,7 @@ Server_Player::cmdShuffle(const Command_Shuffle &cmd, ResponseContainer & /*rc*/ } Response::ResponseCode -Server_Player::cmdMulligan(const Command_Mulligan & /*cmd*/, ResponseContainer & /*rc*/, GameEventStorage &ges) +Server_Player::cmdMulligan(const Command_Mulligan &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges) { if (spectator) { return Response::RespFunctionNotAllowed; @@ -994,14 +992,18 @@ Server_Player::cmdMulligan(const Command_Mulligan & /*cmd*/, ResponseContainer & } Server_CardZone *hand = zones.value("hand"); - int number = (hand->getCards().size() <= 1) ? initialCards : hand->getCards().size() - 1; - Server_CardZone *deck = zones.value("deck"); - while (!hand->getCards().isEmpty()) { - auto *cardToMove = new CardToMove; - cardToMove->set_card_id(hand->getCards().first()->getId()); - moveCard(ges, hand, QList() << cardToMove, deck, 0, 0, false); - delete cardToMove; + int number = cmd.number(); + + if (!hand->getCards().isEmpty()) { + auto cardsToMove = QList(); + for (auto &card : hand->getCards()) { + auto *cardToMove = new CardToMove; + cardToMove->set_card_id(card->getId()); + cardsToMove.append(cardToMove); + } + moveCard(ges, hand, cardsToMove, deck, -1, 0, false); + qDeleteAll(cardsToMove); } deck->shuffle(); @@ -1009,12 +1011,8 @@ Server_Player::cmdMulligan(const Command_Mulligan & /*cmd*/, ResponseContainer & drawCards(ges, number); - if (number == initialCards) { - number = -1; - } - Context_Mulligan context; - context.set_number(static_cast(number)); + context.set_number(static_cast(hand->getCards().size())); ges.setGameEventContext(context); return Response::RespOk; diff --git a/common/server_player.h b/common/server_player.h index 79b8c9ee..aba9fbe5 100644 --- a/common/server_player.h +++ b/common/server_player.h @@ -79,7 +79,6 @@ private: int playerId; bool spectator; bool judge; - int initialCards; int nextCardId; bool readyStart; bool conceded;