GameEntity#AddCounter now has a Source parameter

update all Effects using them
This commit is contained in:
Hanmac
2017-04-20 12:34:31 +00:00
parent de9ff7575b
commit 58d013e5be
21 changed files with 73 additions and 70 deletions

View File

@@ -1354,7 +1354,7 @@ public class ComputerUtilCard {
pumped.addChangedCardKeywords(kws, new ArrayList<String>(), false, timestamp);
Set<CounterType> types = c.getCounters().keySet();
for(CounterType ct : types) {
pumped.addCounterFireNoEvents(ct, c.getCounters(ct), true);
pumped.addCounterFireNoEvents(ct, c.getCounters(ct), c, true);
}
//Copies tap-state and extra keywords (auras, equipment, etc.)
if (c.isTapped()) {

View File

@@ -1,7 +1,13 @@
package forge.ai;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Predicate;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import forge.ai.ability.AnimateAi;
import forge.card.ColorSet;
@@ -18,14 +24,9 @@ import forge.game.player.Player;
import forge.game.spellability.Spell;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
import forge.util.collect.FCollectionView;
import forge.util.MyRandom;
import forge.util.TextUtil;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import forge.util.collect.FCollectionView;
public class ComputerUtilCost {
@@ -452,16 +453,19 @@ public class ComputerUtilCost {
// Try not to lose Planeswalker if not threatened
if (sa.getRestrictions().isPwAbility()) {
final CostPart cost = sa.getPayCosts().getCostParts().get(0);
if (cost instanceof CostRemoveCounter) {
if (cost.convertAmount() != null && cost.convertAmount() == sa.getHostCard().getCurrentLoyalty()) {
// refuse to pay if opponent has no creature threats or 50% chance otherwise
if (player.getOpponent().getCreaturesInPlay().isEmpty() || MyRandom.getRandom().nextFloat() < .5f) {
for (final CostPart part : sa.getPayCosts().getCostParts()) {
if (part instanceof CostRemoveCounter) {
if (part.convertAmount() != null && part.convertAmount() == sa.getHostCard().getCurrentLoyalty()) {
// refuse to pay if opponent has no creature threats or
// 50% chance otherwise
if (player.getOpponents().getCreaturesInPlay().isEmpty()
|| MyRandom.getRandom().nextFloat() < .5f) {
return false;
}
}
}
}
}
// KLD vehicle
if (sa.hasParam("Crew")) { // put under checkTapTypeCost?
for (final CostPart part : sa.getPayCosts().getCostParts()) {
@@ -571,7 +575,7 @@ public class ComputerUtilCost {
public static Set<String> getAvailableManaColors(Player ai, List<Card> additionalLands) {
CardCollection cardsToConsider = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), Presets.UNTAPPED);
Set<String> colorsAvailable = new HashSet<>();
Set<String> colorsAvailable = Sets.newHashSet();
if (additionalLands != null) {
GameActionUtil.grantBasicLandsManaAbilities(additionalLands);

View File

@@ -335,7 +335,7 @@ public abstract class GameState {
String[] allCounterStrings = counterString.split(",");
for (final String counterPair : allCounterStrings) {
String[] pair = counterPair.split("=", 2);
entity.addCounter(CounterType.valueOf(pair[0]), Integer.parseInt(pair[1]), false, false);
entity.addCounter(CounterType.valueOf(pair[0]), Integer.parseInt(pair[1]), null, false, false);
}
}

View File

@@ -455,14 +455,7 @@ public class Game {
if (zone == ZoneType.Stack) {
return getStackZone().getCards();
}
CardCollection cards = new CardCollection();
for (final Player p : getPlayers()) {
PlayerZone playerZone = p.getZone(zone);
if (playerZone != null) {
cards.addAll(playerZone.getCards());
}
}
return cards;
return getPlayers().getCardsIn(zone);
}
public CardCollectionView getCardsIncludePhasingIn(final ZoneType zone) {

View File

@@ -354,7 +354,7 @@ public abstract class GameEntity extends GameObject implements IIdentifiable {
abstract public void setCounters(final Map<CounterType, Integer> allCounters);
abstract public boolean canReceiveCounters(final CounterType type);
abstract public void addCounter(final CounterType counterType, final int n, final boolean applyMultiplier, final boolean fireEvents);
abstract public void addCounter(final CounterType counterType, final int n, final Card source, final boolean applyMultiplier, final boolean fireEvents);
abstract public void subtractCounter(final CounterType counterName, final int n);
abstract public void clearCounters();

View File

@@ -466,7 +466,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
}
if (sa.hasParam("WithCounters")) {
String[] parse = sa.getParam("WithCounters").split("_");
tgtC.addCounter(CounterType.getType(parse[0]), Integer.parseInt(parse[1]), true);
tgtC.addCounter(CounterType.getType(parse[0]), Integer.parseInt(parse[1]), hostCard, true);
}
if (sa.hasParam("GainControl")) {
if (sa.hasParam("NewController")) {

View File

@@ -141,7 +141,7 @@ public class CountersMoveEffect extends SpellAbilityEffect {
}
if (csum > 0) {
dest.addCounter(cType, csum, true);
dest.addCounter(cType, csum, host, true);
}
return;
} else if (sa.hasParam("ValidDefined")) {
@@ -193,7 +193,7 @@ public class CountersMoveEffect extends SpellAbilityEffect {
int cnum = player.getController().chooseNumber(sa, sb.toString(), 0, source.getCounters(cType), params);
source.subtractCounter(cType, cnum);
dest.addCounter(cType, cnum, true);
dest.addCounter(cType, cnum, host, true);
}
return;
}
@@ -247,7 +247,7 @@ public class CountersMoveEffect extends SpellAbilityEffect {
if (source.getCounters(cType) >= cntToMove) {
source.subtractCounter(cType, cntToMove);
dest.addCounter(cType, cntToMove, true);
dest.addCounter(cType, cntToMove, host, true);
}
} else {
// any counterType currently only Leech Bonder
@@ -279,7 +279,7 @@ public class CountersMoveEffect extends SpellAbilityEffect {
int chosenAmount = pc.chooseNumber(
sa, sb.toString(), 0, Math.min(tgtCounters.get(chosenType), cntToMove), params);
dest.addCounter(chosenType, chosenAmount, true);
dest.addCounter(chosenType, chosenAmount, host, true);
source.subtractCounter(chosenType, chosenAmount);
cntToMove -= chosenAmount;
}

View File

@@ -34,16 +34,17 @@ public class CountersMultiplyEffect extends SpellAbilityEffect {
}
@Override
public void resolve(SpellAbility sa) {
final Card host = sa.getHostCard();
final CounterType counterType = getCounterType(sa);
final int n = Integer.valueOf(sa.getParamOrDefault("Multiplier", "2")) - 1;
for (final Card tgtCard : getTargetCards(sa)) {
if (counterType != null) {
tgtCard.addCounter(counterType, tgtCard.getCounters(counterType) * n, false);
tgtCard.addCounter(counterType, tgtCard.getCounters(counterType) * n, host, false);
} else {
for (Map.Entry<CounterType, Integer> e : tgtCard.getCounters().entrySet()) {
tgtCard.addCounter(e.getKey(), e.getValue() * n, false);
tgtCard.addCounter(e.getKey(), e.getValue() * n, host, false);
}
}
}

View File

@@ -43,7 +43,7 @@ public class CountersNoteEffect extends SpellAbilityEffect {
for(Entry<String, String> svar : source.getSVars().entrySet()) {
String key = svar.getKey();
if (key.startsWith(NOTE_COUNTERS)) {
notee.addCounter(CounterType.getType(key.substring(NOTE_COUNTERS.length())), Integer.parseInt(svar.getValue()), false);
notee.addCounter(CounterType.getType(key.substring(NOTE_COUNTERS.length())), Integer.parseInt(svar.getValue()), source, false);
}
// TODO Probably should "remove" the svars that were temporarily used
}

View File

@@ -23,15 +23,16 @@ public class CountersProliferateEffect extends SpellAbilityEffect {
@Override
public void resolve(SpellAbility sa) {
Player controller = sa.getHostCard().getController();
final Card host = sa.getHostCard();
Player controller = host.getController();
Map<GameEntity, CounterType> proliferateChoice = controller.getController().chooseProliferation(sa);
if (proliferateChoice == null )
return;
for(Entry<GameEntity, CounterType> ge: proliferateChoice.entrySet()) {
if( ge.getKey() instanceof Player )
((Player) ge.getKey()).addCounter(ge.getValue(), 1, true);
((Player) ge.getKey()).addCounter(ge.getValue(), 1, host, true);
else if( ge.getKey() instanceof Card)
((Card) ge.getKey()).addCounter(ge.getValue(), 1, true);
((Card) ge.getKey()).addCounter(ge.getValue(), 1, host, true);
}
}
}

View File

@@ -38,6 +38,7 @@ public class CountersPutAllEffect extends SpellAbilityEffect {
@Override
public void resolve(SpellAbility sa) {
final Card host = sa.getHostCard();
final String type = sa.getParam("CounterType");
final int counterAmount = AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("CounterNum"), sa);
final String valid = sa.getParam("ValidCards");
@@ -47,18 +48,17 @@ public class CountersPutAllEffect extends SpellAbilityEffect {
CardCollectionView cards = game.getCardsIn(zone);
cards = CardLists.getValidCards(cards, valid, sa.getHostCard().getController(), sa.getHostCard());
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null) {
if (sa.usesTargeting()) {
final Player pl = sa.getTargets().getFirstTargetedPlayer();
cards = CardLists.filterControlledBy(cards, pl);
}
for (final Card tgtCard : cards) {
if (game.getZoneOf(tgtCard).is(ZoneType.Battlefield)) {
tgtCard.addCounter(CounterType.valueOf(type), counterAmount, true);
tgtCard.addCounter(CounterType.valueOf(type), counterAmount, host, true);
} else {
// adding counters to something like re-suspend cards
tgtCard.addCounter(CounterType.valueOf(type), counterAmount, false);
tgtCard.addCounter(CounterType.valueOf(type), counterAmount, host, false);
}
}
}

View File

@@ -141,10 +141,10 @@ public class CountersPutEffect extends SpellAbilityEffect {
if (eachExistingCounter) {
for(CounterType ct : choices) {
if (obj instanceof Player) {
((Player) obj).addCounter(ct, counterAmount, true);
((Player) obj).addCounter(ct, counterAmount, card, true);
}
if (obj instanceof Card) {
((Card) obj).addCounter(ct, counterAmount, true);
((Card) obj).addCounter(ct, counterAmount, card, true);
}
}
continue;
@@ -195,7 +195,7 @@ public class CountersPutEffect extends SpellAbilityEffect {
if (etbcounter) {
tgtCard.addEtbCounter(counterType, counterAmount);
} else {
tgtCard.addCounter(counterType, counterAmount, true);
tgtCard.addCounter(counterType, counterAmount, card, true);
}
if (remember) {
final int value = tgtCard.getTotalCountersToAdd();
@@ -226,14 +226,14 @@ public class CountersPutEffect extends SpellAbilityEffect {
if (etbcounter) {
tgtCard.addEtbCounter(counterType, counterAmount);
} else {
tgtCard.addCounter(counterType, counterAmount, false);
tgtCard.addCounter(counterType, counterAmount, card, false);
}
}
}
} else if (obj instanceof Player) {
// Add Counters to players!
Player pl = (Player) obj;
pl.addCounter(counterType, counterAmount, true);
pl.addCounter(counterType, counterAmount, card, true);
}
}
}

View File

@@ -78,10 +78,10 @@ public class CountersPutOrRemoveEffect extends SpellAbilityEffect {
// Put another of the chosen counter on card
final Zone zone = tgtCard.getGame().getZoneOf(tgtCard);
if (zone == null || zone.is(ZoneType.Battlefield) || zone.is(ZoneType.Stack)) {
tgtCard.addCounter(chosenType, counterAmount, true);
tgtCard.addCounter(chosenType, counterAmount, source, true);
} else {
// adding counters to something like re-suspend cards
tgtCard.addCounter(chosenType, counterAmount, false);
tgtCard.addCounter(chosenType, counterAmount, source, false);
}
} else {
tgtCard.subtractCounter(chosenType, counterAmount);

View File

@@ -50,7 +50,7 @@ public class SacrificeEffect extends SpellAbilityEffect {
return;
}
} else if (sa.hasParam("CumulativeUpkeep")) {
card.addCounter(CounterType.AGE, 1, true);
card.addCounter(CounterType.AGE, 1, card, true);
Cost cumCost = new Cost(sa.getParam("CumulativeUpkeep"), true);
Cost payCost = new Cost(ManaCost.ZERO, true);
int n = card.getCounters(CounterType.AGE);

View File

@@ -94,7 +94,7 @@ public class SetStateEffect extends SpellAbilityEffect {
}
game.fireEvent(new GameEventCardStatsChanged(tgt));
if (sa.hasParam("Mega")) {
tgt.addCounter(CounterType.P1P1, 1, true);
tgt.addCounter(CounterType.P1P1, 1, host, true);
}
if (remChanged) {
host.addRemembered(tgt);

View File

@@ -982,15 +982,15 @@ public class Card extends GameEntity implements Comparable<Card> {
countersAdded = value;
}
public final void addCounter(final CounterType counterType, final int n, final boolean applyMultiplier) {
addCounter(counterType, n, applyMultiplier, true);
public final void addCounter(final CounterType counterType, final int n, final Card source, final boolean applyMultiplier) {
addCounter(counterType, n, source, applyMultiplier, true);
}
public final void addCounterFireNoEvents(final CounterType counterType, final int n, final boolean applyMultiplier) {
addCounter(counterType, n, applyMultiplier, false);
public final void addCounterFireNoEvents(final CounterType counterType, final int n, final Card source, final boolean applyMultiplier) {
addCounter(counterType, n, source, applyMultiplier, false);
}
@Override
public void addCounter(final CounterType counterType, final int n, final boolean applyMultiplier, final boolean fireEvents) {
public void addCounter(final CounterType counterType, final int n, final Card source, final boolean applyMultiplier, final boolean fireEvents) {
int addAmount = n;
if(addAmount < 0) {
addAmount = 0; // As per rule 107.1b
@@ -998,6 +998,7 @@ public class Card extends GameEntity implements Comparable<Card> {
final Map<String, Object> repParams = Maps.newHashMap();
repParams.put("Event", "AddCounter");
repParams.put("Affected", this);
repParams.put("Source", source);
repParams.put("CounterType", counterType);
repParams.put("CounterNum", addAmount);
repParams.put("EffectOnly", applyMultiplier);
@@ -1052,6 +1053,7 @@ public class Card extends GameEntity implements Comparable<Card> {
// Run triggers
final Map<String, Object> runParams = Maps.newTreeMap();
runParams.put("Card", this);
runParams.put("Source", source);
runParams.put("CounterType", counterType);
for (int i = 0; i < addAmount; i++) {
getGame().getTriggerHandler().runTrigger(TriggerType.CounterAdded, runParams, false);
@@ -6144,7 +6146,7 @@ public class Card extends GameEntity implements Comparable<Card> {
if (isInPlay()) {
if (wither) {
addCounter(CounterType.M1M1, damageIn, true);
addCounter(CounterType.M1M1, damageIn, source, true);
damageType = DamageType.M1M1Counters;
}
else {
@@ -7160,7 +7162,7 @@ public class Card extends GameEntity implements Comparable<Card> {
public final void putEtbCounters() {
for (Map.Entry<CounterType, Integer> e : etbCounters.entrySet()) {
this.addCounter(e.getKey(), e.getValue(), true);
this.addCounter(e.getKey(), e.getValue(), this, true);
}
}
}

View File

@@ -243,7 +243,7 @@ public class CardFactoryUtil {
final Card c = game.getAction().exile(sourceCard);
int counters = AbilityUtils.calculateAmount(c, timeCounters, this);
c.addCounter(CounterType.TIME, counters, true);
c.addCounter(CounterType.TIME, counters, c, true);
String sb = String.format("%s has suspended %s with %d time counters on it.", this.getActivatingPlayer(), c.getName(), counters);
game.getGameLog().add(GameLogEntryType.STACK_RESOLVE, sb);
@@ -4142,9 +4142,9 @@ public class CardFactoryUtil {
@Override
public void run() {
if (card.isCreature()) {
card.addCounter(CounterType.P1P1, card.getSunburstValue(), true);
card.addCounter(CounterType.P1P1, card.getSunburstValue(), card, true);
} else {
card.addCounter(CounterType.CHARGE, card.getSunburstValue(), true);
card.addCounter(CounterType.CHARGE, card.getSunburstValue(), card, true);
}
}

View File

@@ -182,7 +182,7 @@ public class CostPutCounter extends CostPartWithList {
*/
@Override
protected Card doPayment(SpellAbility ability, Card targetCard){
targetCard.addCounter(this.getCounter(), 1, false);
targetCard.addCounter(this.getCounter(), 1, ability.getHostCard(), false);
return targetCard;
}

View File

@@ -110,7 +110,7 @@ public class CostRemoveCounter extends CostPartWithList {
public final void refund(final Card source) {
int refund = this.getCardList().size() == 1 ? this.cntRemoved : 1; // is wrong for Ooze Flux and Novijen Sages
for (final Card c : this.getCardList()) {
c.addCounter(this.counter, refund, false);
c.addCounter(this.counter, refund, source, false);
}
}

View File

@@ -879,12 +879,12 @@ public class Player extends GameEntity implements Comparable<Player> {
return true;
}
public final void addCounter(final CounterType counterType, final int n, final boolean applyMultiplier) {
addCounter(counterType, n, applyMultiplier, true);
public final void addCounter(final CounterType counterType, final int n, final Card source, final boolean applyMultiplier) {
addCounter(counterType, n, source, applyMultiplier, true);
}
@Override
public void addCounter(CounterType counterType, int n, boolean applyMultiplier, boolean fireEvents) {
public void addCounter(CounterType counterType, int n, final Card source, boolean applyMultiplier, boolean fireEvents) {
if (!canReceiveCounters(counterType)) {
return;
}
@@ -898,6 +898,7 @@ public class Player extends GameEntity implements Comparable<Player> {
final Map<String, Object> repParams = Maps.newHashMap();
repParams.put("Event", "AddCounter");
repParams.put("Affected", this);
repParams.put("Source", source);
repParams.put("CounterType", counterType);
repParams.put("CounterNum", addAmount);
repParams.put("EffectOnly", applyMultiplier);
@@ -919,6 +920,7 @@ public class Player extends GameEntity implements Comparable<Player> {
final Map<String, Object> runParams = Maps.newHashMap();
runParams.put("Player", this);
runParams.put("Source", this);
runParams.put("CounterType", counterType);
for (int i = 0; i < addAmount; i++) {
getGame().getTriggerHandler().runTrigger(TriggerType.CounterAdded, runParams, false);
@@ -984,7 +986,7 @@ public class Player extends GameEntity implements Comparable<Player> {
}
public final void addPoisonCounters(final int num, final Card source) {
int oldPoison = getCounters(CounterType.POISON);
addCounter(CounterType.POISON, num, false, true);
addCounter(CounterType.POISON, num, source, false, true);
if (oldPoison != getCounters(CounterType.POISON)) {
game.fireEvent(new GameEventPlayerPoisoned(this, source, oldPoison, num));

View File

@@ -216,7 +216,7 @@ public class GameSimulatorTest extends SimulationTestCase {
Game game = initAndCreateGame();
Player p = game.getPlayers().get(1);
Card sorin = addCard("Sorin, Solemn Visitor", p);
sorin.addCounter(CounterType.LOYALTY, 5, false);
sorin.addCounter(CounterType.LOYALTY, 5, sorin, false);
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
game.getAction().checkStateEffects(true);
@@ -260,7 +260,7 @@ public class GameSimulatorTest extends SimulationTestCase {
String bearCardName = "Runeclaw Bear";
addCard(bearCardName, p);
Card gideon = addCard("Gideon, Ally of Zendikar", p);
gideon.addCounter(CounterType.LOYALTY, 4, false);
gideon.addCounter(CounterType.LOYALTY, 4, gideon, false);
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
game.getAction().checkStateEffects(true);
@@ -379,7 +379,7 @@ public class GameSimulatorTest extends SimulationTestCase {
Game game = initAndCreateGame();
Player p = game.getPlayers().get(1);
Card sarkhan = addCard(sarkhanCardName, p);
sarkhan.addCounter(CounterType.LOYALTY, 4, false);
sarkhan.addCounter(CounterType.LOYALTY, 4, sarkhan, false);
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
game.getAction().checkStateEffects(true);
@@ -413,7 +413,7 @@ public class GameSimulatorTest extends SimulationTestCase {
addCard(ornithoperCardName, p);
addCard(bearCardName, p);
Card ajani = addCard(ajaniCardName, p);
ajani.addCounter(CounterType.LOYALTY, 4, false);
ajani.addCounter(CounterType.LOYALTY, 4, ajani, false);
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
game.getAction().checkStateEffects(true);
@@ -444,7 +444,7 @@ public class GameSimulatorTest extends SimulationTestCase {
SpellAbility boltSA = boltCard.getFirstSpellAbility();
Card ajani = addCard(ajaniCardName, p);
ajani.addCounter(CounterType.LOYALTY, 8, false);
ajani.addCounter(CounterType.LOYALTY, 8, ajani, false);
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
game.getAction().checkStateEffects(true);
@@ -494,7 +494,7 @@ public class GameSimulatorTest extends SimulationTestCase {
addCard("Swamp", p);
addCard("Swamp", p);
Card depths = addCard("Dark Depths", p);
depths.addCounter(CounterType.ICE, 10, false);
depths.addCounter(CounterType.ICE, 10, depths, false);
Card thespian = addCard("Thespian's Stage", p);
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
game.getAction().checkStateEffects(true);