Vote: replace hidden keywords with timestamped properties

This commit is contained in:
Hans Mackowiak
2020-03-19 06:22:44 +00:00
committed by Michael Kamensky
parent d35a2cdead
commit 33d83dc0c5
20 changed files with 258 additions and 82 deletions

View File

@@ -2323,7 +2323,7 @@ public class ComputerUtil {
return chosen; return chosen;
} }
public static Object vote(Player ai, List<Object> options, SpellAbility sa, Multimap<Object, Player> votes) { public static Object vote(Player ai, List<Object> options, SpellAbility sa, Multimap<Object, Player> votes, Player forPlayer) {
final Card source = sa.getHostCard(); final Card source = sa.getHostCard();
final Player controller = source.getController(); final Player controller = source.getController();
final Game game = controller.getGame(); final Game game = controller.getGame();

View File

@@ -513,8 +513,8 @@ public class PlayerControllerAi extends PlayerController {
} }
@Override @Override
public Object vote(SpellAbility sa, String prompt, List<Object> options, ListMultimap<Object, Player> votes) { public Object vote(SpellAbility sa, String prompt, List<Object> options, ListMultimap<Object, Player> votes, Player forPlayer) {
return ComputerUtil.vote(player, options, sa, votes); return ComputerUtil.vote(player, options, sa, votes, forPlayer);
} }
@Override @Override

View File

@@ -46,6 +46,12 @@ public class VoteAi extends SpellAbilityAi {
@Override @Override
public int chooseNumber(Player player, SpellAbility sa, int min, int max, Map<String, Object> params) { public int chooseNumber(Player player, SpellAbility sa, int min, int max, Map<String, Object> params) {
if (params.containsKey("Voter")) {
Player p = (Player)params.get("Voter");
if (p.isOpponentOf(player)) {
return min;
}
}
if (sa.getActivatingPlayer().isOpponentOf(player)) { if (sa.getActivatingPlayer().isOpponentOf(player)) {
return min; return min;
} }

View File

@@ -914,4 +914,17 @@ public class Game {
} }
return false; return false;
} }
public Player getControlVote() {
Player result = null;
long maxValue = 0;
for (Player p : getPlayers()) {
Long v = p.getHighestControlVote();
if (v != null && v > maxValue) {
maxValue = v;
result = p;
}
}
return result;
}
} }

View File

@@ -177,7 +177,6 @@ public class StaticEffect {
final CardCollectionView remove() { final CardCollectionView remove() {
final CardCollectionView affectedCards = getAffectedCards(); final CardCollectionView affectedCards = getAffectedCards();
final List<Player> affectedPlayers = getAffectedPlayers(); final List<Player> affectedPlayers = getAffectedPlayers();
//final Map<String, String> params = getParams();
String changeColorWordsTo = null; String changeColorWordsTo = null;
@@ -245,6 +244,10 @@ public class StaticEffect {
p.removeMaxLandPlays(getTimestamp()); p.removeMaxLandPlays(getTimestamp());
p.removeMaxLandPlaysInfinite(getTimestamp()); p.removeMaxLandPlaysInfinite(getTimestamp());
p.removeControlVote(getTimestamp());
p.removeAdditionalVote(getTimestamp());
p.removeAdditionalOptionalVote(getTimestamp());
} }
// modify the affected card // modify the affected card

View File

@@ -1,6 +1,7 @@
package forge.game.ability.effects; package forge.game.ability.effects;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -9,9 +10,9 @@ import forge.game.ability.AbilityKey;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.ListMultimap; import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import forge.game.Game; import forge.game.Game;
import forge.game.ability.AbilityFactory; import forge.game.ability.AbilityFactory;
@@ -19,10 +20,7 @@ import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect; import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardLists; import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.player.PlayerCollection;
import forge.game.player.PlayerPredicates;
import forge.game.spellability.AbilitySub; import forge.game.spellability.AbilitySub;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.game.trigger.TriggerType; import forge.game.trigger.TriggerType;
@@ -67,33 +65,29 @@ public class VoteEffect extends SpellAbilityEffect {
return; return;
} }
// starting with the activator
int pSize = tgtPlayers.size();
Player activator = sa.getActivatingPlayer(); Player activator = sa.getActivatingPlayer();
while (tgtPlayers.contains(activator) && !activator.equals(Iterables.getFirst(tgtPlayers, null))) {
tgtPlayers.add(pSize - 1, tgtPlayers.remove(0)); // starting with the activator
int aidx = tgtPlayers.indexOf(activator);
if (aidx != -1) {
Collections.rotate(tgtPlayers, -aidx);
} }
ListMultimap<Object, Player> votes = ArrayListMultimap.create(); ListMultimap<Object, Player> votes = ArrayListMultimap.create();
Player voter = null; Player voter = game.getControlVote();
PlayerCollection voters = game.getPlayers().filter(PlayerPredicates.hasKeyword("You choose how each player votes this turn."));
if (voters.size() > 1) {
List<Card> illusions = CardLists.filter(voters.getCardsIn(ZoneType.Command), CardPredicates.nameEquals("Illusion of Choice Effect"));
voter = Collections.max(illusions, CardPredicates.compareByTimestamp()).getController();
} else if (voters.size() == 1) {
voter = voters.get(0);
}
for (final Player p : tgtPlayers) { for (final Player p : tgtPlayers) {
int voteAmount = p.getKeywords().getAmount("You get an additional vote.") + 1; int voteAmount = p.getAdditionalVotesAmount() + 1;
int optionalVotes = p.getKeywords().getAmount("You may vote an additional time."); int optionalVotes = p.getAdditionalOptionalVotesAmount();
voteAmount += p.getController().chooseNumber(sa, Localizer.getInstance().getMessage("lblHowManyAdditionalVotesDoYouWant"), 0, optionalVotes);
Player realVoter = voter == null ? p : voter; Player realVoter = voter == null ? p : voter;
Map<String, Object> params = Maps.newHashMap();
params.put("Voter", realVoter);
voteAmount += p.getController().chooseNumber(sa, Localizer.getInstance().getMessage("lblHowManyAdditionalVotesDoYouWant"), 0, optionalVotes, params);
for (int i = 0; i < voteAmount; i++) { for (int i = 0; i < voteAmount; i++) {
Object result = realVoter.getController().vote(sa, host + Localizer.getInstance().getMessage("lblVote") + ":", voteType, votes); Object result = realVoter.getController().vote(sa, host + Localizer.getInstance().getMessage("lblVote") + ":", voteType, votes, p);
votes.put(result, p); votes.put(result, p);
host.getGame().getAction().nofityOfValue(sa, p, result + "\r\n" + Localizer.getInstance().getMessage("lblCurrentVote") + ":" + votes, p); host.getGame().getAction().nofityOfValue(sa, p, result + "\r\n" + Localizer.getInstance().getMessage("lblCurrentVote") + ":" + votes, p);
@@ -104,34 +98,49 @@ public class VoteEffect extends SpellAbilityEffect {
runParams.put(AbilityKey.AllVotes, votes); runParams.put(AbilityKey.AllVotes, votes);
game.getTriggerHandler().runTrigger(TriggerType.Vote, runParams, false); game.getTriggerHandler().runTrigger(TriggerType.Vote, runParams, false);
List<String> subAbs = Lists.newArrayList(); if (sa.hasParam("EachVote")) {
final List<Object> mostVotes = getMostVotes(votes); for (Map.Entry<Object, Collection<Player>> e : votes.asMap().entrySet()) {
if (sa.hasParam("Tied") && mostVotes.size() > 1) { final SpellAbility action = AbilityFactory.getAbility(host, sa.getParam("Vote" + e.getKey().toString()));
subAbs.add(sa.getParam("Tied"));
} else if (sa.hasParam("VoteSubAbility")) {
for (final Object o : mostVotes) {
host.addRemembered(o);
}
subAbs.add(sa.getParam("VoteSubAbility"));
} else {
for (Object type : mostVotes) {
subAbs.add(sa.getParam("Vote" + type.toString()));
}
}
if (sa.hasParam("StoreVoteNum")) {
for (final Object type : voteType) {
host.setSVar("VoteNum" + type, "Number$" + votes.get(type).size());
}
} else {
for (final String subAb : subAbs) {
final SpellAbility action = AbilityFactory.getAbility(host.getSVar(subAb), host);
action.setActivatingPlayer(sa.getActivatingPlayer()); action.setActivatingPlayer(sa.getActivatingPlayer());
((AbilitySub) action).setParent(sa); ((AbilitySub) action).setParent(sa);
AbilityUtils.resolve(action);
for (Player p : e.getValue()) {
host.addRemembered(p);
AbilityUtils.resolve(action);
host.removeRemembered(p);
}
}
} else {
List<String> subAbs = Lists.newArrayList();
final List<Object> mostVotes = getMostVotes(votes);
if (sa.hasParam("Tied") && mostVotes.size() > 1) {
subAbs.add(sa.getParam("Tied"));
} else if (sa.hasParam("VoteSubAbility")) {
for (final Object o : mostVotes) {
host.addRemembered(o);
}
subAbs.add(sa.getParam("VoteSubAbility"));
} else {
for (Object type : mostVotes) {
subAbs.add(sa.getParam("Vote" + type.toString()));
}
}
if (sa.hasParam("StoreVoteNum")) {
for (final Object type : voteType) {
host.setSVar("VoteNum" + type, "Number$" + votes.get(type).size());
}
} else {
for (final String subAb : subAbs) {
final SpellAbility action = AbilityFactory.getAbility(host, subAb);
action.setActivatingPlayer(sa.getActivatingPlayer());
((AbilitySub) action).setParent(sa);
AbilityUtils.resolve(action);
}
}
if (sa.hasParam("VoteSubAbility")) {
host.clearRemembered();
} }
}
if (sa.hasParam("VoteSubAbility")) {
host.clearRemembered();
} }
} }

View File

@@ -3938,7 +3938,9 @@ public class Card extends GameEntity implements Comparable<Card> {
keywordsGrantedByTextChanges.add(newKw); keywordsGrantedByTextChanges.add(newKw);
} }
} }
addChangedCardKeywordsInternal(addKeywords, removeKeywords, false, false, timestamp, true); if (!addKeywords.isEmpty() || !removeKeywords.isEmpty()) {
addChangedCardKeywordsInternal(addKeywords, removeKeywords, false, false, timestamp, true);
}
} }
private void updateKeywordsOnRemoveChangedText(final KeywordsChange k) { private void updateKeywordsOnRemoveChangedText(final KeywordsChange k) {

View File

@@ -162,6 +162,10 @@ public class Player extends GameEntity implements Comparable<Player> {
private Card blessingEffect = null; private Card blessingEffect = null;
private Card keywordEffect = null; private Card keywordEffect = null;
private Map<Long, Integer> additionalVotes = Maps.newHashMap();
private Map<Long, Integer> additionalOptionalVotes = Maps.newHashMap();
private SortedSet<Long> controlVotes = Sets.newTreeSet();
private final AchievementTracker achievementTracker = new AchievementTracker(); private final AchievementTracker achievementTracker = new AchievementTracker();
private final PlayerView view; private final PlayerView view;
@@ -3067,4 +3071,86 @@ public class Player extends GameEntity implements Comparable<Player> {
this.updateZoneForView(com); this.updateZoneForView(com);
return keywordEffect; return keywordEffect;
} }
public void addAdditionalVote(long timestamp, int value) {
additionalVotes.put(timestamp, value);
getView().updateAdditionalVote(this);
getGame().fireEvent(new GameEventPlayerStatsChanged(this, false));
}
public void removeAdditionalVote(long timestamp) {
if (additionalVotes.remove(timestamp) != null) {
getView().updateAdditionalVote(this);
getGame().fireEvent(new GameEventPlayerStatsChanged(this, false));
}
}
public int getAdditionalVotesAmount() {
int value = 0;
for (Integer i : additionalVotes.values()) {
value += i;
}
return value;
}
public void addAdditionalOptionalVote(long timestamp, int value) {
additionalOptionalVotes.put(timestamp, value);
getView().updateOptionalAdditionalVote(this);
getGame().fireEvent(new GameEventPlayerStatsChanged(this, false));
}
public void removeAdditionalOptionalVote(long timestamp) {
if (additionalOptionalVotes.remove(timestamp) != null) {
getView().updateOptionalAdditionalVote(this);
getGame().fireEvent(new GameEventPlayerStatsChanged(this, false));
}
}
public int getAdditionalOptionalVotesAmount() {
int value = 0;
for (Integer i : additionalOptionalVotes.values()) {
value += i;
}
return value;
}
public boolean addControlVote(long timestamp) {
if (controlVotes.add(timestamp)) {
updateControlVote();
return true;
}
return false;
}
public boolean removeControlVote(long timestamp) {
if (controlVotes.remove(timestamp)) {
updateControlVote();
return true;
}
return false;
}
void updateControlVote() {
// need to update all players because it can't know
Player control = getGame().getControlVote();
for (Player pl : getGame().getPlayers()) {
pl.getView().updateControlVote(pl.equals(control));
getGame().fireEvent(new GameEventPlayerStatsChanged(pl, false));
}
}
public Set<Long> getControlVote() {
return controlVotes;
}
public void setControlVote(Set<Long> value) {
controlVotes.clear();
controlVotes.addAll(value);
updateControlVote();
}
public Long getHighestControlVote() {
if (controlVotes.isEmpty()) {
return null;
}
return controlVotes.last();
}
} }

View File

@@ -166,7 +166,7 @@ public abstract class PlayerController {
return chooseSomeType(kindOfType, sa, validTypes, invalidTypes, false); return chooseSomeType(kindOfType, sa, validTypes, invalidTypes, false);
} }
public abstract Object vote(SpellAbility sa, String prompt, List<Object> options, ListMultimap<Object, Player> votes); public abstract Object vote(SpellAbility sa, String prompt, List<Object> options, ListMultimap<Object, Player> votes, Player forPlayer);
public abstract boolean confirmReplacementEffect(ReplacementEffect replacementEffect, SpellAbility effectSA, String question); public abstract boolean confirmReplacementEffect(ReplacementEffect replacementEffect, SpellAbility effectSA, String question);
public abstract CardCollectionView getCardsToMulligan(Player firstPlayer); public abstract CardCollectionView getCardsToMulligan(Player firstPlayer);

View File

@@ -271,6 +271,27 @@ public class PlayerView extends GameEntityView {
set(TrackableProperty.NumDrawnThisTurn, p.getNumDrawnThisTurn()); set(TrackableProperty.NumDrawnThisTurn, p.getNumDrawnThisTurn());
} }
public int getAdditionalVote() {
return get(TrackableProperty.AdditionalVote);
}
public void updateAdditionalVote(Player p) {
set(TrackableProperty.AdditionalVote, p.getAdditionalVotesAmount());
}
public int getOptionalAdditionalVote() {
return get(TrackableProperty.OptionalAdditionalVote);
}
public void updateOptionalAdditionalVote(Player p) {
set(TrackableProperty.OptionalAdditionalVote, p.getAdditionalOptionalVotesAmount());
}
public boolean getControlVote() {
return get(TrackableProperty.ControlVotes);
}
public void updateControlVote(boolean val) {
set(TrackableProperty.ControlVotes, val);
}
public ImmutableMultiset<String> getKeywords() { public ImmutableMultiset<String> getKeywords() {
return get(TrackableProperty.Keywords); return get(TrackableProperty.Keywords);
} }
@@ -497,6 +518,19 @@ public class PlayerView extends GameEntityView {
details.add(Localizer.getInstance().getMessage("lblCardDrawnThisTurnHas", String.valueOf(getNumDrawnThisTurn()))); details.add(Localizer.getInstance().getMessage("lblCardDrawnThisTurnHas", String.valueOf(getNumDrawnThisTurn())));
details.add(Localizer.getInstance().getMessage("lblDamagepreventionHas", String.valueOf(getPreventNextDamage()))); details.add(Localizer.getInstance().getMessage("lblDamagepreventionHas", String.valueOf(getPreventNextDamage())));
int v = getAdditionalVote();
if (v > 0) {
details.add(Localizer.getInstance().getMessage("lblAdditionalVotes", String.valueOf(v)));
}
v = getOptionalAdditionalVote();
if (v > 0) {
details.add(Localizer.getInstance().getMessage("lblOptionalAdditionalVotes", String.valueOf(v)));
}
if (getControlVote()) {
details.add(Localizer.getInstance().getMessage("lblControlsVote"));
}
if (getIsExtraTurn()) { if (getIsExtraTurn()) {
details.add(Localizer.getInstance().getMessage("lblIsExtraTurn")); details.add(Localizer.getInstance().getMessage("lblIsExtraTurn"));
} }

View File

@@ -181,15 +181,9 @@ public class StaticAbility extends CardTraitBase implements IIdentifiable, Clone
layers.add(StaticAbilityLayer.MODIFYPT); layers.add(StaticAbilityLayer.MODIFYPT);
} }
if (hasParam("AddHiddenKeyword")) { if (hasParam("AddHiddenKeyword")
layers.add(StaticAbilityLayer.RULES); || hasParam("IgnoreEffectCost") || hasParam("Goad") || hasParam("CanBlockAny") || hasParam("CanBlockAmount")
} || hasParam("AdjustLandPlays") || hasParam("ControlVote") || hasParam("AdditionalVote") || hasParam("AdditionalOptionalVote")) {
if (hasParam("IgnoreEffectCost") || hasParam("Goad") || hasParam("CanBlockAny") || hasParam("CanBlockAmount")) {
layers.add(StaticAbilityLayer.RULES);
}
if (hasParam("AdjustLandPlays")) {
layers.add(StaticAbilityLayer.RULES); layers.add(StaticAbilityLayer.RULES);
} }

View File

@@ -513,6 +513,20 @@ public final class StaticAbilityContinuous {
} }
} }
if (params.containsKey("ControlVote")) {
p.addControlVote(se.getTimestamp());
}
if (params.containsKey("AdditionalVote")) {
String mhs = params.get("AdditionalVote");
int add = AbilityUtils.calculateAmount(hostCard, mhs, stAb);
p.addAdditionalVote(se.getTimestamp(), add);
}
if (params.containsKey("AdditionalOptionalVote")) {
String mhs = params.get("AdditionalOptionalVote");
int add = AbilityUtils.calculateAmount(hostCard, mhs, stAb);
p.addAdditionalOptionalVote(se.getTimestamp(), add);
}
if (params.containsKey("RaiseMaxHandSize")) { if (params.containsKey("RaiseMaxHandSize")) {
String rmhs = params.get("RaiseMaxHandSize"); String rmhs = params.get("RaiseMaxHandSize");
int rmax = AbilityUtils.calculateAmount(hostCard, rmhs, stAb); int rmax = AbilityUtils.calculateAmount(hostCard, rmhs, stAb);

View File

@@ -134,6 +134,9 @@ public enum TrackableProperty {
HasUnlimitedLandPlay(TrackableTypes.BooleanType), HasUnlimitedLandPlay(TrackableTypes.BooleanType),
NumLandThisTurn(TrackableTypes.IntegerType), NumLandThisTurn(TrackableTypes.IntegerType),
NumDrawnThisTurn(TrackableTypes.IntegerType), NumDrawnThisTurn(TrackableTypes.IntegerType),
AdditionalVote(TrackableTypes.IntegerType),
OptionalAdditionalVote(TrackableTypes.IntegerType),
ControlVotes(TrackableTypes.BooleanType),
Keywords(TrackableTypes.KeywordCollectionViewType, FreezeMode.IgnoresFreeze), Keywords(TrackableTypes.KeywordCollectionViewType, FreezeMode.IgnoresFreeze),
Commander(TrackableTypes.CardViewCollectionType, FreezeMode.IgnoresFreeze), Commander(TrackableTypes.CardViewCollectionType, FreezeMode.IgnoresFreeze),
CommanderCast(TrackableTypes.IntegerMapType), CommanderCast(TrackableTypes.IntegerMapType),

View File

@@ -486,7 +486,7 @@ public class PlayerControllerForTests extends PlayerController {
} }
@Override @Override
public Object vote(SpellAbility sa, String prompt, List<Object> options, ListMultimap<Object, Player> votes) { public Object vote(SpellAbility sa, String prompt, List<Object> options, ListMultimap<Object, Player> votes, Player forPlayer) {
return chooseItem(options); return chooseItem(options);
} }

View File

@@ -2,5 +2,5 @@ Name:Ballot Broker
ManaCost:2 W ManaCost:2 W
Types:Creature Human Advisor Types:Creature Human Advisor
PT:2/3 PT:2/3
S:Mode$ Continuous | Affected$ You | AddKeyword$ You may vote an additional time. | Description$ While voting, you may vote an additional time. (The votes can be for different choices or for the same choice.) S:Mode$ Continuous | Affected$ You | AdditionalOptionalVote$ 1 | Description$ While voting, you may vote an additional time. (The votes can be for different choices or for the same choice.)
Oracle:While voting, you may vote an additional time. (The votes can be for different choices or for the same choice.) Oracle:While voting, you may vote an additional time. (The votes can be for different choices or for the same choice.)

View File

@@ -2,6 +2,6 @@ Name:Brago's Representative
ManaCost:2 W ManaCost:2 W
Types:Creature Human Advisor Types:Creature Human Advisor
PT:1/4 PT:1/4
S:Mode$ Continuous | Affected$ You | AddKeyword$ You get an additional vote. | Description$ While voting, you get an additional vote. (The votes can be for different choices or for the same choice.) S:Mode$ Continuous | Affected$ You | AdditionalVote$ 1 | Description$ While voting, you get an additional vote. (The votes can be for different choices or for the same choice.)
SVar:Picture:http://www.wizards.com/global/images/magic/general/bragos_representative.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/bragos_representative.jpg
Oracle:While voting, you get an additional vote. (The votes can be for different choices or for the same choice.) Oracle:While voting, you get an additional vote. (The votes can be for different choices or for the same choice.)

View File

@@ -0,0 +1,9 @@
Name:Expropriate
ManaCost:7 U U
Types:Sorcery
A:SP$ Vote | Cost$ 7 U U | Defined$ Player | VoteType$ Time,Money | VoteTime$ DBTime | VoteMoney$ DBMoney | EachVote$ True | SubAbility$ DBChange | SpellDescription$ Councils dilemma — Starting with you, each player votes for time or money. For each time vote, take an extra turn after this one. For each money vote, choose a permanent owned by the voter and gain control of it. Exile Expropriate.
SVar:DBTime:DB$ AddTurn | Defined$ You | NumTurns$ 1
SVar:DBMoney:DB$ ChooseCard | Defined$ You | Choices$ Permanent.RememberedPlayerOwn | SubAbility$ DBControl
SVar:DBControl:DB$ GainControl | Defined$ ChosenCard | NewController$ You
SVar:DBChange:DB$ ChangeZone | Origin$ Stack | Destination$ Exile | StackDescription$ None
Oracle:Councils dilemma — Starting with you, each player votes for time or money. For each time vote, take an extra turn after this one. For each money vote, choose a permanent owned by the voter and gain control of it. Exile Expropriate.

View File

@@ -3,6 +3,6 @@ ManaCost:U
Types:Instant Types:Instant
A:SP$ Effect | Cost$ U | Name$ Illusion of Choice Effect | StaticAbilities$ STVoter | SubAbility$ DBDraw | SpellDescription$ You choose how each player votes this turn. Draw a card. A:SP$ Effect | Cost$ U | Name$ Illusion of Choice Effect | StaticAbilities$ STVoter | SubAbility$ DBDraw | SpellDescription$ You choose how each player votes this turn. Draw a card.
SVar:DBDraw:DB$ Draw | NumCards$ 1 SVar:DBDraw:DB$ Draw | NumCards$ 1
SVar:STVoter:Mode$ Continuous | EffectZone$ Command | Affected$ You | AddKeyword$ You choose how each player votes this turn. | Description$ You choose how each player votes this turn. SVar:STVoter:Mode$ Continuous | EffectZone$ Command | Affected$ You | ControlVote$ True | Description$ You choose how each player votes this turn.
AI:RemoveDeck:All AI:RemoveDeck:All
Oracle:You choose how each player votes this turn. Draw a card. Oracle:You choose how each player votes this turn. Draw a card.

View File

@@ -2010,6 +2010,9 @@ lblDamagepreventionHas=Damage prevention: {0}
lblIsExtraTurn=Extra Turn: Yes lblIsExtraTurn=Extra Turn: Yes
lblExtraTurnCountHas=Extra Turn Count: {0} lblExtraTurnCountHas=Extra Turn Count: {0}
lblAntedHas=Ante''d: {0} lblAntedHas=Ante''d: {0}
lblAdditionalVotes=You get {0} additional votes.
lblOptionalAdditionalVotes=You may vote {0} additional times.
lblControlsVote=You choose how each player votes.
#VStack.java #VStack.java
lblAlwaysYes=Always Yes lblAlwaysYes=Always Yes
lblAlwaysNo=Always No lblAlwaysNo=Always No

View File

@@ -1181,7 +1181,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override @Override
public Object vote(final SpellAbility sa, final String prompt, final List<Object> options, public Object vote(final SpellAbility sa, final String prompt, final List<Object> options,
final ListMultimap<Object, Player> votes) { final ListMultimap<Object, Player> votes, Player forPlayer) {
return getGui().one(prompt, options); return getGui().one(prompt, options);
} }