* Fixed wrong selection count in choose ability mode dialog (cards like Planewide Celebration);

This commit is contained in:
Oleg Agafonov 2019-12-07 01:48:39 +04:00
parent 57cb023f78
commit 1d20069ddf
2 changed files with 58 additions and 21 deletions

View file

@ -710,9 +710,9 @@ public class HumanPlayer extends PlayerImpl {
if (!isExecutingMacro()) {
String selectedNames = target.getTargetedName(game);
game.fireSelectTargetEvent(playerId, new MessageToClient(target.getMessage()
+ "<br> Amount remaining: " + target.getAmountRemaining()
+ (selectedNames.isEmpty() ? "" : ", selected: " + selectedNames),
getRelatedObjectName(source, game)),
+ "<br> Amount remaining: " + target.getAmountRemaining()
+ (selectedNames.isEmpty() ? "" : ", selected: " + selectedNames),
getRelatedObjectName(source, game)),
target.possibleTargets(source == null ? null : source.getSourceId(), playerId, game),
target.isRequired(source),
getOptions(target, null));
@ -725,7 +725,7 @@ public class HumanPlayer extends PlayerImpl {
boolean removeMode = target.getTargets().contains(targetId)
&& chooseUse(outcome, "What do you want to do with " + (targetObject != null ? targetObject.getLogName() : "target") + "?", "",
"Remove from selected", "Add extra amount", source, game);
"Remove from selected", "Add extra amount", source, game);
if (removeMode) {
target.remove(targetId);
@ -862,9 +862,9 @@ public class HumanPlayer extends PlayerImpl {
if (!skippedAtLeastOnce
|| (playerId.equals(game.getActivePlayerId())
&& !controllingPlayer
.getUserData()
.getUserSkipPrioritySteps()
.isStopOnAllEndPhases())) {
.getUserData()
.getUserSkipPrioritySteps()
.isStopOnAllEndPhases())) {
skippedAtLeastOnce = true;
if (passWithManaPoolCheck(game)) {
return false;
@ -896,9 +896,9 @@ public class HumanPlayer extends PlayerImpl {
if (haveNewObjectsOnStack
&& (playerId.equals(game.getActivePlayerId())
&& controllingPlayer
.getUserData()
.getUserSkipPrioritySteps()
.isStopOnStackNewObjects())) {
.getUserData()
.getUserSkipPrioritySteps()
.isStopOnStackNewObjects())) {
// new objects on stack -- disable "pass until stack resolved"
passedUntilStackResolved = false;
} else {
@ -1235,8 +1235,8 @@ public class HumanPlayer extends PlayerImpl {
if (passedAllTurns
|| passedUntilEndStepBeforeMyTurn
|| (!getControllingPlayersUserData(game)
.getUserSkipPrioritySteps()
.isStopOnDeclareAttackers()
.getUserSkipPrioritySteps()
.isStopOnDeclareAttackers()
&& (passedTurn
|| passedTurnSkipStack
|| passedUntilEndOfTurn
@ -1419,7 +1419,7 @@ public class HumanPlayer extends PlayerImpl {
/**
* Selects a defender for an attacker and adds the attacker to combat
*
* @param defenders - list of possible defender
* @param defenders - list of possible defender
* @param attackerId - UUID of attacker
* @param game
* @return
@ -1817,17 +1817,20 @@ public class HumanPlayer extends PlayerImpl {
Map<UUID, String> modeMap = new LinkedHashMap<>();
AvailableModes:
for (Mode mode : modes.getAvailableModes(source, game)) {
int timesSelected = 0;
int timesSelected = modes.getSelectedStats(mode.getId());
for (UUID selectedModeId : modes.getSelectedModes()) {
Mode selectedMode = modes.get(selectedModeId);
if (mode.getId().equals(selectedMode.getId())) {
// mode selected
if (modes.isEachModeMoreThanOnce()) {
timesSelected++;
// can select again
} else {
continue AvailableModes;
// hide mode from dialog
continue AvailableModes; // TODO: test 2x cheat here
}
}
}
if (mode.getTargets().canChoose(source.getSourceId(), source.getControllerId(), game)) { // and needed targets have to be available
String modeText = mode.getEffects().getText(mode);
if (obj != null) {
@ -1852,11 +1855,12 @@ public class HumanPlayer extends PlayerImpl {
if (response.getUUID() != null) {
for (Mode mode : modes.getAvailableModes(source, game)) {
if (mode.getId().equals(response.getUUID())) {
// TODO: add checks on 2x selects (cheaters can rewrite client side code and select same mode multiple times)
// reason: wrong setup eachModeMoreThanOnce and eachModeOnlyOnce in many cards
return mode;
}
}
}
else if (modes.getSelectedModes().size() >= modes.getMinModes()) {
} else if (modes.getSelectedModes().size() >= modes.getMinModes()) {
/* let the player cancel mode selection if they do not need to select any further modes */
done = true;
}

View file

@ -19,13 +19,15 @@ import java.util.*;
public class Modes extends LinkedHashMap<UUID, Mode> {
private Mode currentMode; // the current mode of the selected modes
private final List<UUID> selectedModes = new ArrayList<>();
private final List<UUID> selectedModes = new ArrayList<>(); // all selected modes (this + duplicate)
private final Map<UUID, Mode> duplicateModes = new LinkedHashMap<>(); // for 2x selects: copy mode and put it to duplicate list
private final Map<UUID, UUID> duplicateToOriginalModeRefs = new LinkedHashMap<>(); // for 2x selects: stores ref from duplicate to original mode
private int minModes;
private int maxModes;
private TargetController modeChooser;
private boolean eachModeMoreThanOnce; // each mode can be selected multiple times during one choice
private boolean eachModeOnlyOnce; // state if each mode can be chosen only once as long as the source object exists
private final Map<UUID, Mode> duplicateModes = new LinkedHashMap<>();
private OptionalAdditionalModeSourceCosts optionalAdditionalModeSourceCosts = null; // only set if costs have to be paid
private Filter maxModesFilter = null; // calculates the max number of available modes
private boolean isRandom = false;
@ -49,6 +51,8 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
for (Map.Entry<UUID, Mode> entry : modes.duplicateModes.entrySet()) {
duplicateModes.put(entry.getKey(), entry.getValue().copy());
}
duplicateToOriginalModeRefs.putAll(modes.duplicateToOriginalModeRefs);
this.minModes = modes.minModes;
this.maxModes = modes.maxModes;
this.selectedModes.addAll(modes.getSelectedModes());
@ -116,6 +120,32 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
return selectedModes;
}
public int getSelectedStats(UUID modeId) {
int count = 0;
if (this.selectedModes.contains(modeId)) {
// single select
count++;
// multiple select (all 2x select generate new duplicate mode)
UUID originalId;
if (this.duplicateModes.containsKey(modeId)) {
// modeId is duplicate
originalId = this.duplicateToOriginalModeRefs.get(modeId);
} else {
// modeId is original
originalId = modeId;
}
for (UUID id : this.duplicateToOriginalModeRefs.values()) {
if (id.equals(originalId)) {
count++;
}
}
}
return count;
}
public void setMinModes(int minModes) {
this.minModes = minModes;
}
@ -168,6 +198,7 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
if (this.size() > 1) {
this.selectedModes.clear();
this.duplicateModes.clear();
this.duplicateToOriginalModeRefs.clear();
if (this.isRandom) {
List<Mode> modes = getAvailableModes(source, game);
this.addSelectedMode(modes.get(RandomUtil.nextInt(modes.size())).getId());
@ -286,9 +317,11 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
private void addSelectedMode(UUID modeId) {
if (selectedModes.contains(modeId) && eachModeMoreThanOnce) {
Mode duplicateMode = get(modeId).copy();
UUID originalId = modeId;
duplicateMode.setRandomId();
modeId = duplicateMode.getId();
duplicateModes.put(modeId, duplicateMode);
duplicateToOriginalModeRefs.put(duplicateMode.getId(), originalId);
}
this.selectedModes.add(modeId);
@ -329,7 +362,7 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
nonAvailableModes = getAlreadySelectedModes(source, game);
}
for (Mode mode : this.values()) {
if (isEachModeOnlyOnce() && nonAvailableModes != null && nonAvailableModes.contains(mode.getId())) {
if (isEachModeOnlyOnce() && nonAvailableModes.contains(mode.getId())) {
continue;
}
availableModes.add(mode);