mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-06-29 18:13:55 -07:00
Add moveToTable context menu action and extract tableRowToGridY helper (#6738)
Adds a Table option to the Move menu, allowing cards to be moved directly to the battlefield from any zone. Extracts the repeated tableRow-to-grid-Y conversion logic into TableZone::tableRowToGridY(), consolidating five call sites and fixing a latent bug where cards with tableRow > 2 could land on the wrong row.
This commit is contained in:
parent
70b41c2095
commit
94ea574c76
7 changed files with 64 additions and 14 deletions
|
|
@ -563,6 +563,9 @@ private:
|
||||||
{"Player/aMoveToTopLibrary", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Top of Library"),
|
{"Player/aMoveToTopLibrary", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Top of Library"),
|
||||||
parseSequenceString(""),
|
parseSequenceString(""),
|
||||||
ShortcutGroup::Move_selected)},
|
ShortcutGroup::Move_selected)},
|
||||||
|
{"Player/aMoveToTable", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Battlefield"),
|
||||||
|
parseSequenceString(""),
|
||||||
|
ShortcutGroup::Move_selected)},
|
||||||
{"Player/aViewHand",
|
{"Player/aViewHand",
|
||||||
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Hand"), parseSequenceString(""), ShortcutGroup::View)},
|
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Hand"), parseSequenceString(""), ShortcutGroup::View)},
|
||||||
{"Player/aViewGraveyard",
|
{"Player/aViewGraveyard",
|
||||||
|
|
|
||||||
|
|
@ -9,17 +9,20 @@
|
||||||
|
|
||||||
enum CardMenuActionType
|
enum CardMenuActionType
|
||||||
{
|
{
|
||||||
|
// Per-card attribute actions (must be <= cmClone for cardMenuAction() dispatch)
|
||||||
cmTap,
|
cmTap,
|
||||||
cmUntap,
|
cmUntap,
|
||||||
cmDoesntUntap,
|
cmDoesntUntap,
|
||||||
cmFlip,
|
cmFlip,
|
||||||
cmPeek,
|
cmPeek,
|
||||||
cmClone,
|
cmClone,
|
||||||
|
// Move actions (must be > cmClone for cardMenuAction() dispatch)
|
||||||
cmMoveToTopLibrary,
|
cmMoveToTopLibrary,
|
||||||
cmMoveToBottomLibrary,
|
cmMoveToBottomLibrary,
|
||||||
cmMoveToHand,
|
cmMoveToHand,
|
||||||
cmMoveToGraveyard,
|
cmMoveToGraveyard,
|
||||||
cmMoveToExile
|
cmMoveToExile,
|
||||||
|
cmMoveToTable
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // COCKATRICE_CARD_MENU_ACTION_TYPE_H
|
#endif // COCKATRICE_CARD_MENU_ACTION_TYPE_H
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@ MoveMenu::MoveMenu(Player *player) : QMenu(tr("Move to"))
|
||||||
aMoveToBottomLibrary = new QAction(this);
|
aMoveToBottomLibrary = new QAction(this);
|
||||||
aMoveToBottomLibrary->setData(cmMoveToBottomLibrary);
|
aMoveToBottomLibrary->setData(cmMoveToBottomLibrary);
|
||||||
aMoveToXfromTopOfLibrary = new QAction(this);
|
aMoveToXfromTopOfLibrary = new QAction(this);
|
||||||
|
aMoveToTable = new QAction(this);
|
||||||
|
aMoveToTable->setData(cmMoveToTable);
|
||||||
aMoveToGraveyard = new QAction(this);
|
aMoveToGraveyard = new QAction(this);
|
||||||
aMoveToHand = new QAction(this);
|
aMoveToHand = new QAction(this);
|
||||||
aMoveToHand->setData(cmMoveToHand);
|
aMoveToHand->setData(cmMoveToHand);
|
||||||
|
|
@ -22,6 +24,7 @@ MoveMenu::MoveMenu(Player *player) : QMenu(tr("Move to"))
|
||||||
connect(aMoveToBottomLibrary, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction);
|
connect(aMoveToBottomLibrary, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction);
|
||||||
connect(aMoveToXfromTopOfLibrary, &QAction::triggered, player->getPlayerActions(),
|
connect(aMoveToXfromTopOfLibrary, &QAction::triggered, player->getPlayerActions(),
|
||||||
&PlayerActions::actMoveCardXCardsFromTop);
|
&PlayerActions::actMoveCardXCardsFromTop);
|
||||||
|
connect(aMoveToTable, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction);
|
||||||
connect(aMoveToHand, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction);
|
connect(aMoveToHand, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction);
|
||||||
connect(aMoveToGraveyard, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction);
|
connect(aMoveToGraveyard, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction);
|
||||||
connect(aMoveToExile, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction);
|
connect(aMoveToExile, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction);
|
||||||
|
|
@ -30,6 +33,8 @@ MoveMenu::MoveMenu(Player *player) : QMenu(tr("Move to"))
|
||||||
addAction(aMoveToXfromTopOfLibrary);
|
addAction(aMoveToXfromTopOfLibrary);
|
||||||
addAction(aMoveToBottomLibrary);
|
addAction(aMoveToBottomLibrary);
|
||||||
addSeparator();
|
addSeparator();
|
||||||
|
addAction(aMoveToTable);
|
||||||
|
addSeparator();
|
||||||
addAction(aMoveToHand);
|
addAction(aMoveToHand);
|
||||||
addSeparator();
|
addSeparator();
|
||||||
addAction(aMoveToGraveyard);
|
addAction(aMoveToGraveyard);
|
||||||
|
|
@ -47,6 +52,7 @@ void MoveMenu::setShortcutsActive()
|
||||||
|
|
||||||
aMoveToTopLibrary->setShortcuts(shortcuts.getShortcut("Player/aMoveToTopLibrary"));
|
aMoveToTopLibrary->setShortcuts(shortcuts.getShortcut("Player/aMoveToTopLibrary"));
|
||||||
aMoveToBottomLibrary->setShortcuts(shortcuts.getShortcut("Player/aMoveToBottomLibrary"));
|
aMoveToBottomLibrary->setShortcuts(shortcuts.getShortcut("Player/aMoveToBottomLibrary"));
|
||||||
|
aMoveToTable->setShortcuts(shortcuts.getShortcut("Player/aMoveToTable"));
|
||||||
aMoveToHand->setShortcuts(shortcuts.getShortcut("Player/aMoveToHand"));
|
aMoveToHand->setShortcuts(shortcuts.getShortcut("Player/aMoveToHand"));
|
||||||
aMoveToGraveyard->setShortcuts(shortcuts.getShortcut("Player/aMoveToGraveyard"));
|
aMoveToGraveyard->setShortcuts(shortcuts.getShortcut("Player/aMoveToGraveyard"));
|
||||||
aMoveToExile->setShortcuts(shortcuts.getShortcut("Player/aMoveToExile"));
|
aMoveToExile->setShortcuts(shortcuts.getShortcut("Player/aMoveToExile"));
|
||||||
|
|
@ -57,6 +63,7 @@ void MoveMenu::retranslateUi()
|
||||||
aMoveToTopLibrary->setText(tr("&Top of library in random order"));
|
aMoveToTopLibrary->setText(tr("&Top of library in random order"));
|
||||||
aMoveToXfromTopOfLibrary->setText(tr("X cards from the top of library..."));
|
aMoveToXfromTopOfLibrary->setText(tr("X cards from the top of library..."));
|
||||||
aMoveToBottomLibrary->setText(tr("&Bottom of library in random order"));
|
aMoveToBottomLibrary->setText(tr("&Bottom of library in random order"));
|
||||||
|
aMoveToTable->setText(tr("T&able"));
|
||||||
aMoveToHand->setText(tr("&Hand"));
|
aMoveToHand->setText(tr("&Hand"));
|
||||||
aMoveToGraveyard->setText(tr("&Graveyard"));
|
aMoveToGraveyard->setText(tr("&Graveyard"));
|
||||||
aMoveToExile->setText(tr("&Exile"));
|
aMoveToExile->setText(tr("&Exile"));
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ public:
|
||||||
QAction *aMoveToBottomLibrary = nullptr;
|
QAction *aMoveToBottomLibrary = nullptr;
|
||||||
|
|
||||||
QAction *aMoveToHand = nullptr;
|
QAction *aMoveToHand = nullptr;
|
||||||
|
QAction *aMoveToTable = nullptr;
|
||||||
QAction *aMoveToGraveyard = nullptr;
|
QAction *aMoveToGraveyard = nullptr;
|
||||||
QAction *aMoveToExile = nullptr;
|
QAction *aMoveToExile = nullptr;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ void PlayerActions::playCard(CardItem *card, bool faceDown)
|
||||||
cmd.set_y(0);
|
cmd.set_y(0);
|
||||||
} else {
|
} else {
|
||||||
tableRow = faceDown ? 2 : info.getUiAttributes().tableRow;
|
tableRow = faceDown ? 2 : info.getUiAttributes().tableRow;
|
||||||
QPoint gridPoint = QPoint(-1, TableZone::clampValidTableRow(2 - tableRow));
|
QPoint gridPoint = QPoint(-1, TableZone::tableRowToGridY(tableRow));
|
||||||
cardToMove->set_face_down(faceDown);
|
cardToMove->set_face_down(faceDown);
|
||||||
if (!faceDown) {
|
if (!faceDown) {
|
||||||
cardToMove->set_pt(info.getPowTough().toStdString());
|
cardToMove->set_pt(info.getPowTough().toStdString());
|
||||||
|
|
@ -114,12 +114,7 @@ void PlayerActions::playCardToTable(const CardItem *card, bool faceDown)
|
||||||
const CardInfo &info = exactCard.getInfo();
|
const CardInfo &info = exactCard.getInfo();
|
||||||
|
|
||||||
int tableRow = faceDown ? 2 : info.getUiAttributes().tableRow;
|
int tableRow = faceDown ? 2 : info.getUiAttributes().tableRow;
|
||||||
// default instant/sorcery cards to the noncreatures row
|
QPoint gridPoint = QPoint(-1, TableZone::tableRowToGridY(tableRow));
|
||||||
if (tableRow > 2) {
|
|
||||||
tableRow = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
QPoint gridPoint = QPoint(-1, TableZone::clampValidTableRow(2 - tableRow));
|
|
||||||
cardToMove->set_face_down(faceDown);
|
cardToMove->set_face_down(faceDown);
|
||||||
if (!faceDown) {
|
if (!faceDown) {
|
||||||
cardToMove->set_pt(info.getPowTough().toStdString());
|
cardToMove->set_pt(info.getPowTough().toStdString());
|
||||||
|
|
@ -866,7 +861,7 @@ void PlayerActions::actCreateToken()
|
||||||
ExactCard correctedCard = CardDatabaseManager::query()->guessCard({lastTokenInfo.name, lastTokenInfo.providerId});
|
ExactCard correctedCard = CardDatabaseManager::query()->guessCard({lastTokenInfo.name, lastTokenInfo.providerId});
|
||||||
if (correctedCard) {
|
if (correctedCard) {
|
||||||
lastTokenInfo.name = correctedCard.getName();
|
lastTokenInfo.name = correctedCard.getName();
|
||||||
lastTokenTableRow = TableZone::clampValidTableRow(2 - correctedCard.getInfo().getUiAttributes().tableRow);
|
lastTokenTableRow = TableZone::tableRowToGridY(correctedCard.getInfo().getUiAttributes().tableRow);
|
||||||
if (lastTokenInfo.pt.isEmpty()) {
|
if (lastTokenInfo.pt.isEmpty()) {
|
||||||
lastTokenInfo.pt = correctedCard.getInfo().getPowTough();
|
lastTokenInfo.pt = correctedCard.getInfo().getPowTough();
|
||||||
}
|
}
|
||||||
|
|
@ -917,7 +912,7 @@ void PlayerActions::setLastToken(CardInfoPtr cardInfo)
|
||||||
.providerId =
|
.providerId =
|
||||||
SettingsCache::instance().cardOverrides().getCardPreferenceOverride(cardInfo->getName())};
|
SettingsCache::instance().cardOverrides().getCardPreferenceOverride(cardInfo->getName())};
|
||||||
|
|
||||||
lastTokenTableRow = TableZone::clampValidTableRow(2 - cardInfo->getUiAttributes().tableRow);
|
lastTokenTableRow = TableZone::tableRowToGridY(cardInfo->getUiAttributes().tableRow);
|
||||||
|
|
||||||
utilityMenu->setAndEnableCreateAnotherTokenAction(tr("C&reate another %1 token").arg(lastTokenInfo.name));
|
utilityMenu->setAndEnableCreateAnotherTokenAction(tr("C&reate another %1 token").arg(lastTokenInfo.name));
|
||||||
}
|
}
|
||||||
|
|
@ -1085,9 +1080,7 @@ void PlayerActions::createCard(const CardItem *sourceCard,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the target token's location
|
QPoint gridPoint = QPoint(-1, TableZone::tableRowToGridY(cardInfo->getUiAttributes().tableRow));
|
||||||
// TODO: Define this QPoint into its own function along with the one below
|
|
||||||
QPoint gridPoint = QPoint(-1, TableZone::clampValidTableRow(2 - cardInfo->getUiAttributes().tableRow));
|
|
||||||
|
|
||||||
// create the token for the related card
|
// create the token for the related card
|
||||||
Command_CreateToken cmd;
|
Command_CreateToken cmd;
|
||||||
|
|
@ -1930,6 +1923,34 @@ void PlayerActions::cardMenuAction()
|
||||||
commandList.append(cmd);
|
commandList.append(cmd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case cmMoveToTable: {
|
||||||
|
// Each card needs its own command because table row, pt, and cipt vary per card
|
||||||
|
for (const auto &card : cardList) {
|
||||||
|
auto *cmd = new Command_MoveCard;
|
||||||
|
cmd->set_start_player_id(startPlayerId);
|
||||||
|
cmd->set_start_zone(startZone.toStdString());
|
||||||
|
cmd->set_target_player_id(player->getPlayerInfo()->getId());
|
||||||
|
cmd->set_target_zone(ZoneNames::TABLE);
|
||||||
|
cmd->set_x(-1);
|
||||||
|
|
||||||
|
CardToMove *ctm = cmd->mutable_cards_to_move()->add_card();
|
||||||
|
ctm->set_card_id(card->getId());
|
||||||
|
ctm->set_face_down(false);
|
||||||
|
|
||||||
|
int tableRow = 0;
|
||||||
|
ExactCard exactCard = card->getCard();
|
||||||
|
if (exactCard) {
|
||||||
|
const CardInfo &info = exactCard.getInfo();
|
||||||
|
tableRow = info.getUiAttributes().tableRow;
|
||||||
|
ctm->set_pt(info.getPowTough().toStdString());
|
||||||
|
ctm->set_tapped(info.getUiAttributes().cipt);
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd->set_y(TableZone::tableRowToGridY(tableRow));
|
||||||
|
commandList.append(cmd);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -382,3 +382,11 @@ int TableZone::clampValidTableRow(const int row)
|
||||||
return TABLEROWS - 1;
|
return TABLEROWS - 1;
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int TableZone::tableRowToGridY(int tableRow)
|
||||||
|
{
|
||||||
|
if (tableRow > 2) {
|
||||||
|
tableRow = 1;
|
||||||
|
}
|
||||||
|
return clampValidTableRow(2 - tableRow);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,13 @@ public:
|
||||||
|
|
||||||
static int clampValidTableRow(const int row);
|
static int clampValidTableRow(const int row);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a card's logical table row (0=creatures, 1=noncreatures, 2=lands)
|
||||||
|
* to the corresponding grid Y coordinate. Cards with tableRow > 2 (e.g.,
|
||||||
|
* instants/sorceries) default to the noncreatures row.
|
||||||
|
*/
|
||||||
|
static int tableRowToGridY(int tableRow);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Resizes the TableZone in case CardItems are within or
|
Resizes the TableZone in case CardItems are within or
|
||||||
outside of the TableZone constraints.
|
outside of the TableZone constraints.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue