/** * @file player_actions.h * @ingroup GameLogicActions * @ingroup GameLogicPlayers */ //! \todo Document this file. #ifndef COCKATRICE_PLAYER_ACTIONS_H #define COCKATRICE_PLAYER_ACTIONS_H #include "../board/card_list.h" #include "../board/card_state.h" #include "card_menu_action_type.h" #include "card_move_request.h" #include "libcockatrice/card/card_info.h" #include "move_top_cards_until_options.h" #include "token_info.h" #include #include #include #include #include #include class CardRelation; class QAction; class QTimer; template class QList; namespace google { namespace protobuf { class Message; } } // namespace google class CardState; class CardZoneLogic; class Command_MoveCard; class GameEventContext; class ICardPreferenceProvider; class IInterfaceSettingsProvider; class PendingCommand; class PlayerLogic; class QAction; struct ArrowData; class PlayerActions : public QObject { Q_OBJECT public: enum CardsToReveal { RANDOM_CARD_FROM_ZONE = -2 }; explicit PlayerActions(PlayerLogic *player, IInterfaceSettingsProvider *interfaceSettings = nullptr, ICardPreferenceProvider *cardPreferences = nullptr); void sendGameCommand(PendingCommand *pend); void sendGameCommand(const google::protobuf::Message &command); PendingCommand *prepareGameCommand(const ::google::protobuf::Message &cmd); PendingCommand *prepareGameCommand(const QList &cmdList); /** * @brief Moves the requested cards between zones on behalf of a view. * @param startZone Zone the cards are dragged out of. * @param targetZone Zone the cards are dropped onto. * @param x Horizontal target index within the zone. * @param y Vertical target index within the zone. * @param cards The cards to move, as chosen by the view. */ void moveCards(CardZoneLogic *startZone, CardZoneLogic *targetZone, int x, int y, const QList &cards); /** * @brief Prepares a dump of the given zone, for the caller to connect to and send. * @param zone Zone to dump. * @param numberCards How many cards to dump, -1 for all. */ PendingCommand *prepareZoneDump(CardZoneLogic *zone, int numberCards); /** * @brief Sets the tapped state of the cards that do not already have it. * @param zoneName Zone the cards belong to. * @param cards Cards the view wants toggled. * @param tapped Desired tapped state. */ void actToggleTapped(const QString &zoneName, const QList &cards, bool tapped); /** * @brief Attaches one card to another on the table on behalf of a view. * @param startCard Card being attached. * @param targetCard Card being attached to. */ void attachCards(CardState *startCard, const CardState *targetCard); /** * @brief Draws an arrow from a card to another card or a player on behalf of a view. * * The view resolves the endpoints before playing the card out of hand, so the * arrow still records the zone the card started in. * * @param startCard Card the arrow starts from. * @param arrow Arrow endpoints and color, as resolved by the view. * @param deleteInPhase Phase the arrow expires in, 0 to keep it until removed. */ void createArrow(CardState *startCard, const ArrowData &arrow, int deleteInPhase); void moveOneCardUntil(CardState *card); void stopMoveTopCardsUntil(); [[nodiscard]] bool isMovingCardsUntil() const { return movingCardsUntil; } signals: void requestViewTopCardsDialog(int defaultNumberTopCards, int deckSize); void requestViewBottomCardsDialog(int defaultNumberBottomCards, int deckSize); void requestShuffleTopDialog(int defaultNumberTopCards, int maxCards); void requestShuffleBottomDialog(int defaultNumberBottomCards, int maxCards); void requestMulliganDialog(int startSize, int handSize, int deckSize); void requestDrawCardsDialog(int defaultNumberTopCards, int deckSize); void requestMoveTopCardsToDialog(int defaultNumberTopCards, int maxCards, const QString &targetZone, const QString &zoneDisplayName, bool faceDown); void requestMoveTopCardsUntilDialog(MoveTopCardsUntilOptions options); void requestMoveBottomCardsToDialog(int defaultNumberBottomCards, int maxCards, const QString &targetZone, const QString &zoneDisplayName, bool faceDown); void requestDrawBottomCardsDialog(int defaultNumberBottomCards, int maxCards); void requestRollDieDialog(); void requestCreateTokenDialog(const QStringList &predefinedTokens); void requestCreateRelatedFromRelationDialog(const CardState *sourceCard, const CardRelation *cardRelation); void requestMoveCardXCardsFromTopDialog(int defaultNumberTopCardsToPlaceBelow, int deckSize); void requestSetPTDialog(const QString &oldPT); void requestSetAnnotationDialog(const QString &oldAnnotation); void requestSetCardCounterDialog(int counterId, const QString &oldValueForDlg); void requestZoneViewToggle(const QString &zoneName, int numberCards, bool isReversed = false); void requestSortHand(const QList &options); void requestEnableAndSetCreateAnotherTokenAction(const QString &lastTokenName); void requestSetLastToken(CardInfoPtr lastToken); /** * @brief The player chose a mulligan size to remember as the starting hand size. * * Game logic must not write client settings itself, so persistence is left to the application. */ void startingHandSizeChosen(int number); public slots: void setLastToken(CardInfoPtr cardInfo); void setLastTokenInfo(CardInfoPtr cardInfo); void playCard(CardState *c, bool faceDown); void playCardToTable(const CardState *c, bool faceDown); void actUntapAll(); void actRequestRollDieDialog(); void actRollDie(int sides, int count); void actFlipCoin(); void actRequestCreateTokenDialog(const QStringList &predefinedTokens); void actCreateToken(TokenInfo tokenToCreate); void actCreateAnotherToken(); void actRequestCreateRelatedFromRelationDialog(const CardState *sourceCard, const CardRelation *cardRelation); bool createRelatedFromRelation(const CardState *sourceCard, const CardRelation *cardRelation, int variableCount); void onRelatedCardCreated(const CardState *sourceCard, const CardRelation *cardRelation); void setLastRelatedCreationSucceeded(bool succeeded) { lastRelatedCreationSucceeded = succeeded; } void actShuffle(); void actRequestShuffleTopDialog(); void actShuffleTop(int number); void actRequestShuffleBottomDialog(); void actShuffleBottom(int number); void actDrawCard(); void actRequestDrawCardsDialog(); void actDrawCards(int number); void actUndoDraw(); void actRequestMulliganDialog(); void actMulligan(int number); void actMulliganSameSize(); void actMulliganMinusOne(); void doMulligan(int number); void actPlay(QList selectedCards); void actPlayFacedown(QList selectedCards); void actHide(QList selectedCards); void actMoveTopCardToPlay(); void actMoveTopCardToPlayFaceDown(); void actMoveTopCardToGrave(); void actMoveTopCardToExile(); void actMoveTopCardsToGrave(); void actMoveTopCardsToGraveFaceDown(); void actMoveTopCardsToExile(); void actMoveTopCardsToExileFaceDown(); void actRequestMoveTopCardsUntilDialog(); void moveTopCardsUntil(const QString &expr, MoveTopCardsUntilOptions options); void actMoveTopCardToBottom(); void actRequestMoveTopCardsToDialog(const QString &targetZone, const QString &zoneDisplayName, bool faceDown); void moveTopCardsTo(int number, const QString &targetZone, bool faceDown); void actDrawBottomCard(); void actRequestDrawBottomCardsDialog(); void actDrawBottomCards(int number); void actMoveBottomCardToPlay(); void actMoveBottomCardToPlayFaceDown(); void actMoveBottomCardToGrave(); void actMoveBottomCardToExile(); void actMoveBottomCardsToGrave(); void actMoveBottomCardsToGraveFaceDown(); void actMoveBottomCardsToExile(); void actMoveBottomCardsToExileFaceDown(); void actMoveBottomCardToTop(); void actRequestMoveBottomCardsToDialog(const QString &targetZone, const QString &zoneDisplayName, bool faceDown); void moveBottomCardsTo(int number, const QString &targetZone, bool faceDown); void actViewLibrary(); void actViewHand(); void actRequestViewTopCardsDialog(); void actViewTopCards(int number); void actRequestViewBottomCardsDialog(); void actViewBottomCards(int number); void actAlwaysRevealTopCard(bool alwaysRevealTopCard); void actAlwaysLookAtTopCard(bool alwaysRevealTopCard); void actViewGraveyard(); void actLendLibrary(int lendToPlayerId); void actRevealTopCards(int revealToPlayerId, int amount); void actRevealRandomGraveyardCard(int revealToPlayerId); void actViewRfg(); void actViewSideboard(); void actSayMessage(); void actOpenDeckInDeckEditor(); void actCreatePredefinedToken(); void actCreateRelatedCard(const CardState *sourceCard, int index); void actCreateAllRelatedCards(const CardState *sourceCard); void actRequestMoveCardXCardsFromTopDialog(); void actMoveCardXCardsFromTop(QList selectedCards, int number); void actRemoveCardCounter(QList selectedCards, int counterId); void actAddCardCounter(QList selectedCards, int counterId); void actRequestSetCardCounterDialog(QList selectedCards, int counterId); void actSetCardCounter(QList selectedCards, int counterId, const QString &counterValue); void actIncrementAllCardCounters(QList cardsToUpdate); void actUnattach(QList selectedCards); void actIncPT(QList selectedCards, int deltaP, int deltaT); void actResetPT(QList selectedCards); void actRequestSetPTDialog(QList selectedCards); void actSetPT(QList selectedCards, const QString &pt); void actIncP(QList selectedCards); void actDecP(QList selectedCards); void actIncT(QList selectedCards); void actDecT(QList selectedCards); void actIncPT(QList selectedCards); void actDecPT(QList selectedCards); void actFlowP(QList selectedCards); void actFlowT(QList selectedCards); /** @brief Adjusts a player counter by a signed delta. */ void actIncrementCounter(int counterId, int delta); /** @brief Sets a player counter to an absolute value. */ void actSetCounter(int counterId, int value); void actReduceLifeByPower(QList selectedCards); void actRequestSetAnnotationDialog(QList selectedCards); void actSetAnnotation(QList selectedCards, const QString &annotation); void actReveal(QList selectedCards, QAction *action); void actRevealHand(int revealToPlayerId); void actRevealRandomHandCard(int revealToPlayerId); void actRevealLibrary(int revealToPlayerId); void actSortHand(); void cardMenuAction(QList selectedCards, CardMenuActionType type); private: PlayerLogic *player; // Borrowed settings providers (owned by the application). Null outside the client, in which case the compiled-in // defaults below apply. IInterfaceSettingsProvider *interfaceSettings; ICardPreferenceProvider *cardPreferences; int defaultNumberTopCards = 1; int defaultNumberTopCardsToPlaceBelow = 1; int defaultNumberBottomCards = 1; int defaultNumberDieRoll = 20; TokenInfo lastTokenInfo; int lastTokenTableRow; bool movingCardsUntil; QTimer *moveTopCardTimer; FilterString movingCardsUntilFilter; int movingCardsUntilCounter = 0; MoveTopCardsUntilOptions movingCardsUntilOptions; bool lastRelatedCreationSucceeded = false; [[nodiscard]] bool getPlayToStack() const; [[nodiscard]] int getStartingHandSize() const; [[nodiscard]] bool getAnnotateTokens() const; [[nodiscard]] QString getCardPreferenceOverride(const QString &cardName) const; void createCard(const CardState *sourceCard, const QString &dbCardName, CardRelationType attach = CardRelationType::DoesNotAttach, bool persistent = false, bool faceDown = false); void playSelectedCards(QList selectedCards, bool faceDown = false); void cmdSetTopCard(Command_MoveCard &cmd); void cmdSetBottomCard(Command_MoveCard &cmd); void offsetCardCounter(QList selectedCards, int counterId, int offset); }; #endif // COCKATRICE_PLAYER_ACTIONS_H