mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2025-12-12 07:40:30 -08:00
add phase to delete arrows in to protocol (#6159)
* protocol changes * servatrice changes * add new setting * implement client side with static 4 phases * reading the code explains the code * add subphases to phase.cpp * use new subphase definition
This commit is contained in:
@@ -261,6 +261,7 @@ SettingsCache::SettingsCache()
|
||||
doubleClickToPlay = settings->value("interface/doubleclicktoplay", true).toBool();
|
||||
clickPlaysAllSelected = settings->value("interface/clickPlaysAllSelected", true).toBool();
|
||||
playToStack = settings->value("interface/playtostack", true).toBool();
|
||||
doNotDeleteArrowsInSubPhases = settings->value("interface/doNotDeleteArrowsInSubPhases", true).toBool();
|
||||
startingHandSize = settings->value("interface/startinghandsize", 7).toInt();
|
||||
annotateTokens = settings->value("interface/annotatetokens", false).toBool();
|
||||
tabGameSplitterSizes = settings->value("interface/tabgame_splittersizes").toByteArray();
|
||||
@@ -664,6 +665,12 @@ void SettingsCache::setPlayToStack(QT_STATE_CHANGED_T _playToStack)
|
||||
settings->setValue("interface/playtostack", playToStack);
|
||||
}
|
||||
|
||||
void SettingsCache::setDoNotDeleteArrowsInSubPhases(QT_STATE_CHANGED_T _doNotDeleteArrowsInSubPhases)
|
||||
{
|
||||
doNotDeleteArrowsInSubPhases = static_cast<bool>(_doNotDeleteArrowsInSubPhases);
|
||||
settings->setValue("interface/doNotDeleteArrowsInSubPhases", doNotDeleteArrowsInSubPhases);
|
||||
}
|
||||
|
||||
void SettingsCache::setStartingHandSize(int _startingHandSize)
|
||||
{
|
||||
startingHandSize = _startingHandSize;
|
||||
|
||||
@@ -228,6 +228,7 @@ private:
|
||||
bool doubleClickToPlay;
|
||||
bool clickPlaysAllSelected;
|
||||
bool playToStack;
|
||||
bool doNotDeleteArrowsInSubPhases;
|
||||
int startingHandSize;
|
||||
bool annotateTokens;
|
||||
QByteArray tabGameSplitterSizes;
|
||||
@@ -525,6 +526,10 @@ public:
|
||||
{
|
||||
return playToStack;
|
||||
}
|
||||
bool getDoNotDeleteArrowsInSubPhases() const
|
||||
{
|
||||
return doNotDeleteArrowsInSubPhases;
|
||||
}
|
||||
int getStartingHandSize() const
|
||||
{
|
||||
return startingHandSize;
|
||||
@@ -984,6 +989,7 @@ public slots:
|
||||
void setDoubleClickToPlay(QT_STATE_CHANGED_T _doubleClickToPlay);
|
||||
void setClickPlaysAllSelected(QT_STATE_CHANGED_T _clickPlaysAllSelected);
|
||||
void setPlayToStack(QT_STATE_CHANGED_T _playToStack);
|
||||
void setDoNotDeleteArrowsInSubPhases(QT_STATE_CHANGED_T _doNotDeleteArrowsInSubPhases);
|
||||
void setStartingHandSize(int _startingHandSize);
|
||||
void setAnnotateTokens(QT_STATE_CHANGED_T _annotateTokens);
|
||||
void setTabGameSplitterSizes(const QByteArray &_tabGameSplitterSizes);
|
||||
|
||||
@@ -151,8 +151,8 @@ void ArrowItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
ArrowDragItem::ArrowDragItem(Player *_owner, ArrowTarget *_startItem, const QColor &_color)
|
||||
: ArrowItem(_owner, -1, _startItem, 0, _color)
|
||||
ArrowDragItem::ArrowDragItem(Player *_owner, ArrowTarget *_startItem, const QColor &_color, int _deleteInPhase)
|
||||
: ArrowItem(_owner, -1, _startItem, 0, _color), deleteInPhase(_deleteInPhase)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -231,20 +231,28 @@ void ArrowDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||
cmd.set_target_player_id(targetZone->getPlayer()->getPlayerInfo()->getId());
|
||||
cmd.set_target_zone(targetZone->getName().toStdString());
|
||||
cmd.set_target_card_id(targetCard->getId());
|
||||
} else {
|
||||
} else { // failed to cast target to card, this means it's a player
|
||||
PlayerTarget *targetPlayer = qgraphicsitem_cast<PlayerTarget *>(targetItem);
|
||||
cmd.set_target_player_id(targetPlayer->getOwner()->getPlayerInfo()->getId());
|
||||
}
|
||||
if (startZone->getName().compare("hand") == 0) {
|
||||
|
||||
// if the card is in hand then we will move the card to stack or table as part of drawing the arrow
|
||||
if (startZone->getName() == "hand") {
|
||||
startCard->playCard(false);
|
||||
CardInfoPtr ci = startCard->getCard().getCardPtr();
|
||||
if (ci && ((!SettingsCache::instance().getPlayToStack() && ci->getUiAttributes().tableRow == 3) ||
|
||||
(SettingsCache::instance().getPlayToStack() && ci->getUiAttributes().tableRow != 0 &&
|
||||
startCard->getZone()->getName().toStdString() != "stack")))
|
||||
bool playToStack = SettingsCache::instance().getPlayToStack();
|
||||
if (ci &&
|
||||
((!playToStack && ci->getUiAttributes().tableRow == 3) ||
|
||||
(playToStack && ci->getUiAttributes().tableRow != 0 && startCard->getZone()->getName() != "stack")))
|
||||
cmd.set_start_zone("stack");
|
||||
else
|
||||
cmd.set_start_zone(SettingsCache::instance().getPlayToStack() ? "stack" : "table");
|
||||
cmd.set_start_zone(playToStack ? "stack" : "table");
|
||||
}
|
||||
|
||||
if (deleteInPhase != 0) {
|
||||
cmd.set_delete_in_phase(deleteInPhase);
|
||||
}
|
||||
|
||||
player->getPlayerActions()->sendGameCommand(cmd);
|
||||
}
|
||||
delArrow();
|
||||
|
||||
@@ -82,10 +82,11 @@ class ArrowDragItem : public ArrowItem
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
int deleteInPhase;
|
||||
QList<ArrowDragItem *> childArrows;
|
||||
|
||||
public:
|
||||
ArrowDragItem(Player *_owner, ArrowTarget *_startItem, const QColor &_color);
|
||||
ArrowDragItem(Player *_owner, ArrowTarget *_startItem, const QColor &_color, int _deleteInPhase);
|
||||
void addChildArrow(ArrowDragItem *childArrow);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "../../client/settings/cache_settings.h"
|
||||
#include "../../interface/widgets/tabs/tab_game.h"
|
||||
#include "../game_scene.h"
|
||||
#include "../phase.h"
|
||||
#include "../player/player.h"
|
||||
#include "../zones/card_zone.h"
|
||||
#include "../zones/logic/view_zone_logic.h"
|
||||
@@ -275,9 +276,14 @@ void CardItem::drawArrow(const QColor &arrowColor)
|
||||
if (owner->getGame()->getPlayerManager()->isSpectator())
|
||||
return;
|
||||
|
||||
Player *arrowOwner =
|
||||
owner->getGame()->getPlayerManager()->getActiveLocalPlayer(owner->getGame()->getGameState()->getActivePlayer());
|
||||
ArrowDragItem *arrow = new ArrowDragItem(arrowOwner, this, arrowColor);
|
||||
auto *game = owner->getGame();
|
||||
Player *arrowOwner = game->getPlayerManager()->getActiveLocalPlayer(game->getGameState()->getActivePlayer());
|
||||
int phase = 0; // 0 means to not set the phase
|
||||
if (SettingsCache::instance().getDoNotDeleteArrowsInSubPhases()) {
|
||||
int currentPhase = game->getGameState()->getCurrentPhase();
|
||||
phase = Phases::getLastSubphase(currentPhase) + 1;
|
||||
}
|
||||
ArrowDragItem *arrow = new ArrowDragItem(arrowOwner, this, arrowColor, phase);
|
||||
scene()->addItem(arrow);
|
||||
arrow->grabMouse();
|
||||
|
||||
@@ -288,7 +294,7 @@ void CardItem::drawArrow(const QColor &arrowColor)
|
||||
if (card->getZone() != zone)
|
||||
continue;
|
||||
|
||||
ArrowDragItem *childArrow = new ArrowDragItem(arrowOwner, card, arrowColor);
|
||||
ArrowDragItem *childArrow = new ArrowDragItem(arrowOwner, card, arrowColor, phase);
|
||||
scene()->addItem(childArrow);
|
||||
arrow->addChildArrow(childArrow);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,28 @@ Phase Phases::getPhase(int phase)
|
||||
}
|
||||
}
|
||||
|
||||
int Phases::getLastSubphase(int phase)
|
||||
{
|
||||
if (0 <= phase && phase < Phases::phaseTypesCount) {
|
||||
return subPhasesEnd[phase];
|
||||
} else {
|
||||
return phase;
|
||||
}
|
||||
}
|
||||
|
||||
QVector<int> getSubPhasesEnd()
|
||||
{
|
||||
QVector<int> array(Phases::phaseTypesCount);
|
||||
for (int phaseEnd = Phases::phaseTypesCount - 1; phaseEnd >= 0;) {
|
||||
int subPhase = phaseEnd;
|
||||
for (; subPhase >= 0 && Phases::phases[phaseEnd].color == Phases::phases[subPhase].color; --subPhase) {
|
||||
array[subPhase] = phaseEnd;
|
||||
}
|
||||
phaseEnd = subPhase;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
const Phase Phases::unknownPhase(QT_TRANSLATE_NOOP("Phase", "Unknown Phase"), "black", "unknown_phase");
|
||||
const Phase Phases::phases[Phases::phaseTypesCount] = {
|
||||
{QT_TRANSLATE_NOOP("Phase", "Untap"), "green", "untap_step"},
|
||||
@@ -35,3 +57,4 @@ const Phase Phases::phases[Phases::phaseTypesCount] = {
|
||||
{QT_TRANSLATE_NOOP("Phase", "End of Combat"), "red", "end_combat"},
|
||||
{QT_TRANSLATE_NOOP("Phase", "Second Main"), "blue", "main_2"},
|
||||
{QT_TRANSLATE_NOOP("Phase", "End/Cleanup"), "green", "end_step"}};
|
||||
const QVector<int> Phases::subPhasesEnd = getSubPhasesEnd();
|
||||
|
||||
@@ -28,8 +28,10 @@ struct Phases
|
||||
const static int phaseTypesCount = 11;
|
||||
const static Phase unknownPhase;
|
||||
const static Phase phases[phaseTypesCount];
|
||||
const static QVector<int> subPhasesEnd;
|
||||
|
||||
static Phase getPhase(int);
|
||||
static int getLastSubphase(int phase);
|
||||
};
|
||||
|
||||
#endif // PHASE_H
|
||||
|
||||
@@ -801,6 +801,10 @@ UserInterfaceSettingsPage::UserInterfaceSettingsPage()
|
||||
connect(&playToStackCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
||||
&SettingsCache::setPlayToStack);
|
||||
|
||||
doNotDeleteArrowsInSubPhasesCheckBox.setChecked(SettingsCache::instance().getDoNotDeleteArrowsInSubPhases());
|
||||
connect(&doNotDeleteArrowsInSubPhasesCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
||||
&SettingsCache::setDoNotDeleteArrowsInSubPhases);
|
||||
|
||||
closeEmptyCardViewCheckBox.setChecked(SettingsCache::instance().getCloseEmptyCardView());
|
||||
connect(&closeEmptyCardViewCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
||||
&SettingsCache::setCloseEmptyCardView);
|
||||
@@ -821,10 +825,11 @@ UserInterfaceSettingsPage::UserInterfaceSettingsPage()
|
||||
generalGrid->addWidget(&doubleClickToPlayCheckBox, 0, 0);
|
||||
generalGrid->addWidget(&clickPlaysAllSelectedCheckBox, 1, 0);
|
||||
generalGrid->addWidget(&playToStackCheckBox, 2, 0);
|
||||
generalGrid->addWidget(&closeEmptyCardViewCheckBox, 3, 0);
|
||||
generalGrid->addWidget(&focusCardViewSearchBarCheckBox, 4, 0);
|
||||
generalGrid->addWidget(&annotateTokensCheckBox, 5, 0);
|
||||
generalGrid->addWidget(&useTearOffMenusCheckBox, 6, 0);
|
||||
generalGrid->addWidget(&doNotDeleteArrowsInSubPhasesCheckBox, 3, 0);
|
||||
generalGrid->addWidget(&closeEmptyCardViewCheckBox, 4, 0);
|
||||
generalGrid->addWidget(&focusCardViewSearchBarCheckBox, 5, 0);
|
||||
generalGrid->addWidget(&annotateTokensCheckBox, 6, 0);
|
||||
generalGrid->addWidget(&useTearOffMenusCheckBox, 7, 0);
|
||||
|
||||
generalGroupBox = new QGroupBox;
|
||||
generalGroupBox->setLayout(generalGrid);
|
||||
@@ -942,6 +947,7 @@ void UserInterfaceSettingsPage::retranslateUi()
|
||||
doubleClickToPlayCheckBox.setText(tr("&Double-click cards to play them (instead of single-click)"));
|
||||
clickPlaysAllSelectedCheckBox.setText(tr("&Clicking plays all selected cards (instead of just the clicked card)"));
|
||||
playToStackCheckBox.setText(tr("&Play all nonlands onto the stack (not the battlefield) by default"));
|
||||
doNotDeleteArrowsInSubPhasesCheckBox.setText(tr("Do not delete &arrows inside of subphases"));
|
||||
closeEmptyCardViewCheckBox.setText(tr("Close card view window when last card is removed"));
|
||||
focusCardViewSearchBarCheckBox.setText(tr("Auto focus search bar when card view window is opened"));
|
||||
annotateTokensCheckBox.setText(tr("Annotate card text on tokens"));
|
||||
|
||||
@@ -163,6 +163,7 @@ private:
|
||||
QCheckBox doubleClickToPlayCheckBox;
|
||||
QCheckBox clickPlaysAllSelectedCheckBox;
|
||||
QCheckBox playToStackCheckBox;
|
||||
QCheckBox doNotDeleteArrowsInSubPhasesCheckBox;
|
||||
QCheckBox closeEmptyCardViewCheckBox;
|
||||
QCheckBox focusCardViewSearchBarCheckBox;
|
||||
QCheckBox annotateTokensCheckBox;
|
||||
|
||||
@@ -182,6 +182,9 @@ void SettingsCache::setClickPlaysAllSelected(QT_STATE_CHANGED_T /* _clickPlaysAl
|
||||
void SettingsCache::setPlayToStack(QT_STATE_CHANGED_T /* _playToStack */)
|
||||
{
|
||||
}
|
||||
void SettingsCache::setDoNotDeleteArrowsInSubPhases(QT_STATE_CHANGED_T /* _doNotDeleteArrowsInSubPhases */)
|
||||
{
|
||||
}
|
||||
void SettingsCache::setStartingHandSize(int /* _startingHandSize */)
|
||||
{
|
||||
}
|
||||
@@ -445,4 +448,4 @@ void SettingsCache::setRoundCardCorners(bool /* _roundCardCorners */)
|
||||
|
||||
void CardPictureLoader::clearPixmapCache(CardInfoPtr /* card */)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1210,7 +1210,9 @@ Server_AbstractPlayer::cmdCreateArrow(const Command_CreateArrow &cmd, ResponseCo
|
||||
}
|
||||
}
|
||||
|
||||
auto arrow = new Server_Arrow(newArrowId(), startCard, targetItem, cmd.arrow_color());
|
||||
int currentPhase = game->getActivePhase();
|
||||
int deletionPhase = cmd.has_delete_in_phase() ? cmd.delete_in_phase() : currentPhase;
|
||||
auto arrow = new Server_Arrow(newArrowId(), startCard, targetItem, cmd.arrow_color(), currentPhase, deletionPhase);
|
||||
addArrow(arrow);
|
||||
|
||||
Event_CreateArrow event;
|
||||
|
||||
@@ -6,8 +6,14 @@
|
||||
|
||||
#include <libcockatrice/protocol/pb/serverinfo_arrow.pb.h>
|
||||
|
||||
Server_Arrow::Server_Arrow(int _id, Server_Card *_startCard, Server_ArrowTarget *_targetItem, const color &_arrowColor)
|
||||
: id(_id), startCard(_startCard), targetItem(_targetItem), arrowColor(_arrowColor)
|
||||
Server_Arrow::Server_Arrow(int _id,
|
||||
Server_Card *_startCard,
|
||||
Server_ArrowTarget *_targetItem,
|
||||
const color &_arrowColor,
|
||||
int _phaseCreated,
|
||||
int _phaseDeleted)
|
||||
: id(_id), startCard(_startCard), targetItem(_targetItem), arrowColor(_arrowColor), phaseCreated(_phaseCreated),
|
||||
phaseDeleted(_phaseDeleted)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -14,9 +14,15 @@ private:
|
||||
Server_Card *startCard;
|
||||
Server_ArrowTarget *targetItem;
|
||||
color arrowColor;
|
||||
int phaseCreated, phaseDeleted;
|
||||
|
||||
public:
|
||||
Server_Arrow(int _id, Server_Card *_startCard, Server_ArrowTarget *_targetItem, const color &_arrowColor);
|
||||
Server_Arrow(int _id,
|
||||
Server_Card *_startCard,
|
||||
Server_ArrowTarget *_targetItem,
|
||||
const color &_arrowColor,
|
||||
int _phaseCreated,
|
||||
int _phaseDeleted);
|
||||
int getId() const
|
||||
{
|
||||
return id;
|
||||
@@ -45,6 +51,10 @@ public:
|
||||
{
|
||||
return arrowColor;
|
||||
}
|
||||
bool checkPhaseDeletion(int phase) const // returns true if the arrow should be deleted in this phase
|
||||
{
|
||||
return phase < phaseCreated || phase >= phaseDeleted;
|
||||
}
|
||||
|
||||
void getInfo(ServerInfo_Arrow *info);
|
||||
};
|
||||
|
||||
@@ -654,6 +654,8 @@ void Server_Game::setActivePlayer(int _activePlayer)
|
||||
{
|
||||
QMutexLocker locker(&gameMutex);
|
||||
|
||||
removeArrows(0, true);
|
||||
|
||||
activePlayer = _activePlayer;
|
||||
|
||||
Event_SetActivePlayer event;
|
||||
@@ -663,30 +665,35 @@ void Server_Game::setActivePlayer(int _activePlayer)
|
||||
setActivePhase(0);
|
||||
}
|
||||
|
||||
void Server_Game::setActivePhase(int _activePhase)
|
||||
void Server_Game::setActivePhase(int newPhase)
|
||||
{
|
||||
QMutexLocker locker(&gameMutex);
|
||||
|
||||
for (auto *player : getPlayers().values()) {
|
||||
QList<Server_Arrow *> toDelete = player->getArrows().values();
|
||||
for (int i = 0; i < toDelete.size(); ++i) {
|
||||
Server_Arrow *a = toDelete[i];
|
||||
|
||||
Event_DeleteArrow event;
|
||||
event.set_arrow_id(a->getId());
|
||||
sendGameEventContainer(prepareGameEvent(event, player->getPlayerId()));
|
||||
|
||||
player->deleteArrow(a->getId());
|
||||
}
|
||||
}
|
||||
|
||||
activePhase = _activePhase;
|
||||
removeArrows(newPhase);
|
||||
activePhase = newPhase;
|
||||
|
||||
Event_SetActivePhase event;
|
||||
event.set_phase(activePhase);
|
||||
sendGameEventContainer(prepareGameEvent(event, -1));
|
||||
}
|
||||
|
||||
void Server_Game::removeArrows(int newPhase, bool force)
|
||||
{
|
||||
QMutexLocker locker(&gameMutex);
|
||||
|
||||
for (auto *anyPlayer : getPlayers().values()) {
|
||||
for (auto *arrowToDelete : anyPlayer->getArrows().values()) { // values creates a copy
|
||||
if (force || arrowToDelete->checkPhaseDeletion(newPhase)) {
|
||||
Event_DeleteArrow event;
|
||||
event.set_arrow_id(arrowToDelete->getId());
|
||||
sendGameEventContainer(prepareGameEvent(event, anyPlayer->getPlayerId()));
|
||||
|
||||
anyPlayer->deleteArrow(arrowToDelete->getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Server_Game::nextTurn()
|
||||
{
|
||||
QMutexLocker locker(&gameMutex);
|
||||
|
||||
@@ -198,8 +198,9 @@ public:
|
||||
{
|
||||
return activePhase;
|
||||
}
|
||||
void setActivePlayer(int _activePlayer);
|
||||
void setActivePhase(int _activePhase);
|
||||
void setActivePlayer(int newPlayer);
|
||||
void setActivePhase(int newPhase);
|
||||
void removeArrows(int newPhase, bool force = false);
|
||||
void nextTurn();
|
||||
int getSecondsElapsed() const
|
||||
{
|
||||
|
||||
@@ -27,4 +27,9 @@ message Command_CreateArrow {
|
||||
|
||||
// the color of the arrow
|
||||
optional color arrow_color = 7;
|
||||
|
||||
// the phase that this arrow is deleted in, arrows are deleted when this or a later phase is activated and also
|
||||
// when the phase moves back before the current phase or the turn is passed, when not set the arrow is deleted
|
||||
// immediately when the phase is changed
|
||||
optional sint32 delete_in_phase = 8;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user