mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 19:28:01 +00:00
Bioessence Hydra: add new Trigger for counters on many game entities at once
This commit is contained in:
committed by
swordshine
parent
f7546eca32
commit
f408950aad
@@ -1601,7 +1601,7 @@ public class ComputerUtilCard {
|
|||||||
pumped.addChangedCardKeywords(kws, null, false, false, timestamp);
|
pumped.addChangedCardKeywords(kws, null, false, false, timestamp);
|
||||||
Set<CounterType> types = c.getCounters().keySet();
|
Set<CounterType> types = c.getCounters().keySet();
|
||||||
for(CounterType ct : types) {
|
for(CounterType ct : types) {
|
||||||
pumped.addCounterFireNoEvents(ct, c.getCounters(ct), ai, true);
|
pumped.addCounterFireNoEvents(ct, c.getCounters(ct), ai, true, null);
|
||||||
}
|
}
|
||||||
//Copies tap-state and extra keywords (auras, equipment, etc.)
|
//Copies tap-state and extra keywords (auras, equipment, etc.)
|
||||||
if (c.isTapped()) {
|
if (c.isTapped()) {
|
||||||
|
|||||||
@@ -1016,7 +1016,7 @@ public abstract class GameState {
|
|||||||
String[] allCounterStrings = counterString.split(",");
|
String[] allCounterStrings = counterString.split(",");
|
||||||
for (final String counterPair : allCounterStrings) {
|
for (final String counterPair : allCounterStrings) {
|
||||||
String[] pair = counterPair.split("=", 2);
|
String[] pair = counterPair.split("=", 2);
|
||||||
entity.addCounter(CounterType.valueOf(pair[0]), Integer.parseInt(pair[1]), null, false, false);
|
entity.addCounter(CounterType.valueOf(pair[0]), Integer.parseInt(pair[1]), null, false, false, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import forge.ai.ComputerUtilCard;
|
|||||||
import forge.ai.ComputerUtilMana;
|
import forge.ai.ComputerUtilMana;
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
|
import forge.game.GameEntity;
|
||||||
import forge.game.GlobalRuleChange;
|
import forge.game.GlobalRuleChange;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.*;
|
import forge.game.card.*;
|
||||||
@@ -354,7 +355,25 @@ public class CountersRemoveAi 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) {
|
||||||
// TODO Auto-generated method stub
|
GameEntity target = (GameEntity) params.get("Target");
|
||||||
|
CounterType type = (CounterType) params.get("CounterType");
|
||||||
|
|
||||||
|
if (target instanceof Card) {
|
||||||
|
Card targetCard = (Card) target;
|
||||||
|
if (targetCard.getController().isOpponentOf(player)) {
|
||||||
|
return !ComputerUtil.isNegativeCounter(type, targetCard) ? max : min;
|
||||||
|
} else {
|
||||||
|
return ComputerUtil.isNegativeCounter(type, targetCard) ? max : min;
|
||||||
|
}
|
||||||
|
} else if (target instanceof Player) {
|
||||||
|
Player targetPlayer = (Player) target;
|
||||||
|
if (targetPlayer.isOpponentOf(player)) {
|
||||||
|
return !type.equals(CounterType.POISON) ? max : min;
|
||||||
|
} else {
|
||||||
|
return type.equals(CounterType.POISON) ? max : min;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return super.chooseNumber(player, sa, min, max, params);
|
return super.chooseNumber(player, sa, min, max, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -370,30 +389,49 @@ public class CountersRemoveAi extends SpellAbilityAi {
|
|||||||
return super.chooseCounterType(options, sa, params);
|
return super.chooseCounterType(options, sa, params);
|
||||||
}
|
}
|
||||||
Player ai = sa.getActivatingPlayer();
|
Player ai = sa.getActivatingPlayer();
|
||||||
Card target = (Card) params.get("Target");
|
GameEntity target = (GameEntity) params.get("Target");
|
||||||
|
|
||||||
if (target.getController().isOpponentOf(ai)) {
|
if (target instanceof Card) {
|
||||||
|
Card targetCard = (Card) target;
|
||||||
|
if (targetCard.getController().isOpponentOf(ai)) {
|
||||||
// if its a Planeswalker try to remove Loyality first
|
// if its a Planeswalker try to remove Loyality first
|
||||||
if (target.isPlaneswalker()) {
|
if (targetCard.isPlaneswalker()) {
|
||||||
return CounterType.LOYALTY;
|
return CounterType.LOYALTY;
|
||||||
}
|
}
|
||||||
for (CounterType type : options) {
|
for (CounterType type : options) {
|
||||||
if (!ComputerUtil.isNegativeCounter(type, target)) {
|
if (!ComputerUtil.isNegativeCounter(type, targetCard)) {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (options.contains(CounterType.M1M1) && target.hasKeyword(Keyword.PERSIST)) {
|
if (options.contains(CounterType.M1M1) && targetCard.hasKeyword(Keyword.PERSIST)) {
|
||||||
return CounterType.M1M1;
|
|
||||||
} else if (options.contains(CounterType.P1P1) && target.hasKeyword(Keyword.UNDYING)) {
|
|
||||||
return CounterType.M1M1;
|
return CounterType.M1M1;
|
||||||
|
} else if (options.contains(CounterType.P1P1) && targetCard.hasKeyword(Keyword.UNDYING)) {
|
||||||
|
return CounterType.P1P1;
|
||||||
}
|
}
|
||||||
for (CounterType type : options) {
|
for (CounterType type : options) {
|
||||||
if (ComputerUtil.isNegativeCounter(type, target)) {
|
if (ComputerUtil.isNegativeCounter(type, targetCard)) {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (target instanceof Player) {
|
||||||
|
Player targetPlayer = (Player) target;
|
||||||
|
if (targetPlayer.isOpponentOf(ai)) {
|
||||||
|
for (CounterType type : options) {
|
||||||
|
if (!type.equals(CounterType.POISON)) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (CounterType type : options) {
|
||||||
|
if (type.equals(CounterType.POISON)) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return super.chooseCounterType(options, sa, params);
|
return super.chooseCounterType(options, sa, params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -247,7 +247,7 @@ public class GameAction {
|
|||||||
// fake etb counters thing, then if something changed,
|
// fake etb counters thing, then if something changed,
|
||||||
// need to apply checkStaticAbilities again
|
// need to apply checkStaticAbilities again
|
||||||
if(!noLandLKI.isLand()) {
|
if(!noLandLKI.isLand()) {
|
||||||
if (noLandLKI.putEtbCounters()) {
|
if (noLandLKI.putEtbCounters(null)) {
|
||||||
// counters are added need to check again
|
// counters are added need to check again
|
||||||
checkStaticAbilities(false, Sets.newHashSet(noLandLKI), preList);
|
checkStaticAbilities(false, Sets.newHashSet(noLandLKI), preList);
|
||||||
}
|
}
|
||||||
@@ -380,11 +380,34 @@ public class GameAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GameEntityCounterTable table = new GameEntityCounterTable();
|
||||||
|
|
||||||
|
// need to suspend cards own replacement effects
|
||||||
|
if (!suppress) {
|
||||||
|
if (toBattlefield && !copied.getEtbCounters().isEmpty()) {
|
||||||
|
for (final ReplacementEffect re : copied.getReplacementEffects()) {
|
||||||
|
re.setSuppressed(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// "enter the battlefield as a copy" - apply code here
|
// "enter the battlefield as a copy" - apply code here
|
||||||
// but how to query for input here and continue later while the callers assume synchronous result?
|
// but how to query for input here and continue later while the callers assume synchronous result?
|
||||||
zoneTo.add(copied, position, c); // the modified state of the card is also reported here (e.g. for Morbid + Awaken)
|
zoneTo.add(copied, position, c); // the modified state of the card is also reported here (e.g. for Morbid + Awaken)
|
||||||
c.setZone(zoneTo);
|
c.setZone(zoneTo);
|
||||||
|
|
||||||
|
// do ETB counters after zone add
|
||||||
|
if (!suppress) {
|
||||||
|
if (toBattlefield ) {
|
||||||
|
copied.putEtbCounters(table);
|
||||||
|
// enable replacement effects again
|
||||||
|
for (final ReplacementEffect re : copied.getReplacementEffects()) {
|
||||||
|
re.setSuppressed(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
copied.clearEtbCounters();
|
||||||
|
}
|
||||||
|
|
||||||
if (fromBattlefield) {
|
if (fromBattlefield) {
|
||||||
c.setDamage(0); //clear damage after a card leaves the battlefield
|
c.setDamage(0); //clear damage after a card leaves the battlefield
|
||||||
c.setHasBeenDealtDeathtouchDamage(false);
|
c.setHasBeenDealtDeathtouchDamage(false);
|
||||||
@@ -400,16 +423,7 @@ public class GameAction {
|
|||||||
game.getTriggerHandler().clearInstrinsicActiveTriggers(c, zoneFrom);
|
game.getTriggerHandler().clearInstrinsicActiveTriggers(c, zoneFrom);
|
||||||
game.getTriggerHandler().registerActiveTrigger(lastKnownInfo, false);
|
game.getTriggerHandler().registerActiveTrigger(lastKnownInfo, false);
|
||||||
|
|
||||||
// do ETB counters after StaticAbilities check
|
table.triggerCountersPutAll(game);
|
||||||
if (!suppress) {
|
|
||||||
if (toBattlefield) {
|
|
||||||
if (copied.putEtbCounters()) {
|
|
||||||
// if counter where put of card, call checkStaticAbilities again
|
|
||||||
checkStaticAbilities();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
copied.clearEtbCounters();
|
|
||||||
}
|
|
||||||
|
|
||||||
// play the change zone sound
|
// play the change zone sound
|
||||||
game.fireEvent(new GameEventCardChangeZone(c, zoneFrom, zoneTo));
|
game.fireEvent(new GameEventCardChangeZone(c, zoneFrom, zoneTo));
|
||||||
|
|||||||
@@ -66,52 +66,52 @@ public abstract class GameEntity extends GameObject implements IIdentifiable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final int addDamage(final int damage, final Card source, boolean isCombat, boolean noPrevention,
|
public final int addDamage(final int damage, final Card source, boolean isCombat, boolean noPrevention,
|
||||||
final CardDamageMap damageMap, final CardDamageMap preventMap, final SpellAbility cause) {
|
final CardDamageMap damageMap, final CardDamageMap preventMap, GameEntityCounterTable counterTable, final SpellAbility cause) {
|
||||||
if (noPrevention) {
|
if (noPrevention) {
|
||||||
return addDamageWithoutPrevention(damage, source, damageMap, preventMap, cause);
|
return addDamageWithoutPrevention(damage, source, damageMap, preventMap, counterTable, cause);
|
||||||
} else if (isCombat) {
|
} else if (isCombat) {
|
||||||
return addCombatDamage(damage, source, damageMap, preventMap);
|
return addCombatDamage(damage, source, damageMap, preventMap, counterTable);
|
||||||
} else {
|
} else {
|
||||||
return addDamage(damage, source, damageMap, preventMap, cause);
|
return addDamage(damage, source, damageMap, preventMap, counterTable, cause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int addDamage(final int damage, final Card source, final CardDamageMap damageMap,
|
public int addDamage(final int damage, final Card source, final CardDamageMap damageMap,
|
||||||
final CardDamageMap preventMap, final SpellAbility cause) {
|
final CardDamageMap preventMap, GameEntityCounterTable counterTable, final SpellAbility cause) {
|
||||||
int damageToDo = damage;
|
int damageToDo = damage;
|
||||||
|
|
||||||
damageToDo = replaceDamage(damageToDo, source, false, true, damageMap, preventMap, cause);
|
damageToDo = replaceDamage(damageToDo, source, false, true, damageMap, preventMap, counterTable, cause);
|
||||||
damageToDo = preventDamage(damageToDo, source, false, preventMap, cause);
|
damageToDo = preventDamage(damageToDo, source, false, preventMap, cause);
|
||||||
|
|
||||||
return addDamageAfterPrevention(damageToDo, source, false, damageMap);
|
return addDamageAfterPrevention(damageToDo, source, false, damageMap, counterTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int addCombatDamage(final int damage, final Card source, final CardDamageMap damageMap,
|
public final int addCombatDamage(final int damage, final Card source, final CardDamageMap damageMap,
|
||||||
final CardDamageMap preventMap) {
|
final CardDamageMap preventMap, GameEntityCounterTable counterTable) {
|
||||||
int damageToDo = damage;
|
int damageToDo = damage;
|
||||||
|
|
||||||
damageToDo = replaceDamage(damageToDo, source, true, true, damageMap, preventMap, null);
|
damageToDo = replaceDamage(damageToDo, source, true, true, damageMap, preventMap, counterTable, null);
|
||||||
damageToDo = preventDamage(damageToDo, source, true, preventMap, null);
|
damageToDo = preventDamage(damageToDo, source, true, preventMap, null);
|
||||||
|
|
||||||
if (damageToDo > 0) {
|
if (damageToDo > 0) {
|
||||||
source.getDamageHistory().registerCombatDamage(this);
|
source.getDamageHistory().registerCombatDamage(this);
|
||||||
}
|
}
|
||||||
// damage prevention is already checked
|
// damage prevention is already checked
|
||||||
return addCombatDamageBase(damageToDo, source, damageMap);
|
return addCombatDamageBase(damageToDo, source, damageMap, counterTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int addCombatDamageBase(final int damage, final Card source, CardDamageMap damageMap) {
|
protected int addCombatDamageBase(final int damage, final Card source, CardDamageMap damageMap, GameEntityCounterTable counterTable) {
|
||||||
return addDamageAfterPrevention(damage, source, true, damageMap);
|
return addDamageAfterPrevention(damage, source, true, damageMap, counterTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int addDamageWithoutPrevention(final int damage, final Card source, final CardDamageMap damageMap,
|
public int addDamageWithoutPrevention(final int damage, final Card source, final CardDamageMap damageMap,
|
||||||
final CardDamageMap preventMap, final SpellAbility cause) {
|
final CardDamageMap preventMap, GameEntityCounterTable counterTable, final SpellAbility cause) {
|
||||||
int damageToDo = replaceDamage(damage, source, false, false, damageMap, preventMap, cause);
|
int damageToDo = replaceDamage(damage, source, false, false, damageMap, preventMap, counterTable, cause);
|
||||||
return addDamageAfterPrevention(damageToDo, source, false, damageMap);
|
return addDamageAfterPrevention(damageToDo, source, false, damageMap, counterTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int replaceDamage(final int damage, final Card source, final boolean isCombat, final boolean prevention,
|
public int replaceDamage(final int damage, final Card source, final boolean isCombat, final boolean prevention,
|
||||||
final CardDamageMap damageMap, final CardDamageMap preventMap, final SpellAbility cause) {
|
final CardDamageMap damageMap, final CardDamageMap preventMap, GameEntityCounterTable counterTable, final SpellAbility cause) {
|
||||||
// Replacement effects
|
// Replacement effects
|
||||||
final Map<String, Object> repParams = Maps.newHashMap();
|
final Map<String, Object> repParams = Maps.newHashMap();
|
||||||
repParams.put("Event", "DamageDone");
|
repParams.put("Event", "DamageDone");
|
||||||
@@ -122,6 +122,7 @@ public abstract class GameEntity extends GameObject implements IIdentifiable {
|
|||||||
repParams.put("NoPreventDamage", !prevention);
|
repParams.put("NoPreventDamage", !prevention);
|
||||||
repParams.put("DamageMap", damageMap);
|
repParams.put("DamageMap", damageMap);
|
||||||
repParams.put("PreventMap", preventMap);
|
repParams.put("PreventMap", preventMap);
|
||||||
|
repParams.put("CounterTable", counterTable);
|
||||||
if (cause != null) {
|
if (cause != null) {
|
||||||
repParams.put("Cause", cause);
|
repParams.put("Cause", cause);
|
||||||
}
|
}
|
||||||
@@ -139,7 +140,7 @@ public abstract class GameEntity extends GameObject implements IIdentifiable {
|
|||||||
if (prevention) {
|
if (prevention) {
|
||||||
newDamage = newTarget.preventDamage(newDamage, source, isCombat, preventMap, cause);
|
newDamage = newTarget.preventDamage(newDamage, source, isCombat, preventMap, cause);
|
||||||
}
|
}
|
||||||
newTarget.addDamageAfterPrevention(newDamage, source, isCombat, damageMap);
|
newTarget.addDamageAfterPrevention(newDamage, source, isCombat, damageMap, counterTable);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
@@ -147,7 +148,7 @@ public abstract class GameEntity extends GameObject implements IIdentifiable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This function handles damage after replacement and prevention effects are applied
|
// This function handles damage after replacement and prevention effects are applied
|
||||||
public abstract int addDamageAfterPrevention(final int damage, final Card source, final boolean isCombat, CardDamageMap damageMap);
|
public abstract int addDamageAfterPrevention(final int damage, final Card source, final boolean isCombat, CardDamageMap damageMap, GameEntityCounterTable counterTable);
|
||||||
|
|
||||||
// This should be also usable by the AI to forecast an effect (so it must
|
// This should be also usable by the AI to forecast an effect (so it must
|
||||||
// not change the game state)
|
// not change the game state)
|
||||||
@@ -470,7 +471,7 @@ public abstract class GameEntity extends GameObject implements IIdentifiable {
|
|||||||
abstract public void setCounters(final Map<CounterType, Integer> allCounters);
|
abstract public void setCounters(final Map<CounterType, Integer> allCounters);
|
||||||
|
|
||||||
abstract public boolean canReceiveCounters(final CounterType type);
|
abstract public boolean canReceiveCounters(final CounterType type);
|
||||||
abstract public int addCounter(final CounterType counterType, final int n, final Player source, final boolean applyMultiplier, final boolean fireEvents);
|
abstract public int addCounter(final CounterType counterType, final int n, final Player source, final boolean applyMultiplier, final boolean fireEvents, GameEntityCounterTable table);
|
||||||
abstract public void subtractCounter(final CounterType counterName, final int n);
|
abstract public void subtractCounter(final CounterType counterName, final int n);
|
||||||
abstract public void clearCounters();
|
abstract public void clearCounters();
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package forge.game;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.google.common.collect.ForwardingTable;
|
||||||
|
import com.google.common.collect.HashBasedTable;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.common.collect.Table;
|
||||||
|
|
||||||
|
import forge.game.card.Card;
|
||||||
|
import forge.game.card.CounterType;
|
||||||
|
import forge.game.spellability.SpellAbility;
|
||||||
|
import forge.game.trigger.TriggerType;
|
||||||
|
|
||||||
|
public class GameEntityCounterTable extends ForwardingTable<GameEntity, CounterType, Integer> {
|
||||||
|
|
||||||
|
private Table<GameEntity, CounterType, Integer> dataMap = HashBasedTable.create();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see com.google.common.collect.ForwardingTable#delegate()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected Table<GameEntity, CounterType, Integer> delegate() {
|
||||||
|
return dataMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see com.google.common.collect.ForwardingTable#put(java.lang.Object, java.lang.Object, java.lang.Object)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Integer put(GameEntity rowKey, CounterType columnKey, Integer value) {
|
||||||
|
Integer old = contains(rowKey, columnKey) ? get(rowKey, columnKey) : 0;
|
||||||
|
return super.put(rowKey, columnKey, old + value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<GameEntity, Integer> filterTable(CounterType type, String valid, Card host, SpellAbility sa) {
|
||||||
|
Map<GameEntity, Integer> result = Maps.newHashMap();
|
||||||
|
|
||||||
|
for (Map.Entry<GameEntity, Integer> e : column(type).entrySet()) {
|
||||||
|
if (e.getKey().isValid(valid, host.getController(), host, sa)) {
|
||||||
|
result.put(e.getKey(), e.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void triggerCountersPutAll(final Game game) {
|
||||||
|
if (!isEmpty()) {
|
||||||
|
final Map<String, Object> runParams = Maps.newHashMap();
|
||||||
|
runParams.put("Objects", this);
|
||||||
|
game.getTriggerHandler().runTrigger(TriggerType.CounterAddedAll, runParams, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package forge.game.ability.effects;
|
package forge.game.ability.effects;
|
||||||
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
|
import forge.game.GameEntityCounterTable;
|
||||||
import forge.game.ability.AbilityUtils;
|
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;
|
||||||
@@ -62,14 +63,16 @@ public class AmassEffect extends SpellAbilityEffect {
|
|||||||
CardCollectionView tgtCards = CardLists.getType(activator.getCardsIn(ZoneType.Battlefield), "Army");
|
CardCollectionView tgtCards = CardLists.getType(activator.getCardsIn(ZoneType.Battlefield), "Army");
|
||||||
tgtCards = pc.chooseCardsForEffect(tgtCards, sa, "Choose an army to put counters on", 1, 1, false);
|
tgtCards = pc.chooseCardsForEffect(tgtCards, sa, "Choose an army to put counters on", 1, 1, false);
|
||||||
|
|
||||||
|
GameEntityCounterTable table = new GameEntityCounterTable();
|
||||||
for(final Card tgtCard : tgtCards) {
|
for(final Card tgtCard : tgtCards) {
|
||||||
tgtCard.addCounter(CounterType.P1P1, amount, activator, true);
|
tgtCard.addCounter(CounterType.P1P1, amount, activator, true, table);
|
||||||
game.updateLastStateForCard(tgtCard);
|
game.updateLastStateForCard(tgtCard);
|
||||||
|
|
||||||
if (remember) {
|
if (remember) {
|
||||||
card.addRemembered(tgtCard);
|
card.addRemembered(tgtCard);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
table.triggerCountersPutAll(game);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package forge.game.ability.effects;
|
package forge.game.ability.effects;
|
||||||
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
|
import forge.game.GameEntityCounterTable;
|
||||||
import forge.game.ability.AbilityUtils;
|
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;
|
||||||
@@ -78,6 +79,8 @@ public class CountersMoveEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GameEntityCounterTable table = new GameEntityCounterTable();
|
||||||
|
|
||||||
// uses for multi sources -> one defined/target
|
// uses for multi sources -> one defined/target
|
||||||
// this needs given counter type
|
// this needs given counter type
|
||||||
if (sa.hasParam("ValidSource")) {
|
if (sa.hasParam("ValidSource")) {
|
||||||
@@ -146,8 +149,9 @@ public class CountersMoveEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (csum > 0) {
|
if (csum > 0) {
|
||||||
dest.addCounter(cType, csum, player, true);
|
dest.addCounter(cType, csum, player, true, table);
|
||||||
game.updateLastStateForCard(dest);
|
game.updateLastStateForCard(dest);
|
||||||
|
table.triggerCountersPutAll(game);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else if (sa.hasParam("ValidDefined")) {
|
} else if (sa.hasParam("ValidDefined")) {
|
||||||
@@ -202,7 +206,7 @@ public class CountersMoveEffect extends SpellAbilityEffect {
|
|||||||
|
|
||||||
if (cnum > 0) {
|
if (cnum > 0) {
|
||||||
source.subtractCounter(cType, cnum);
|
source.subtractCounter(cType, cnum);
|
||||||
cur.addCounter(cType, cnum, player, true);
|
cur.addCounter(cType, cnum, player, true, table);
|
||||||
game.updateLastStateForCard(cur);
|
game.updateLastStateForCard(cur);
|
||||||
updateSource = true;
|
updateSource = true;
|
||||||
}
|
}
|
||||||
@@ -210,6 +214,7 @@ public class CountersMoveEffect extends SpellAbilityEffect {
|
|||||||
if (updateSource) {
|
if (updateSource) {
|
||||||
// update source
|
// update source
|
||||||
game.updateLastStateForCard(source);
|
game.updateLastStateForCard(source);
|
||||||
|
table.triggerCountersPutAll(game);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -263,7 +268,7 @@ public class CountersMoveEffect extends SpellAbilityEffect {
|
|||||||
|
|
||||||
if (source.getCounters(cType) >= cntToMove) {
|
if (source.getCounters(cType) >= cntToMove) {
|
||||||
source.subtractCounter(cType, cntToMove);
|
source.subtractCounter(cType, cntToMove);
|
||||||
cur.addCounter(cType, cntToMove, player, true);
|
cur.addCounter(cType, cntToMove, player, true, table);
|
||||||
game.updateLastStateForCard(cur);
|
game.updateLastStateForCard(cur);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -297,7 +302,7 @@ public class CountersMoveEffect extends SpellAbilityEffect {
|
|||||||
sa, sb.toString(), 0, Math.min(tgtCounters.get(chosenType), cntToMove), params);
|
sa, sb.toString(), 0, Math.min(tgtCounters.get(chosenType), cntToMove), params);
|
||||||
|
|
||||||
if (chosenAmount > 0) {
|
if (chosenAmount > 0) {
|
||||||
dest.addCounter(chosenType, chosenAmount, player, true);
|
dest.addCounter(chosenType, chosenAmount, player, true, table);
|
||||||
source.subtractCounter(chosenType, chosenAmount);
|
source.subtractCounter(chosenType, chosenAmount);
|
||||||
game.updateLastStateForCard(dest);
|
game.updateLastStateForCard(dest);
|
||||||
cntToMove -= chosenAmount;
|
cntToMove -= chosenAmount;
|
||||||
@@ -307,5 +312,6 @@ public class CountersMoveEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
// update source
|
// update source
|
||||||
game.updateLastStateForCard(source);
|
game.updateLastStateForCard(source);
|
||||||
|
table.triggerCountersPutAll(game);
|
||||||
} // moveCounterResolve
|
} // moveCounterResolve
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package forge.game.ability.effects;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
|
import forge.game.GameEntityCounterTable;
|
||||||
import forge.game.ability.AbilityUtils;
|
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;
|
||||||
@@ -43,6 +44,7 @@ public class CountersMultiplyEffect extends SpellAbilityEffect {
|
|||||||
final CounterType counterType = getCounterType(sa);
|
final CounterType counterType = getCounterType(sa);
|
||||||
final int n = Integer.valueOf(sa.getParamOrDefault("Multiplier", "2")) - 1;
|
final int n = Integer.valueOf(sa.getParamOrDefault("Multiplier", "2")) - 1;
|
||||||
|
|
||||||
|
GameEntityCounterTable table = new GameEntityCounterTable();
|
||||||
for (final Card tgtCard : getTargetCards(sa)) {
|
for (final Card tgtCard : getTargetCards(sa)) {
|
||||||
Card gameCard = game.getCardState(tgtCard, null);
|
Card gameCard = game.getCardState(tgtCard, null);
|
||||||
// gameCard is LKI in that case, the card is not in game anymore
|
// gameCard is LKI in that case, the card is not in game anymore
|
||||||
@@ -52,14 +54,15 @@ public class CountersMultiplyEffect extends SpellAbilityEffect {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (counterType != null) {
|
if (counterType != null) {
|
||||||
gameCard.addCounter(counterType, gameCard.getCounters(counterType) * n, player, true);
|
gameCard.addCounter(counterType, gameCard.getCounters(counterType) * n, player, true, table);
|
||||||
} else {
|
} else {
|
||||||
for (Map.Entry<CounterType, Integer> e : gameCard.getCounters().entrySet()) {
|
for (Map.Entry<CounterType, Integer> e : gameCard.getCounters().entrySet()) {
|
||||||
gameCard.addCounter(e.getKey(), e.getValue() * n, player, true);
|
gameCard.addCounter(e.getKey(), e.getValue() * n, player, true, table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
game.updateLastStateForCard(gameCard);
|
game.updateLastStateForCard(gameCard);
|
||||||
}
|
}
|
||||||
|
table.triggerCountersPutAll(game);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,10 @@ package forge.game.ability.effects;
|
|||||||
|
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import forge.game.Game;
|
||||||
|
import forge.game.GameEntityCounterTable;
|
||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardCollection;
|
|
||||||
import forge.game.card.CounterType;
|
import forge.game.card.CounterType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
@@ -20,16 +21,19 @@ public class CountersNoteEffect extends SpellAbilityEffect {
|
|||||||
@Override
|
@Override
|
||||||
public void resolve(SpellAbility sa) {
|
public void resolve(SpellAbility sa) {
|
||||||
Card source = sa.getHostCard();
|
Card source = sa.getHostCard();
|
||||||
CardCollection tgtCards = new CardCollection();
|
final Game game = source.getGame();
|
||||||
tgtCards.addAll(getDefinedCardsOrTargeted(sa));
|
Player p = sa.getActivatingPlayer();
|
||||||
String mode = sa.getParamOrDefault("Mode", "Load");
|
String mode = sa.getParamOrDefault("Mode", "Load");
|
||||||
for (Card c : tgtCards) {
|
|
||||||
|
GameEntityCounterTable table = new GameEntityCounterTable();
|
||||||
|
for (Card c : getDefinedCardsOrTargeted(sa)) {
|
||||||
if (mode.equals(MODE_STORE)) {
|
if (mode.equals(MODE_STORE)) {
|
||||||
noteCounters(c, source);
|
noteCounters(c, source);
|
||||||
} else if (mode.equals(MODE_LOAD)) {
|
} else if (mode.equals(MODE_LOAD)) {
|
||||||
loadCounters(c, source, sa.getActivatingPlayer());
|
loadCounters(c, source, p, table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
table.triggerCountersPutAll(game);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void noteCounters(Card notee, Card source) {
|
private void noteCounters(Card notee, Card source) {
|
||||||
@@ -40,11 +44,13 @@ public class CountersNoteEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadCounters(Card notee, Card source, final Player p) {
|
private void loadCounters(Card notee, Card source, final Player p, GameEntityCounterTable table) {
|
||||||
for(Entry<String, String> svar : source.getSVars().entrySet()) {
|
for(Entry<String, String> svar : source.getSVars().entrySet()) {
|
||||||
String key = svar.getKey();
|
String key = svar.getKey();
|
||||||
if (key.startsWith(NOTE_COUNTERS)) {
|
if (key.startsWith(NOTE_COUNTERS)) {
|
||||||
notee.addCounter(CounterType.getType(key.substring(NOTE_COUNTERS.length())), Integer.parseInt(svar.getValue()), p, false);
|
notee.addCounter(
|
||||||
|
CounterType.getType(key.substring(NOTE_COUNTERS.length())),
|
||||||
|
Integer.parseInt(svar.getValue()), p, false, table);
|
||||||
}
|
}
|
||||||
// TODO Probably should "remove" the svars that were temporarily used
|
// TODO Probably should "remove" the svars that were temporarily used
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package forge.game.ability.effects;
|
|||||||
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameEntity;
|
import forge.game.GameEntity;
|
||||||
|
import forge.game.GameEntityCounterTable;
|
||||||
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;
|
||||||
@@ -43,14 +44,16 @@ public class CountersProliferateEffect extends SpellAbilityEffect {
|
|||||||
List<GameEntity> result = pc.chooseEntitiesForEffect(list, 0, list.size(), null, sa,
|
List<GameEntity> result = pc.chooseEntitiesForEffect(list, 0, list.size(), null, sa,
|
||||||
"Choose any number of permanents and/or players for proliferate", p);
|
"Choose any number of permanents and/or players for proliferate", p);
|
||||||
|
|
||||||
|
GameEntityCounterTable table = new GameEntityCounterTable();
|
||||||
for (final GameEntity ge : result) {
|
for (final GameEntity ge : result) {
|
||||||
for (final CounterType ct : ge.getCounters().keySet()) {
|
for (final CounterType ct : ge.getCounters().keySet()) {
|
||||||
ge.addCounter(ct, 1, p, true, true);
|
ge.addCounter(ct, 1, p, true, true, table);
|
||||||
}
|
}
|
||||||
if (ge instanceof Card) {
|
if (ge instanceof Card) {
|
||||||
Card c = (Card) ge;
|
Card c = (Card) ge;
|
||||||
game.updateLastStateForCard(c);
|
game.updateLastStateForCard(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
table.triggerCountersPutAll(game);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package forge.game.ability.effects;
|
package forge.game.ability.effects;
|
||||||
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
|
import forge.game.GameEntityCounterTable;
|
||||||
import forge.game.ability.AbilityUtils;
|
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;
|
||||||
@@ -63,15 +64,13 @@ public class CountersPutAllEffect extends SpellAbilityEffect {
|
|||||||
placer = AbilityUtils.getDefinedPlayers(host, pstr, sa).get(0);
|
placer = AbilityUtils.getDefinedPlayers(host, pstr, sa).get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GameEntityCounterTable table = new GameEntityCounterTable();
|
||||||
for (final Card tgtCard : cards) {
|
for (final Card tgtCard : cards) {
|
||||||
if (game.getZoneOf(tgtCard).is(ZoneType.Battlefield)) {
|
boolean inBattlefield = game.getZoneOf(tgtCard).is(ZoneType.Battlefield);
|
||||||
tgtCard.addCounter(CounterType.valueOf(type), counterAmount, placer, true);
|
tgtCard.addCounter(CounterType.valueOf(type), counterAmount, placer, inBattlefield, table);
|
||||||
} else {
|
|
||||||
// adding counters to something like re-suspend cards
|
|
||||||
tgtCard.addCounter(CounterType.valueOf(type), counterAmount, placer, false);
|
|
||||||
}
|
|
||||||
game.updateLastStateForCard(tgtCard);
|
game.updateLastStateForCard(tgtCard);
|
||||||
}
|
}
|
||||||
|
table.triggerCountersPutAll(game);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import com.google.common.collect.Sets;
|
|||||||
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameEntity;
|
import forge.game.GameEntity;
|
||||||
|
import forge.game.GameEntityCounterTable;
|
||||||
import forge.game.GameObject;
|
import forge.game.GameObject;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
@@ -133,6 +134,8 @@ public class CountersPutEffect extends SpellAbilityEffect {
|
|||||||
tgtObjects.addAll(getDefinedOrTargeted(sa, "Defined"));
|
tgtObjects.addAll(getDefinedOrTargeted(sa, "Defined"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GameEntityCounterTable table = new GameEntityCounterTable();
|
||||||
|
|
||||||
for (final GameObject obj : tgtObjects) {
|
for (final GameObject obj : tgtObjects) {
|
||||||
// check if the object is still in game or if it was moved
|
// check if the object is still in game or if it was moved
|
||||||
Card gameCard = null;
|
Card gameCard = null;
|
||||||
@@ -162,10 +165,10 @@ public class CountersPutEffect extends SpellAbilityEffect {
|
|||||||
if (eachExistingCounter) {
|
if (eachExistingCounter) {
|
||||||
for(CounterType ct : choices) {
|
for(CounterType ct : choices) {
|
||||||
if (obj instanceof Player) {
|
if (obj instanceof Player) {
|
||||||
((Player) obj).addCounter(ct, counterAmount, placer, true);
|
((Player) obj).addCounter(ct, counterAmount, placer, true, table);
|
||||||
}
|
}
|
||||||
if (obj instanceof Card) {
|
if (obj instanceof Card) {
|
||||||
gameCard.addCounter(ct, counterAmount, placer, true);
|
gameCard.addCounter(ct, counterAmount, placer, true, table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@@ -249,7 +252,7 @@ public class CountersPutEffect extends SpellAbilityEffect {
|
|||||||
if (etbcounter) {
|
if (etbcounter) {
|
||||||
tgtCard.addEtbCounter(counterType, counterAmount, placer);
|
tgtCard.addEtbCounter(counterType, counterAmount, placer);
|
||||||
} else {
|
} else {
|
||||||
tgtCard.addCounter(counterType, counterAmount, placer, true);
|
tgtCard.addCounter(counterType, counterAmount, placer, true, table);
|
||||||
}
|
}
|
||||||
if (remember) {
|
if (remember) {
|
||||||
final int value = tgtCard.getTotalCountersToAdd();
|
final int value = tgtCard.getTotalCountersToAdd();
|
||||||
@@ -287,7 +290,7 @@ public class CountersPutEffect extends SpellAbilityEffect {
|
|||||||
if (etbcounter) {
|
if (etbcounter) {
|
||||||
tgtCard.addEtbCounter(counterType, counterAmount, placer);
|
tgtCard.addEtbCounter(counterType, counterAmount, placer);
|
||||||
} else {
|
} else {
|
||||||
tgtCard.addCounter(counterType, counterAmount, placer, false);
|
tgtCard.addCounter(counterType, counterAmount, placer, false, table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
game.updateLastStateForCard(tgtCard);
|
game.updateLastStateForCard(tgtCard);
|
||||||
@@ -295,9 +298,10 @@ public class CountersPutEffect extends SpellAbilityEffect {
|
|||||||
} else if (obj instanceof Player) {
|
} else if (obj instanceof Player) {
|
||||||
// Add Counters to players!
|
// Add Counters to players!
|
||||||
Player pl = (Player) obj;
|
Player pl = (Player) obj;
|
||||||
pl.addCounter(counterType, counterAmount, placer, true);
|
pl.addCounter(counterType, counterAmount, placer, true, table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
table.triggerCountersPutAll(game);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package forge.game.ability.effects;
|
package forge.game.ability.effects;
|
||||||
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
|
import forge.game.GameEntityCounterTable;
|
||||||
import forge.game.ability.AbilityUtils;
|
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;
|
||||||
@@ -57,6 +58,8 @@ public class CountersPutOrRemoveEffect extends SpellAbilityEffect {
|
|||||||
ctype = CounterType.valueOf(sa.getParam("CounterType"));
|
ctype = CounterType.valueOf(sa.getParam("CounterType"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GameEntityCounterTable table = new GameEntityCounterTable();
|
||||||
|
|
||||||
for (final Card tgtCard : getDefinedCardsOrTargeted(sa)) {
|
for (final Card tgtCard : getDefinedCardsOrTargeted(sa)) {
|
||||||
Card gameCard = game.getCardState(tgtCard, null);
|
Card gameCard = game.getCardState(tgtCard, null);
|
||||||
// gameCard is LKI in that case, the card is not in game anymore
|
// gameCard is LKI in that case, the card is not in game anymore
|
||||||
@@ -69,19 +72,20 @@ public class CountersPutOrRemoveEffect extends SpellAbilityEffect {
|
|||||||
if (gameCard.hasCounters()) {
|
if (gameCard.hasCounters()) {
|
||||||
if (sa.hasParam("EachExistingCounter")) {
|
if (sa.hasParam("EachExistingCounter")) {
|
||||||
for (CounterType listType : Lists.newArrayList(gameCard.getCounters().keySet())) {
|
for (CounterType listType : Lists.newArrayList(gameCard.getCounters().keySet())) {
|
||||||
addOrRemoveCounter(sa, gameCard, listType, counterAmount);
|
addOrRemoveCounter(sa, gameCard, listType, counterAmount, table);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
addOrRemoveCounter(sa, gameCard, ctype, counterAmount);
|
addOrRemoveCounter(sa, gameCard, ctype, counterAmount, table);
|
||||||
}
|
}
|
||||||
game.updateLastStateForCard(gameCard);
|
game.updateLastStateForCard(gameCard);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
table.triggerCountersPutAll(game);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addOrRemoveCounter(final SpellAbility sa, final Card tgtCard, CounterType ctype,
|
private void addOrRemoveCounter(final SpellAbility sa, final Card tgtCard, CounterType ctype,
|
||||||
final int counterAmount) {
|
final int counterAmount, GameEntityCounterTable table) {
|
||||||
final Player pl = sa.getActivatingPlayer();
|
final Player pl = sa.getActivatingPlayer();
|
||||||
final PlayerController pc = pl.getController();
|
final PlayerController pc = pl.getController();
|
||||||
|
|
||||||
@@ -106,7 +110,7 @@ public class CountersPutOrRemoveEffect extends SpellAbilityEffect {
|
|||||||
|
|
||||||
boolean apply = zone == null || zone.is(ZoneType.Battlefield) || zone.is(ZoneType.Stack);
|
boolean apply = zone == null || zone.is(ZoneType.Battlefield) || zone.is(ZoneType.Stack);
|
||||||
|
|
||||||
tgtCard.addCounter(chosenType, counterAmount, pl, apply);
|
tgtCard.addCounter(chosenType, counterAmount, pl, apply, table);
|
||||||
} else {
|
} else {
|
||||||
tgtCard.subtractCounter(chosenType, counterAmount);
|
tgtCard.subtractCounter(chosenType, counterAmount);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package forge.game.ability.effects;
|
package forge.game.ability.effects;
|
||||||
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
|
import forge.game.GameEntity;
|
||||||
import forge.game.ability.AbilityUtils;
|
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;
|
||||||
@@ -106,12 +107,22 @@ public class CountersRemoveEffect extends SpellAbilityEffect {
|
|||||||
for (final Player tgtPlayer : getTargetPlayers(sa)) {
|
for (final Player tgtPlayer : getTargetPlayers(sa)) {
|
||||||
// Removing energy
|
// Removing energy
|
||||||
if (!sa.usesTargeting() || tgtPlayer.canBeTargetedBy(sa)) {
|
if (!sa.usesTargeting() || tgtPlayer.canBeTargetedBy(sa)) {
|
||||||
|
if (type.equals("All")) {
|
||||||
|
for (Map.Entry<CounterType, Integer> e : tgtPlayer.getCounters().entrySet()) {
|
||||||
|
tgtPlayer.subtractCounter(e.getKey(), e.getValue());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (num.equals("All")) {
|
if (num.equals("All")) {
|
||||||
cntToRemove = tgtPlayer.getCounters(counterType);
|
cntToRemove = tgtPlayer.getCounters(counterType);
|
||||||
}
|
}
|
||||||
|
if (type.equals("Any")) {
|
||||||
|
removeAnyType(tgtPlayer, cntToRemove, sa);
|
||||||
|
} else {
|
||||||
tgtPlayer.subtractCounter(counterType, cntToRemove);
|
tgtPlayer.subtractCounter(counterType, cntToRemove);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CardCollectionView srcCards = null;
|
CardCollectionView srcCards = null;
|
||||||
if (sa.hasParam("ValidSource")) {
|
if (sa.hasParam("ValidSource")) {
|
||||||
@@ -152,32 +163,7 @@ public class CountersRemoveEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type.equals("Any")) {
|
if (type.equals("Any")) {
|
||||||
while (cntToRemove > 0 && gameCard.hasCounters()) {
|
removeAnyType(gameCard, cntToRemove, sa);
|
||||||
final Map<CounterType, Integer> tgtCounters = gameCard.getCounters();
|
|
||||||
Map<String, Object> params = Maps.newHashMap();
|
|
||||||
params.put("Target", gameCard);
|
|
||||||
|
|
||||||
String prompt = "Select type of counters to remove";
|
|
||||||
CounterType chosenType = pc.chooseCounterType(
|
|
||||||
ImmutableList.copyOf(tgtCounters.keySet()), sa, prompt, params);
|
|
||||||
prompt = "Select the number of " + chosenType.getName() + " counters to remove";
|
|
||||||
int max = Math.min(cntToRemove, tgtCounters.get(chosenType));
|
|
||||||
params = Maps.newHashMap();
|
|
||||||
params.put("Target", gameCard);
|
|
||||||
params.put("CounterType", chosenType);
|
|
||||||
int chosenAmount = pc.chooseNumber(sa, prompt, 1, max, params);
|
|
||||||
|
|
||||||
if (chosenAmount > 0) {
|
|
||||||
gameCard.subtractCounter(chosenType, chosenAmount);
|
|
||||||
game.updateLastStateForCard(gameCard);
|
|
||||||
if (rememberRemoved) {
|
|
||||||
for (int i = 0; i < chosenAmount; i++) {
|
|
||||||
card.addRemembered(Pair.of(chosenType, i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cntToRemove -= chosenAmount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
cntToRemove = Math.min(cntToRemove, gameCard.getCounters(counterType));
|
cntToRemove = Math.min(cntToRemove, gameCard.getCounters(counterType));
|
||||||
|
|
||||||
@@ -212,4 +198,47 @@ public class CountersRemoveEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void removeAnyType(GameEntity entity, int cntToRemove, SpellAbility sa) {
|
||||||
|
boolean rememberRemoved = sa.hasParam("RememberRemoved");
|
||||||
|
|
||||||
|
final Card card = sa.getHostCard();
|
||||||
|
final Game game = card.getGame();
|
||||||
|
final Player player = sa.getActivatingPlayer();
|
||||||
|
|
||||||
|
PlayerController pc = player.getController();
|
||||||
|
|
||||||
|
while (cntToRemove > 0 && entity.hasCounters()) {
|
||||||
|
final Map<CounterType, Integer> tgtCounters = entity.getCounters();
|
||||||
|
Map<String, Object> params = Maps.newHashMap();
|
||||||
|
params.put("Target", entity);
|
||||||
|
|
||||||
|
String prompt = "Select type of counters to remove";
|
||||||
|
CounterType chosenType = pc.chooseCounterType(
|
||||||
|
ImmutableList.copyOf(tgtCounters.keySet()), sa, prompt, params);
|
||||||
|
prompt = "Select the number of " + chosenType.getName() + " counters to remove";
|
||||||
|
int max = Math.min(cntToRemove, tgtCounters.get(chosenType));
|
||||||
|
params = Maps.newHashMap();
|
||||||
|
params.put("Target", entity);
|
||||||
|
params.put("CounterType", chosenType);
|
||||||
|
int chosenAmount = pc.chooseNumber(sa, prompt, sa.hasParam("UpTo") ? 0 : 1, max, params);
|
||||||
|
|
||||||
|
if (chosenAmount > 0) {
|
||||||
|
entity.subtractCounter(chosenType, chosenAmount);
|
||||||
|
if (entity instanceof Card) {
|
||||||
|
Card gameCard = (Card) entity;
|
||||||
|
game.updateLastStateForCard(gameCard);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rememberRemoved) {
|
||||||
|
for (int i = 0; i < chosenAmount; i++) {
|
||||||
|
card.addRemembered(Pair.of(chosenType, i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cntToRemove -= chosenAmount;
|
||||||
|
} else if (sa.hasParam("UpTo")) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package forge.game.ability.effects;
|
|||||||
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameEntity;
|
import forge.game.GameEntity;
|
||||||
|
import forge.game.GameEntityCounterTable;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardCollection;
|
import forge.game.card.CardCollection;
|
||||||
@@ -88,6 +89,7 @@ public class DamageAllEffect extends DamageBaseEffect {
|
|||||||
boolean usedDamageMap = true;
|
boolean usedDamageMap = true;
|
||||||
CardDamageMap damageMap = sa.getDamageMap();
|
CardDamageMap damageMap = sa.getDamageMap();
|
||||||
CardDamageMap preventMap = sa.getPreventMap();
|
CardDamageMap preventMap = sa.getPreventMap();
|
||||||
|
GameEntityCounterTable counterTable = new GameEntityCounterTable();
|
||||||
|
|
||||||
if (damageMap == null) {
|
if (damageMap == null) {
|
||||||
// make a new damage map
|
// make a new damage map
|
||||||
@@ -97,13 +99,13 @@ public class DamageAllEffect extends DamageBaseEffect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (final Card c : list) {
|
for (final Card c : list) {
|
||||||
c.addDamage(dmg, sourceLKI, damageMap, preventMap, sa);
|
c.addDamage(dmg, sourceLKI, damageMap, preventMap, counterTable, sa);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!players.equals("")) {
|
if (!players.equals("")) {
|
||||||
final List<Player> playerList = AbilityUtils.getDefinedPlayers(card, players, sa);
|
final List<Player> playerList = AbilityUtils.getDefinedPlayers(card, players, sa);
|
||||||
for (final Player p : playerList) {
|
for (final Player p : playerList) {
|
||||||
p.addDamage(dmg, sourceLKI, damageMap, preventMap, sa);
|
p.addDamage(dmg, sourceLKI, damageMap, preventMap, counterTable, sa);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,6 +128,8 @@ public class DamageAllEffect extends DamageBaseEffect {
|
|||||||
damageMap.clear();
|
damageMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
counterTable.triggerCountersPutAll(game);
|
||||||
|
|
||||||
replaceDying(sa);
|
replaceDying(sa);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package forge.game.ability.effects;
|
|||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
|
import forge.game.GameEntityCounterTable;
|
||||||
import forge.game.GameObject;
|
import forge.game.GameObject;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
@@ -119,6 +120,7 @@ public class DamageDealEffect extends DamageBaseEffect {
|
|||||||
boolean usedDamageMap = true;
|
boolean usedDamageMap = true;
|
||||||
CardDamageMap damageMap = sa.getDamageMap();
|
CardDamageMap damageMap = sa.getDamageMap();
|
||||||
CardDamageMap preventMap = sa.getPreventMap();
|
CardDamageMap preventMap = sa.getPreventMap();
|
||||||
|
GameEntityCounterTable counterTable = new GameEntityCounterTable();
|
||||||
|
|
||||||
if (damageMap == null) {
|
if (damageMap == null) {
|
||||||
// make a new damage map
|
// make a new damage map
|
||||||
@@ -159,7 +161,7 @@ public class DamageDealEffect extends DamageBaseEffect {
|
|||||||
Player assigningPlayer = players.get(0);
|
Player assigningPlayer = players.get(0);
|
||||||
Map<Card, Integer> map = assigningPlayer.getController().assignCombatDamage(sourceLKI, assigneeCards, dmg, null, true);
|
Map<Card, Integer> map = assigningPlayer.getController().assignCombatDamage(sourceLKI, assigneeCards, dmg, null, true);
|
||||||
for (Entry<Card, Integer> dt : map.entrySet()) {
|
for (Entry<Card, Integer> dt : map.entrySet()) {
|
||||||
dt.getKey().addDamage(dt.getValue(), sourceLKI, damageMap, preventMap, sa);
|
dt.getKey().addDamage(dt.getValue(), sourceLKI, damageMap, preventMap, counterTable, sa);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!usedDamageMap) {
|
if (!usedDamageMap) {
|
||||||
@@ -170,6 +172,8 @@ public class DamageDealEffect extends DamageBaseEffect {
|
|||||||
preventMap.clear();
|
preventMap.clear();
|
||||||
damageMap.clear();
|
damageMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
counterTable.triggerCountersPutAll(game);
|
||||||
replaceDying(sa);
|
replaceDying(sa);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -194,13 +198,13 @@ public class DamageDealEffect extends DamageBaseEffect {
|
|||||||
c.clearAssignedDamage();
|
c.clearAssignedDamage();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
c.addDamage(dmg, sourceLKI, false, noPrevention, damageMap, preventMap, sa);
|
c.addDamage(dmg, sourceLKI, false, noPrevention, damageMap, preventMap, counterTable, sa);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (o instanceof Player) {
|
} else if (o instanceof Player) {
|
||||||
final Player p = (Player) o;
|
final Player p = (Player) o;
|
||||||
if (!targeted || p.canBeTargetedBy(sa)) {
|
if (!targeted || p.canBeTargetedBy(sa)) {
|
||||||
p.addDamage(dmg, sourceLKI, false, noPrevention, damageMap, preventMap, sa);
|
p.addDamage(dmg, sourceLKI, false, noPrevention, damageMap, preventMap, counterTable, sa);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -217,6 +221,7 @@ public class DamageDealEffect extends DamageBaseEffect {
|
|||||||
preventMap.clear();
|
preventMap.clear();
|
||||||
damageMap.clear();
|
damageMap.clear();
|
||||||
}
|
}
|
||||||
|
counterTable.triggerCountersPutAll(game);
|
||||||
replaceDying(sa);
|
replaceDying(sa);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package forge.game.ability.effects;
|
package forge.game.ability.effects;
|
||||||
|
|
||||||
|
import forge.game.Game;
|
||||||
|
import forge.game.GameEntityCounterTable;
|
||||||
import forge.game.GameObject;
|
import forge.game.GameObject;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
@@ -60,8 +62,9 @@ public class DamageEachEffect extends DamageBaseEffect {
|
|||||||
@Override
|
@Override
|
||||||
public void resolve(SpellAbility sa) {
|
public void resolve(SpellAbility sa) {
|
||||||
final Card card = sa.getHostCard();
|
final Card card = sa.getHostCard();
|
||||||
|
final Game game = card.getGame();
|
||||||
|
|
||||||
FCollectionView<Card> sources = card.getGame().getCardsIn(ZoneType.Battlefield);
|
FCollectionView<Card> sources = game.getCardsIn(ZoneType.Battlefield);
|
||||||
if (sa.hasParam("ValidCards")) {
|
if (sa.hasParam("ValidCards")) {
|
||||||
sources = CardLists.getValidCards(sources, sa.getParam("ValidCards"), card.getController(), card);
|
sources = CardLists.getValidCards(sources, sa.getParam("ValidCards"), card.getController(), card);
|
||||||
}
|
}
|
||||||
@@ -73,6 +76,7 @@ public class DamageEachEffect extends DamageBaseEffect {
|
|||||||
boolean usedDamageMap = true;
|
boolean usedDamageMap = true;
|
||||||
CardDamageMap damageMap = sa.getDamageMap();
|
CardDamageMap damageMap = sa.getDamageMap();
|
||||||
CardDamageMap preventMap = sa.getPreventMap();
|
CardDamageMap preventMap = sa.getPreventMap();
|
||||||
|
GameEntityCounterTable counterTable = new GameEntityCounterTable();
|
||||||
|
|
||||||
if (damageMap == null) {
|
if (damageMap == null) {
|
||||||
// make a new damage map
|
// make a new damage map
|
||||||
@@ -83,21 +87,22 @@ public class DamageEachEffect extends DamageBaseEffect {
|
|||||||
|
|
||||||
for (final Object o : tgts) {
|
for (final Object o : tgts) {
|
||||||
for (final Card source : sources) {
|
for (final Card source : sources) {
|
||||||
final Card sourceLKI = source.getGame().getChangeZoneLKIInfo(source);
|
final Card sourceLKI = game.getChangeZoneLKIInfo(source);
|
||||||
|
|
||||||
|
// TODO shouldn't that be using Num or something first?
|
||||||
final int dmg = CardFactoryUtil.xCount(source, sa.getSVar("X"));
|
final int dmg = CardFactoryUtil.xCount(source, sa.getSVar("X"));
|
||||||
|
|
||||||
// System.out.println(source+" deals "+dmg+" damage to "+o.toString());
|
// System.out.println(source+" deals "+dmg+" damage to "+o.toString());
|
||||||
if (o instanceof Card) {
|
if (o instanceof Card) {
|
||||||
final Card c = (Card) o;
|
final Card c = (Card) o;
|
||||||
if (c.isInPlay() && (!targeted || c.canBeTargetedBy(sa))) {
|
if (c.isInPlay() && (!targeted || c.canBeTargetedBy(sa))) {
|
||||||
c.addDamage(dmg, sourceLKI, damageMap, preventMap, sa);
|
c.addDamage(dmg, sourceLKI, damageMap, preventMap, counterTable, sa);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (o instanceof Player) {
|
} else if (o instanceof Player) {
|
||||||
final Player p = (Player) o;
|
final Player p = (Player) o;
|
||||||
if (!targeted || p.canBeTargetedBy(sa)) {
|
if (!targeted || p.canBeTargetedBy(sa)) {
|
||||||
p.addDamage(dmg, sourceLKI, damageMap, preventMap, sa);
|
p.addDamage(dmg, sourceLKI, damageMap, preventMap, counterTable, sa);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -106,11 +111,11 @@ public class DamageEachEffect extends DamageBaseEffect {
|
|||||||
if (sa.hasParam("DefinedCards")) {
|
if (sa.hasParam("DefinedCards")) {
|
||||||
if (sa.getParam("DefinedCards").equals("Self")) {
|
if (sa.getParam("DefinedCards").equals("Self")) {
|
||||||
for (final Card source : sources) {
|
for (final Card source : sources) {
|
||||||
final Card sourceLKI = source.getGame().getChangeZoneLKIInfo(source);
|
final Card sourceLKI = game.getChangeZoneLKIInfo(source);
|
||||||
|
|
||||||
final int dmg = CardFactoryUtil.xCount(source, card.getSVar("X"));
|
final int dmg = CardFactoryUtil.xCount(source, card.getSVar("X"));
|
||||||
// System.out.println(source+" deals "+dmg+" damage to "+source);
|
// System.out.println(source+" deals "+dmg+" damage to "+source);
|
||||||
source.addDamage(dmg, sourceLKI, damageMap, preventMap, sa);
|
source.addDamage(dmg, sourceLKI, damageMap, preventMap, counterTable, sa);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sa.getParam("DefinedCards").equals("Remembered")) {
|
if (sa.getParam("DefinedCards").equals("Remembered")) {
|
||||||
@@ -122,7 +127,7 @@ public class DamageEachEffect extends DamageBaseEffect {
|
|||||||
if (o instanceof Card) {
|
if (o instanceof Card) {
|
||||||
Card rememberedcard = (Card) o;
|
Card rememberedcard = (Card) o;
|
||||||
// System.out.println(source + " deals " + dmg + " damage to " + rememberedcard);
|
// System.out.println(source + " deals " + dmg + " damage to " + rememberedcard);
|
||||||
rememberedcard.addDamage(dmg, sourceLKI, damageMap, preventMap, sa);
|
rememberedcard.addDamage(dmg, sourceLKI, damageMap, preventMap, counterTable, sa);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,6 +142,8 @@ public class DamageEachEffect extends DamageBaseEffect {
|
|||||||
damageMap.clear();
|
damageMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
counterTable.triggerCountersPutAll(game);
|
||||||
|
|
||||||
replaceDying(sa);
|
replaceDying(sa);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package forge.game.ability.effects;
|
|||||||
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameActionUtil;
|
import forge.game.GameActionUtil;
|
||||||
|
import forge.game.GameEntityCounterTable;
|
||||||
import forge.game.ability.AbilityUtils;
|
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;
|
||||||
@@ -110,6 +111,7 @@ public class DigEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CardZoneTable table = new CardZoneTable();
|
CardZoneTable table = new CardZoneTable();
|
||||||
|
GameEntityCounterTable counterTable = new GameEntityCounterTable();
|
||||||
for (final Player p : tgtPlayers) {
|
for (final Player p : tgtPlayers) {
|
||||||
if (tgt != null && !p.canBeTargetedBy(sa)) {
|
if (tgt != null && !p.canBeTargetedBy(sa)) {
|
||||||
continue;
|
continue;
|
||||||
@@ -378,7 +380,8 @@ public class DigEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
} else if (destZone2 == ZoneType.Exile) {
|
} else if (destZone2 == ZoneType.Exile) {
|
||||||
if (sa.hasParam("ExileWithCounter")) {
|
if (sa.hasParam("ExileWithCounter")) {
|
||||||
c.addCounter(CounterType.getType(sa.getParam("ExileWithCounter")), 1, player, true);
|
c.addCounter(CounterType.getType(sa.getParam("ExileWithCounter")),
|
||||||
|
1, player, true, counterTable);
|
||||||
}
|
}
|
||||||
c.setExiledWith(effectHost);
|
c.setExiledWith(effectHost);
|
||||||
}
|
}
|
||||||
@@ -389,6 +392,7 @@ public class DigEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
//table trigger there
|
//table trigger there
|
||||||
table.triggerChangesZoneAll(game);
|
table.triggerChangesZoneAll(game);
|
||||||
|
counterTable.triggerCountersPutAll(game);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO This should be somewhere else, maybe like CardUtil or something like that
|
// TODO This should be somewhere else, maybe like CardUtil or something like that
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package forge.game.ability.effects;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
|
import forge.game.GameEntityCounterTable;
|
||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardCollection;
|
import forge.game.card.CardCollection;
|
||||||
@@ -47,9 +48,9 @@ public class ExploreEffect extends SpellAbilityEffect {
|
|||||||
final Player pl = sa.getActivatingPlayer();
|
final Player pl = sa.getActivatingPlayer();
|
||||||
final PlayerController pc = pl.getController();
|
final PlayerController pc = pl.getController();
|
||||||
final Game game = pl.getGame();
|
final Game game = pl.getGame();
|
||||||
List<Card> tgt = getTargetCards(sa);
|
|
||||||
|
|
||||||
for (final Card c : tgt) {
|
GameEntityCounterTable table = new GameEntityCounterTable();
|
||||||
|
for (final Card c : getTargetCards(sa)) {
|
||||||
// revealed land card
|
// revealed land card
|
||||||
boolean revealedLand = false;
|
boolean revealedLand = false;
|
||||||
CardCollection top = pl.getTopXCardsFromLibrary(1);
|
CardCollection top = pl.getTopXCardsFromLibrary(1);
|
||||||
@@ -76,8 +77,8 @@ public class ExploreEffect extends SpellAbilityEffect {
|
|||||||
Card gamec = game.getCardState(c);
|
Card gamec = game.getCardState(c);
|
||||||
// if the card is not more in the game anymore
|
// if the card is not more in the game anymore
|
||||||
// this might still return true but its no problem
|
// this might still return true but its no problem
|
||||||
if (game.getZoneOf(gamec).is(ZoneType.Battlefield) && gamec.getTimestamp() == c.getTimestamp()) {
|
if (game.getZoneOf(gamec).is(ZoneType.Battlefield) && gamec.equalsWithTimestamp(c)) {
|
||||||
c.addCounter(CounterType.P1P1, 1, pl, true);
|
c.addCounter(CounterType.P1P1, 1, pl, true, table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,6 +87,7 @@ public class ExploreEffect extends SpellAbilityEffect {
|
|||||||
runParams.put("Card", c);
|
runParams.put("Card", c);
|
||||||
game.getTriggerHandler().runTrigger(TriggerType.Explores, runParams, false);
|
game.getTriggerHandler().runTrigger(TriggerType.Explores, runParams, false);
|
||||||
}
|
}
|
||||||
|
table.triggerCountersPutAll(game);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.google.common.collect.Lists;
|
|||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
|
import forge.game.GameEntityCounterTable;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardDamageMap;
|
import forge.game.card.CardDamageMap;
|
||||||
@@ -130,6 +131,7 @@ public class FightEffect extends DamageBaseEffect {
|
|||||||
boolean usedDamageMap = true;
|
boolean usedDamageMap = true;
|
||||||
CardDamageMap damageMap = sa.getDamageMap();
|
CardDamageMap damageMap = sa.getDamageMap();
|
||||||
CardDamageMap preventMap = sa.getPreventMap();
|
CardDamageMap preventMap = sa.getPreventMap();
|
||||||
|
GameEntityCounterTable counterTable = new GameEntityCounterTable();
|
||||||
|
|
||||||
if (damageMap == null) {
|
if (damageMap == null) {
|
||||||
// make a new damage map
|
// make a new damage map
|
||||||
@@ -142,12 +144,12 @@ public class FightEffect extends DamageBaseEffect {
|
|||||||
|
|
||||||
final int dmg1 = fightToughness ? fighterA.getNetToughness() : fighterA.getNetPower();
|
final int dmg1 = fightToughness ? fighterA.getNetToughness() : fighterA.getNetPower();
|
||||||
if (fighterA.equals(fighterB)) {
|
if (fighterA.equals(fighterB)) {
|
||||||
fighterA.addDamage(dmg1 * 2, fighterA, damageMap, preventMap, sa);
|
fighterA.addDamage(dmg1 * 2, fighterA, damageMap, preventMap, counterTable, sa);
|
||||||
} else {
|
} else {
|
||||||
final int dmg2 = fightToughness ? fighterB.getNetToughness() : fighterB.getNetPower();
|
final int dmg2 = fightToughness ? fighterB.getNetToughness() : fighterB.getNetPower();
|
||||||
|
|
||||||
fighterB.addDamage(dmg1, fighterA, damageMap, preventMap, sa);
|
fighterB.addDamage(dmg1, fighterA, damageMap, preventMap, counterTable, sa);
|
||||||
fighterA.addDamage(dmg2, fighterB, damageMap, preventMap, sa);
|
fighterA.addDamage(dmg2, fighterB, damageMap, preventMap, counterTable, sa);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!usedDamageMap) {
|
if (!usedDamageMap) {
|
||||||
@@ -157,6 +159,7 @@ public class FightEffect extends DamageBaseEffect {
|
|||||||
preventMap.clear();
|
preventMap.clear();
|
||||||
damageMap.clear();
|
damageMap.clear();
|
||||||
}
|
}
|
||||||
|
counterTable.triggerCountersPutAll(sa.getHostCard().getGame());
|
||||||
|
|
||||||
replaceDying(sa);
|
replaceDying(sa);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
package forge.game.ability.effects;
|
package forge.game.ability.effects;
|
||||||
|
|
||||||
|
import forge.game.Game;
|
||||||
|
import forge.game.GameEntityCounterTable;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CounterType;
|
import forge.game.card.CounterType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
@@ -21,17 +24,21 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void resolve(SpellAbility sa) {
|
public void resolve(SpellAbility sa) {
|
||||||
final int amount = AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("Num"), sa);
|
final Card host = sa.getHostCard();
|
||||||
|
final Game game = host.getGame();
|
||||||
|
final int amount = AbilityUtils.calculateAmount(host, sa.getParam("Num"), sa);
|
||||||
|
|
||||||
|
GameEntityCounterTable table = new GameEntityCounterTable();
|
||||||
for (final Player p : getTargetPlayers(sa)) {
|
for (final Player p : getTargetPlayers(sa)) {
|
||||||
if ((!sa.usesTargeting()) || p.canBeTargetedBy(sa)) {
|
if ((!sa.usesTargeting()) || p.canBeTargetedBy(sa)) {
|
||||||
if (amount >= 0) {
|
if (amount >= 0) {
|
||||||
p.addPoisonCounters(amount, sa.getHostCard());
|
p.addPoisonCounters(amount, host, table);
|
||||||
} else {
|
} else {
|
||||||
p.removePoisonCounters(-amount, sa.getHostCard());
|
p.removePoisonCounters(-amount, host);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
table.triggerCountersPutAll(game);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class PumpEffect extends SpellAbilityEffect {
|
|||||||
final Game game = host.getGame();
|
final Game game = host.getGame();
|
||||||
//if host is not on the battlefield don't apply
|
//if host is not on the battlefield don't apply
|
||||||
// Suspend should does Affect the Stack
|
// Suspend should does Affect the Stack
|
||||||
if (sa.hasParam("UntilLoseControlOfHost")
|
if ((sa.hasParam("UntilLoseControlOfHost") || sa.hasParam("UntilHostLeavesPlay"))
|
||||||
&& !(host.isInPlay() || host.isInZone(ZoneType.Stack))) {
|
&& !(host.isInPlay() || host.isInZone(ZoneType.Stack))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -104,7 +104,7 @@ public class PumpEffect extends SpellAbilityEffect {
|
|||||||
final Card host = sa.getHostCard();
|
final Card host = sa.getHostCard();
|
||||||
//if host is not on the battlefield don't apply
|
//if host is not on the battlefield don't apply
|
||||||
// Suspend should does Affect the Stack
|
// Suspend should does Affect the Stack
|
||||||
if (sa.hasParam("UntilLoseControlOfHost")
|
if ((sa.hasParam("UntilLoseControlOfHost") || sa.hasParam("UntilHostLeavesPlay"))
|
||||||
&& !(host.isInPlay() || host.isInZone(ZoneType.Stack))) {
|
&& !(host.isInPlay() || host.isInZone(ZoneType.Stack))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.google.common.collect.Maps;
|
|||||||
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameEntity;
|
import forge.game.GameEntity;
|
||||||
|
import forge.game.GameEntityCounterTable;
|
||||||
import forge.game.GameObject;
|
import forge.game.GameObject;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
@@ -57,6 +58,7 @@ public class ReplaceSplitDamageEffect extends SpellAbilityEffect {
|
|||||||
|
|
||||||
CardDamageMap damageMap = (CardDamageMap) originalParams.get("DamageMap");
|
CardDamageMap damageMap = (CardDamageMap) originalParams.get("DamageMap");
|
||||||
CardDamageMap preventMap = (CardDamageMap) originalParams.get("PreventMap");
|
CardDamageMap preventMap = (CardDamageMap) originalParams.get("PreventMap");
|
||||||
|
GameEntityCounterTable counterTable = (GameEntityCounterTable) originalParams.get("CounterTable");
|
||||||
SpellAbility cause = (SpellAbility) originalParams.get("Cause");
|
SpellAbility cause = (SpellAbility) originalParams.get("Cause");
|
||||||
|
|
||||||
boolean isCombat = (Boolean) originalParams.get("IsCombat");
|
boolean isCombat = (Boolean) originalParams.get("IsCombat");
|
||||||
@@ -64,7 +66,7 @@ public class ReplaceSplitDamageEffect extends SpellAbilityEffect {
|
|||||||
|
|
||||||
GameEntity obj = (GameEntity) list.get(0);
|
GameEntity obj = (GameEntity) list.get(0);
|
||||||
|
|
||||||
obj.addDamage(n, sourceLKI, isCombat, noPrevention, damageMap, preventMap, cause);
|
obj.addDamage(n, sourceLKI, isCombat, noPrevention, damageMap, preventMap, counterTable, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
// no damage for original target anymore
|
// no damage for original target anymore
|
||||||
@@ -74,7 +76,6 @@ public class ReplaceSplitDamageEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
params.put("DamageAmount", dmg);
|
params.put("DamageAmount", dmg);
|
||||||
|
|
||||||
|
|
||||||
//try to call replacementHandler with new Params
|
//try to call replacementHandler with new Params
|
||||||
ReplacementResult result = game.getReplacementHandler().run(params);
|
ReplacementResult result = game.getReplacementHandler().run(params);
|
||||||
switch (result) {
|
switch (result) {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.google.common.collect.Maps;
|
|||||||
import forge.card.mana.ManaCost;
|
import forge.card.mana.ManaCost;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameActionUtil;
|
import forge.game.GameActionUtil;
|
||||||
|
import forge.game.GameEntityCounterTable;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.*;
|
import forge.game.card.*;
|
||||||
@@ -43,7 +44,11 @@ public class SacrificeEffect extends SpellAbilityEffect {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if (sa.hasParam("CumulativeUpkeep")) {
|
} else if (sa.hasParam("CumulativeUpkeep")) {
|
||||||
card.addCounter(CounterType.AGE, 1, activator, true);
|
GameEntityCounterTable table = new GameEntityCounterTable();
|
||||||
|
card.addCounter(CounterType.AGE, 1, activator, true, table);
|
||||||
|
|
||||||
|
table.triggerCountersPutAll(game);
|
||||||
|
|
||||||
Cost cumCost = new Cost(sa.getParam("CumulativeUpkeep"), true);
|
Cost cumCost = new Cost(sa.getParam("CumulativeUpkeep"), true);
|
||||||
Cost payCost = new Cost(ManaCost.ZERO, true);
|
Cost payCost = new Cost(ManaCost.ZERO, true);
|
||||||
int n = card.getCounters(CounterType.AGE);
|
int n = card.getCounters(CounterType.AGE);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package forge.game.ability.effects;
|
|||||||
|
|
||||||
import forge.card.CardStateName;
|
import forge.card.CardStateName;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
|
import forge.game.GameEntityCounterTable;
|
||||||
import forge.game.GameLogEntryType;
|
import forge.game.GameLogEntryType;
|
||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
@@ -49,7 +50,6 @@ public class SetStateEffect extends SpellAbilityEffect {
|
|||||||
final String mode = sa.getParam("Mode");
|
final String mode = sa.getParam("Mode");
|
||||||
final Card host = sa.getHostCard();
|
final Card host = sa.getHostCard();
|
||||||
final Game game = host.getGame();
|
final Game game = host.getGame();
|
||||||
final List<Card> tgtCards = getTargetCards(sa);
|
|
||||||
|
|
||||||
final boolean remChanged = sa.hasParam("RememberChanged");
|
final boolean remChanged = sa.hasParam("RememberChanged");
|
||||||
final boolean morphUp = sa.hasParam("MorphUp");
|
final boolean morphUp = sa.hasParam("MorphUp");
|
||||||
@@ -57,7 +57,9 @@ public class SetStateEffect extends SpellAbilityEffect {
|
|||||||
final boolean hiddenAgenda = sa.hasParam("HiddenAgenda");
|
final boolean hiddenAgenda = sa.hasParam("HiddenAgenda");
|
||||||
final boolean optional = sa.hasParam("Optional");
|
final boolean optional = sa.hasParam("Optional");
|
||||||
|
|
||||||
for (final Card tgt : tgtCards) {
|
GameEntityCounterTable table = new GameEntityCounterTable();
|
||||||
|
|
||||||
|
for (final Card tgt : getTargetCards(sa)) {
|
||||||
if (sa.usesTargeting() && !tgt.canBeTargetedBy(sa)) {
|
if (sa.usesTargeting() && !tgt.canBeTargetedBy(sa)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -125,12 +127,13 @@ public class SetStateEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
game.fireEvent(new GameEventCardStatsChanged(tgt));
|
game.fireEvent(new GameEventCardStatsChanged(tgt));
|
||||||
if (sa.hasParam("Mega")) {
|
if (sa.hasParam("Mega")) {
|
||||||
tgt.addCounter(CounterType.P1P1, 1, p, true);
|
tgt.addCounter(CounterType.P1P1, 1, p, true, table);
|
||||||
}
|
}
|
||||||
if (remChanged) {
|
if (remChanged) {
|
||||||
host.addRemembered(tgt);
|
host.addRemembered(tgt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
table.triggerCountersPutAll(game);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1131,16 +1131,18 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean canReceiveCounters(final CounterType type) {
|
public final boolean canReceiveCounters(final CounterType type) {
|
||||||
if (hasKeyword("CARDNAME can't have counters put on it.")) {
|
|
||||||
return false;
|
// CantPutCounter static abilities
|
||||||
}
|
for (final Card ca : getGame().getCardsIn(ZoneType.listValueOf("Battlefield,Command"))) {
|
||||||
if (isCreature() && type == CounterType.M1M1) {
|
for (final StaticAbility stAb : ca.getStaticAbilities()) {
|
||||||
for (final Card c : getController().getCreaturesInPlay()) { // look for Melira, Sylvok Outcast
|
if (stAb.applyAbility("CantPutCounter", this, type)) {
|
||||||
if (c.hasKeyword("Creatures you control can't have -1/-1 counters put on them.")) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (type == CounterType.DREAM) {
|
}
|
||||||
|
|
||||||
|
if (type == CounterType.DREAM) {
|
||||||
|
// need to be done extra because it is also a state based action
|
||||||
if (hasKeyword("CARDNAME can't have more than seven dream counters on it.") && getCounters(CounterType.DREAM) > 6) {
|
if (hasKeyword("CARDNAME can't have more than seven dream counters on it.") && getCounters(CounterType.DREAM) > 6) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1156,17 +1158,17 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
countersAdded = value;
|
countersAdded = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int addCounter(final CounterType counterType, final int n, final Player source, final boolean applyMultiplier) {
|
public final int addCounter(final CounterType counterType, final int n, final Player source, final boolean applyMultiplier, GameEntityCounterTable table) {
|
||||||
return addCounter(counterType, n, source, applyMultiplier, true);
|
return addCounter(counterType, n, source, applyMultiplier, true, table);
|
||||||
}
|
}
|
||||||
public final int addCounterFireNoEvents(final CounterType counterType, final int n, final Player source, final boolean applyMultiplier) {
|
public final int addCounterFireNoEvents(final CounterType counterType, final int n, final Player source, final boolean applyMultiplier, GameEntityCounterTable table) {
|
||||||
return addCounter(counterType, n, source, applyMultiplier, false);
|
return addCounter(counterType, n, source, applyMultiplier, false, table);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int addCounter(final CounterType counterType, final int n, final Player source, final boolean applyMultiplier, final boolean fireEvents) {
|
public int addCounter(final CounterType counterType, final int n, final Player source, final boolean applyMultiplier, final boolean fireEvents, GameEntityCounterTable table) {
|
||||||
int addAmount = n;
|
int addAmount = n;
|
||||||
if(addAmount < 0) {
|
if(addAmount <= 0) {
|
||||||
addAmount = 0; // As per rule 107.1b
|
addAmount = 0; // As per rule 107.1b
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1245,6 +1247,9 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
getController().addCounterToPermThisTurn(counterType, addAmount);
|
getController().addCounterToPermThisTurn(counterType, addAmount);
|
||||||
view.updateCounters(this);
|
view.updateCounters(this);
|
||||||
}
|
}
|
||||||
|
if (table != null) {
|
||||||
|
table.put(this, counterType, addAmount);
|
||||||
|
}
|
||||||
return addAmount;
|
return addAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4622,15 +4627,20 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void addCombatDamage(final Map<Card, Integer> map, final CardDamageMap damageMap, final CardDamageMap preventMap) {
|
public final void addCombatDamage(final Map<Card, Integer> map, final CardDamageMap damageMap, final CardDamageMap preventMap, GameEntityCounterTable counterTable) {
|
||||||
for (final Entry<Card, Integer> entry : map.entrySet()) {
|
for (final Entry<Card, Integer> entry : map.entrySet()) {
|
||||||
addCombatDamage(entry.getValue(), entry.getKey(), damageMap, preventMap);
|
addCombatDamage(entry.getValue(), entry.getKey(), damageMap, preventMap, counterTable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int addCombatDamageBase(final int damage, final Card source, CardDamageMap damageMap) {
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see forge.game.GameEntity#addCombatDamageBase(int, forge.game.card.Card, forge.game.card.CardDamageMap, forge.game.GameEntityCounterTable)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected int addCombatDamageBase(final int damage, final Card source, CardDamageMap damageMap, GameEntityCounterTable counterTable) {
|
||||||
if (isInPlay()) {
|
if (isInPlay()) {
|
||||||
return super.addCombatDamageBase(damage, source, damageMap);
|
return super.addCombatDamageBase(damage, source, damageMap, counterTable);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -4857,10 +4867,10 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
return restDamage;
|
return restDamage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void addDamage(final Map<Card, Integer> sourcesMap, CardDamageMap damageMap) {
|
public final void addDamage(final Map<Card, Integer> sourcesMap, CardDamageMap damageMap, GameEntityCounterTable counterTable) {
|
||||||
for (final Entry<Card, Integer> entry : sourcesMap.entrySet()) {
|
for (final Entry<Card, Integer> entry : sourcesMap.entrySet()) {
|
||||||
// damage prevention is already checked!
|
// damage prevention is already checked!
|
||||||
addDamageAfterPrevention(entry.getValue(), entry.getKey(), true, damageMap);
|
addDamageAfterPrevention(entry.getValue(), entry.getKey(), true, damageMap, counterTable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4869,7 +4879,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
* applied.
|
* applied.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public final int addDamageAfterPrevention(final int damageIn, final Card source, final boolean isCombat, CardDamageMap damageMap) {
|
public final int addDamageAfterPrevention(final int damageIn, final Card source, final boolean isCombat, CardDamageMap damageMap, GameEntityCounterTable counterTable) {
|
||||||
|
|
||||||
if (damageIn == 0) {
|
if (damageIn == 0) {
|
||||||
return 0; // Rule 119.8
|
return 0; // Rule 119.8
|
||||||
@@ -4903,7 +4913,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
|
|
||||||
if (isInPlay()) {
|
if (isInPlay()) {
|
||||||
if (wither) {
|
if (wither) {
|
||||||
addCounter(CounterType.M1M1, damageIn, source.getController(), true);
|
addCounter(CounterType.M1M1, damageIn, source.getController(), true, counterTable);
|
||||||
damageType = DamageType.M1M1Counters;
|
damageType = DamageType.M1M1Counters;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -6052,7 +6062,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
return etbCounters.cellSet();
|
return etbCounters.cellSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean putEtbCounters() {
|
public final boolean putEtbCounters(GameEntityCounterTable table) {
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
for (Table.Cell<Player, CounterType, Integer> e : etbCounters.cellSet()) {
|
for (Table.Cell<Player, CounterType, Integer> e : etbCounters.cellSet()) {
|
||||||
CounterType ct = e.getColumnKey();
|
CounterType ct = e.getColumnKey();
|
||||||
@@ -6062,7 +6072,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
changed |= addCounter(ct, e.getValue(), e.getRowKey(), true) > 0;
|
changed |= addCounter(ct, e.getValue(), e.getRowKey(), true, table) > 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return changed;
|
return changed;
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import forge.card.mana.ManaCostParser;
|
|||||||
import forge.card.mana.ManaCostShard;
|
import forge.card.mana.ManaCostShard;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameEntity;
|
import forge.game.GameEntity;
|
||||||
|
import forge.game.GameEntityCounterTable;
|
||||||
import forge.game.GameLogEntryType;
|
import forge.game.GameLogEntryType;
|
||||||
import forge.game.ability.AbilityFactory;
|
import forge.game.ability.AbilityFactory;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
@@ -4277,7 +4278,9 @@ public class CardFactoryUtil {
|
|||||||
final Card c = game.getAction().exile(this.getHostCard(), this);
|
final Card c = game.getAction().exile(this.getHostCard(), this);
|
||||||
|
|
||||||
int counters = AbilityUtils.calculateAmount(c, k[1], this);
|
int counters = AbilityUtils.calculateAmount(c, k[1], this);
|
||||||
c.addCounter(CounterType.TIME, counters, getActivatingPlayer(), true);
|
GameEntityCounterTable table = new GameEntityCounterTable();
|
||||||
|
c.addCounter(CounterType.TIME, counters, getActivatingPlayer(), true, table);
|
||||||
|
table.triggerCountersPutAll(game);
|
||||||
|
|
||||||
String sb = TextUtil.concatWithSpace(getActivatingPlayer().toString(),"has suspended", c.getName(), "with", String.valueOf(counters),"time counters on it.");
|
String sb = TextUtil.concatWithSpace(getActivatingPlayer().toString(),"has suspended", c.getName(), "with", String.valueOf(counters),"time counters on it.");
|
||||||
game.getGameLog().add(GameLogEntryType.STACK_RESOLVE, sb);
|
game.getGameLog().add(GameLogEntryType.STACK_RESOLVE, sb);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import com.google.common.base.Function;
|
|||||||
import com.google.common.collect.*;
|
import com.google.common.collect.*;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameEntity;
|
import forge.game.GameEntity;
|
||||||
|
import forge.game.GameEntityCounterTable;
|
||||||
import forge.game.GameLogEntryType;
|
import forge.game.GameLogEntryType;
|
||||||
import forge.game.GameObjectMap;
|
import forge.game.GameObjectMap;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
@@ -783,18 +784,20 @@ public class Combat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void dealAssignedDamage() {
|
public void dealAssignedDamage() {
|
||||||
playerWhoAttacks.getGame().copyLastState();
|
final Game game = playerWhoAttacks.getGame();
|
||||||
|
game.copyLastState();
|
||||||
|
|
||||||
CardDamageMap preventMap = new CardDamageMap();
|
CardDamageMap preventMap = new CardDamageMap();
|
||||||
|
GameEntityCounterTable counterTable = new GameEntityCounterTable();
|
||||||
|
|
||||||
// This function handles both Regular and First Strike combat assignment
|
// This function handles both Regular and First Strike combat assignment
|
||||||
for (final Entry<Card, Integer> entry : defendingDamageMap.entrySet()) {
|
for (final Entry<Card, Integer> entry : defendingDamageMap.entrySet()) {
|
||||||
GameEntity defender = getDefenderByAttacker(entry.getKey());
|
GameEntity defender = getDefenderByAttacker(entry.getKey());
|
||||||
if (defender instanceof Player) { // player
|
if (defender instanceof Player) { // player
|
||||||
((Player) defender).addCombatDamage(entry.getValue(), entry.getKey(), dealtDamageTo, preventMap);
|
((Player) defender).addCombatDamage(entry.getValue(), entry.getKey(), dealtDamageTo, preventMap, counterTable);
|
||||||
}
|
}
|
||||||
else if (defender instanceof Card) { // planeswalker
|
else if (defender instanceof Card) { // planeswalker
|
||||||
((Card) defender).getController().addCombatDamage(entry.getValue(), entry.getKey(), dealtDamageTo, preventMap);
|
((Card) defender).getController().addCombatDamage(entry.getValue(), entry.getKey(), dealtDamageTo, preventMap, counterTable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -811,7 +814,7 @@ public class Combat {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
c.addCombatDamage(c.getAssignedDamageMap(), dealtDamageTo, preventMap);
|
c.addCombatDamage(c.getAssignedDamageMap(), dealtDamageTo, preventMap, counterTable);
|
||||||
c.clearAssignedDamage();
|
c.clearAssignedDamage();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -823,6 +826,9 @@ public class Combat {
|
|||||||
// LifeLink for Combat Damage at this place
|
// LifeLink for Combat Damage at this place
|
||||||
dealtDamageTo.triggerDamageDoneOnce(true, null);
|
dealtDamageTo.triggerDamageDoneOnce(true, null);
|
||||||
dealtDamageTo.clear();
|
dealtDamageTo.clear();
|
||||||
|
|
||||||
|
counterTable.triggerCountersPutAll(game);
|
||||||
|
counterTable.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean isUnblocked(final Card att) {
|
public final boolean isUnblocked(final Card att) {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
package forge.game.cost;
|
package forge.game.cost;
|
||||||
|
|
||||||
|
import forge.game.GameEntityCounterTable;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardDamageMap;
|
import forge.game.card.CardDamageMap;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
@@ -47,7 +48,7 @@ public class CostDamage extends CostPart {
|
|||||||
@Override
|
@Override
|
||||||
public final String toString() {
|
public final String toString() {
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
sb.append("Pay ").append(this.getAmount()).append(" Life");
|
sb.append("Deal ").append(this.getAmount()).append(" damage to you");
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,14 +69,17 @@ public class CostDamage extends CostPart {
|
|||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
CardDamageMap damageMap = new CardDamageMap();
|
CardDamageMap damageMap = new CardDamageMap();
|
||||||
CardDamageMap preventMap = new CardDamageMap();
|
CardDamageMap preventMap = new CardDamageMap();
|
||||||
|
GameEntityCounterTable table = new GameEntityCounterTable();
|
||||||
|
|
||||||
payer.addDamage(decision.c, source, damageMap, preventMap, sa);
|
payer.addDamage(decision.c, source, damageMap, preventMap, table, sa);
|
||||||
|
|
||||||
preventMap.triggerPreventDamage(false);
|
preventMap.triggerPreventDamage(false);
|
||||||
damageMap.triggerDamageDoneOnce(false, sa);
|
damageMap.triggerDamageDoneOnce(false, sa);
|
||||||
|
table.triggerCountersPutAll(payer.getGame());
|
||||||
|
|
||||||
preventMap.clear();
|
preventMap.clear();
|
||||||
damageMap.clear();
|
damageMap.clear();
|
||||||
|
table.clear();
|
||||||
return decision.c > 0;
|
return decision.c > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public abstract class CostPartWithList extends CostPart {
|
|||||||
/**
|
/**
|
||||||
* Reset list.
|
* Reset list.
|
||||||
*/
|
*/
|
||||||
public final void resetLists() {
|
public void resetLists() {
|
||||||
lkiList.clear();
|
lkiList.clear();
|
||||||
cardList.clear();
|
cardList.clear();
|
||||||
table.clear();
|
table.clear();
|
||||||
@@ -121,7 +121,7 @@ public abstract class CostPartWithList extends CostPart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// always returns true, made this to inline with return
|
// always returns true, made this to inline with return
|
||||||
public final boolean executePayment(SpellAbility ability, CardCollectionView targetCards) {
|
public boolean executePayment(SpellAbility ability, CardCollectionView targetCards) {
|
||||||
if (canPayListAtOnce()) { // This is used by reveal. Without it when opponent would reveal hand, you'll get N message boxes.
|
if (canPayListAtOnce()) { // This is used by reveal. Without it when opponent would reveal hand, you'll get N message boxes.
|
||||||
lkiList.addAll(targetCards);
|
lkiList.addAll(targetCards);
|
||||||
cardList.addAll(doListPayment(ability, targetCards));
|
cardList.addAll(doListPayment(ability, targetCards));
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
package forge.game.cost;
|
package forge.game.cost;
|
||||||
|
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.GameEntityCounterTable;
|
||||||
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.card.CardPredicates;
|
||||||
@@ -40,6 +40,8 @@ public class CostPutCounter extends CostPartWithList {
|
|||||||
private final CounterType counter;
|
private final CounterType counter;
|
||||||
private int lastPaidAmount = 0;
|
private int lastPaidAmount = 0;
|
||||||
|
|
||||||
|
private final GameEntityCounterTable counterTable = new GameEntityCounterTable();
|
||||||
|
|
||||||
public final CounterType getCounter() {
|
public final CounterType getCounter() {
|
||||||
return this.counter;
|
return this.counter;
|
||||||
}
|
}
|
||||||
@@ -119,9 +121,11 @@ public class CostPutCounter extends CostPartWithList {
|
|||||||
public final void refund(final Card source) {
|
public final void refund(final Card source) {
|
||||||
if(this.payCostFromSource())
|
if(this.payCostFromSource())
|
||||||
source.subtractCounter(this.counter, this.lastPaidAmount);
|
source.subtractCounter(this.counter, this.lastPaidAmount);
|
||||||
else
|
else {
|
||||||
|
final Integer i = this.convertAmount();
|
||||||
for (final Card c : this.getCardList()) {
|
for (final Card c : this.getCardList()) {
|
||||||
c.subtractCounter(this.counter, 1);
|
c.subtractCounter(this.counter, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,50 +166,25 @@ public class CostPutCounter extends CostPartWithList {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean payAsDecided(Player ai, PaymentDecision decision, SpellAbility ability) {
|
public boolean payAsDecided(Player ai, PaymentDecision decision, SpellAbility ability) {
|
||||||
Integer c = getNumberOfCounters(ability);
|
|
||||||
|
|
||||||
if (this.payCostFromSource()) {
|
if (this.payCostFromSource()) {
|
||||||
executePayment(ability, ability.getHostCard(), c);
|
executePayment(ability, ability.getHostCard());
|
||||||
} else {
|
} else {
|
||||||
// Put counter on chosen card
|
|
||||||
for (int i = 0; i < c; i++)
|
|
||||||
executePayment(ability, decision.cards);
|
executePayment(ability, decision.cards);
|
||||||
ability.getHostCard().setSVar("CostCountersAdded", Integer.toString(Math.min(decision.cards.size(), c)));
|
|
||||||
}
|
}
|
||||||
|
triggerCounterPutAll(ability);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getNumberOfCounters(final SpellAbility ability) {
|
|
||||||
Integer c = this.convertAmount();
|
|
||||||
if (c == null) {
|
|
||||||
c = AbilityUtils.calculateAmount(ability.getHostCard(), this.getAmount(), ability);
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card)
|
* @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected Card doPayment(SpellAbility ability, Card targetCard){
|
protected Card doPayment(SpellAbility ability, Card targetCard){
|
||||||
targetCard.addCounter(this.getCounter(), 1, ability.getActivatingPlayer(), false);
|
final Integer i = this.convertAmount();
|
||||||
|
targetCard.addCounter(this.getCounter(), i, ability.getActivatingPlayer(), false, counterTable);
|
||||||
return targetCard;
|
return targetCard;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void executePayment(SpellAbility ability, Card targetCard, int c) {
|
|
||||||
CounterType counterType = this.getCounter();
|
|
||||||
if( c > 1 ) {
|
|
||||||
Integer oldValue = targetCard.getCounters().get(counterType);
|
|
||||||
int newValue = c + (oldValue == null ? 0 : oldValue.intValue()) - 1;
|
|
||||||
targetCard.getCounters().put(counterType, Integer.valueOf(newValue));
|
|
||||||
}
|
|
||||||
// added c - 1 without firing triggers, the last counter added should fire trigger.
|
|
||||||
if (c > 0) {
|
|
||||||
executePayment(ability, targetCard);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getHashForLKIList() {
|
public String getHashForLKIList() {
|
||||||
return "CounterPut";
|
return "CounterPut";
|
||||||
@@ -219,4 +198,24 @@ public class CostPutCounter extends CostPartWithList {
|
|||||||
return visitor.visit(this);
|
return visitor.visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void triggerCounterPutAll(final SpellAbility ability) {
|
||||||
|
if (counterTable.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameEntityCounterTable tempTable = new GameEntityCounterTable();
|
||||||
|
tempTable.putAll(counterTable);
|
||||||
|
tempTable.triggerCountersPutAll(ability.getHostCard().getGame());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see forge.game.cost.CostPartWithList#resetLists()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void resetLists() {
|
||||||
|
super.resetLists();
|
||||||
|
counterTable.clear();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ public class CostRemoveCounter extends CostPartWithList {
|
|||||||
public final void refund(final Card source) {
|
public final void refund(final Card source) {
|
||||||
int refund = this.getCardList().size() == 1 ? this.cntRemoved : 1; // is wrong for Ooze Flux and Novijen Sages
|
int refund = this.getCardList().size() == 1 ? this.cntRemoved : 1; // is wrong for Ooze Flux and Novijen Sages
|
||||||
for (final Card c : this.getCardList()) {
|
for (final Card c : this.getCardList()) {
|
||||||
c.addCounter(this.counter, refund, source.getController(), false);
|
c.addCounter(this.counter, refund, source.getController(), false, false, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -261,12 +261,14 @@ public class PhaseHandler implements java.io.Serializable {
|
|||||||
if (playerTurn.isArchenemy()) {
|
if (playerTurn.isArchenemy()) {
|
||||||
playerTurn.setSchemeInMotion();
|
playerTurn.setSchemeInMotion();
|
||||||
}
|
}
|
||||||
|
GameEntityCounterTable table = new GameEntityCounterTable();
|
||||||
// all Saga get Lore counter at the begin of pre combat
|
// all Saga get Lore counter at the begin of pre combat
|
||||||
for (Card c : playerTurn.getCardsIn(ZoneType.Battlefield)) {
|
for (Card c : playerTurn.getCardsIn(ZoneType.Battlefield)) {
|
||||||
if (c.getType().hasSubtype("Saga")) {
|
if (c.getType().hasSubtype("Saga")) {
|
||||||
c.addCounter(CounterType.LORE, 1, null, false);
|
c.addCounter(CounterType.LORE, 1, null, false, table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
table.triggerCountersPutAll(game);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -559,7 +559,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
|
|
||||||
// This function handles damage after replacement and prevention effects are applied
|
// This function handles damage after replacement and prevention effects are applied
|
||||||
@Override
|
@Override
|
||||||
public final int addDamageAfterPrevention(final int amount, final Card source, final boolean isCombat, CardDamageMap damageMap) {
|
public final int addDamageAfterPrevention(final int amount, final Card source, final boolean isCombat, CardDamageMap damageMap, GameEntityCounterTable counterTable) {
|
||||||
if (amount <= 0) {
|
if (amount <= 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -570,7 +570,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
|| hasKeyword("All damage is dealt to you as though its source had infect.");
|
|| hasKeyword("All damage is dealt to you as though its source had infect.");
|
||||||
|
|
||||||
if (infect) {
|
if (infect) {
|
||||||
addPoisonCounters(amount, source);
|
addPoisonCounters(amount, source, counterTable);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Worship does not reduce the damage dealt but changes the effect
|
// Worship does not reduce the damage dealt but changes the effect
|
||||||
@@ -882,23 +882,23 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final boolean canReceiveCounters(final CounterType type) {
|
public final boolean canReceiveCounters(final CounterType type) {
|
||||||
if (hasKeyword("PLAYER can't have counters put on him or her.")) {
|
// CantPutCounter static abilities
|
||||||
|
for (final Card ca : getGame().getCardsIn(ZoneType.listValueOf("Battlefield,Command"))) {
|
||||||
|
for (final StaticAbility stAb : ca.getStaticAbilities()) {
|
||||||
|
if (stAb.applyAbility("CantPutCounter", this, type)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (type == CounterType.POISON) {
|
|
||||||
if (hasKeyword("You can't get poison counters")) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int addCounter(final CounterType counterType, final int n, final Player source, final boolean applyMultiplier) {
|
public final int addCounter(final CounterType counterType, final int n, final Player source, final boolean applyMultiplier, GameEntityCounterTable table) {
|
||||||
return addCounter(counterType, n, source, applyMultiplier, true);
|
return addCounter(counterType, n, source, applyMultiplier, true, table);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int addCounter(CounterType counterType, int n, final Player source, boolean applyMultiplier, boolean fireEvents) {
|
public int addCounter(CounterType counterType, int n, final Player source, boolean applyMultiplier, boolean fireEvents, GameEntityCounterTable table) {
|
||||||
if (!canReceiveCounters(counterType)) {
|
if (!canReceiveCounters(counterType)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -942,6 +942,9 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
if (addAmount > 0) {
|
if (addAmount > 0) {
|
||||||
getGame().getTriggerHandler().runTrigger(TriggerType.CounterAddedOnce, runParams, false);
|
getGame().getTriggerHandler().runTrigger(TriggerType.CounterAddedOnce, runParams, false);
|
||||||
}
|
}
|
||||||
|
if (table != null) {
|
||||||
|
table.put(this, counterType, addAmount);
|
||||||
|
}
|
||||||
return addAmount;
|
return addAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -999,9 +1002,9 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
setCounters(CounterType.POISON, num, true);
|
setCounters(CounterType.POISON, num, true);
|
||||||
game.fireEvent(new GameEventPlayerPoisoned(this, source, oldPoison, num));
|
game.fireEvent(new GameEventPlayerPoisoned(this, source, oldPoison, num));
|
||||||
}
|
}
|
||||||
public final void addPoisonCounters(final int num, final Card source) {
|
public final void addPoisonCounters(final int num, final Card source, GameEntityCounterTable table) {
|
||||||
int oldPoison = getCounters(CounterType.POISON);
|
int oldPoison = getCounters(CounterType.POISON);
|
||||||
addCounter(CounterType.POISON, num, source.getController(), false, true);
|
addCounter(CounterType.POISON, num, source.getController(), false, true, table);
|
||||||
|
|
||||||
if (oldPoison != getCounters(CounterType.POISON)) {
|
if (oldPoison != getCounters(CounterType.POISON)) {
|
||||||
game.fireEvent(new GameEventPlayerPoisoned(this, source, oldPoison, num));
|
game.fireEvent(new GameEventPlayerPoisoned(this, source, oldPoison, num));
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import forge.game.card.Card;
|
|||||||
import forge.game.card.CardCollection;
|
import forge.game.card.CardCollection;
|
||||||
import forge.game.card.CardCollectionView;
|
import forge.game.card.CardCollectionView;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
|
import forge.game.card.CounterType;
|
||||||
import forge.game.cost.Cost;
|
import forge.game.cost.Cost;
|
||||||
import forge.game.phase.PhaseHandler;
|
import forge.game.phase.PhaseHandler;
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
@@ -386,6 +387,43 @@ public class StaticAbility extends CardTraitBase implements Comparable<StaticAbi
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final boolean applyAbility(String mode, Card card, CounterType type) {
|
||||||
|
|
||||||
|
// don't apply the ability if it hasn't got the right mode
|
||||||
|
if (!getParam("Mode").equals(mode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isSuppressed() || !this.checkConditions()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode.equals("CantPutCounter")) {
|
||||||
|
return StaticAbilityCantPutCounter.applyCantPutCounter(this, card, type);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final boolean applyAbility(String mode, Player player, CounterType type) {
|
||||||
|
|
||||||
|
// don't apply the ability if it hasn't got the right mode
|
||||||
|
if (!getParam("Mode").equals(mode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isSuppressed() || !this.checkConditions()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode.equals("CantPutCounter")) {
|
||||||
|
return StaticAbilityCantPutCounter.applyCantPutCounter(this, player, type);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply ability.
|
* Apply ability.
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package forge.game.staticability;
|
||||||
|
|
||||||
|
import forge.game.card.Card;
|
||||||
|
import forge.game.card.CounterType;
|
||||||
|
import forge.game.player.Player;
|
||||||
|
|
||||||
|
public class StaticAbilityCantPutCounter {
|
||||||
|
|
||||||
|
public static boolean applyCantPutCounter(final StaticAbility staticAbility, final Card card,
|
||||||
|
final CounterType type) {
|
||||||
|
final Card hostCard = staticAbility.getHostCard();
|
||||||
|
|
||||||
|
if (staticAbility.hasParam("CounterType")) {
|
||||||
|
CounterType t = CounterType.valueOf(staticAbility.getParam("CounterType"));
|
||||||
|
if (t != null && !type.equals(t)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (staticAbility.hasParam("ValidCard")) {
|
||||||
|
if (!card.isValid(staticAbility.getParam("ValidCard").split(","), hostCard.getController(), hostCard, null)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (staticAbility.hasParam("ValidPlayer")) {
|
||||||
|
// for the other part
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean applyCantPutCounter(final StaticAbility staticAbility, final Player player,
|
||||||
|
final CounterType type) {
|
||||||
|
final Card hostCard = staticAbility.getHostCard();
|
||||||
|
|
||||||
|
if (staticAbility.hasParam("CounterType")) {
|
||||||
|
CounterType t = CounterType.valueOf(staticAbility.getParam("CounterType"));
|
||||||
|
if (t != null && !type.equals(t)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (staticAbility.hasParam("ValidPlayer")) {
|
||||||
|
if (!player.isValid(staticAbility.getParam("ValidPlayer").split(","), hostCard.getController(), hostCard, null)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (staticAbility.hasParam("ValidCard")) {
|
||||||
|
// for the other part
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package forge.game.trigger;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
import forge.game.GameEntity;
|
||||||
|
import forge.game.GameEntityCounterTable;
|
||||||
|
import forge.game.card.*;
|
||||||
|
import forge.game.spellability.SpellAbility;
|
||||||
|
|
||||||
|
public class TriggerCounterAddedAll extends Trigger {
|
||||||
|
|
||||||
|
public TriggerCounterAddedAll(Map<String, String> params, Card host, boolean intrinsic) {
|
||||||
|
super(params, host, intrinsic);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean performTest(Map<String, Object> runParams2) {
|
||||||
|
final GameEntityCounterTable table = (GameEntityCounterTable) runParams2.get("Objects");
|
||||||
|
|
||||||
|
if (filterTable(table).isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTriggeringObjects(SpellAbility sa) {
|
||||||
|
final GameEntityCounterTable table = (GameEntityCounterTable) getRunParams().get("Objects");
|
||||||
|
|
||||||
|
Map<GameEntity, Integer> all = this.filterTable(table);
|
||||||
|
|
||||||
|
int amount = 0;
|
||||||
|
for (final Integer v : all.values()) {
|
||||||
|
amount += v;
|
||||||
|
}
|
||||||
|
|
||||||
|
sa.setTriggeringObject("Objects", Lists.newArrayList(all.keySet()));
|
||||||
|
sa.setTriggeringObject("Amount", amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getImportantStackObjects(SpellAbility sa) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("Amount: ").append(sa.getTriggeringObject("Amount"));
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<GameEntity, Integer> filterTable(GameEntityCounterTable table) {
|
||||||
|
CounterType counterType = CounterType.getType(getParam("CounterType"));
|
||||||
|
String valid = getParam("Valid");
|
||||||
|
|
||||||
|
return table.filterTable(counterType, valid, getHostCard(), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -36,6 +36,7 @@ public enum TriggerType {
|
|||||||
Clashed(TriggerClashed.class),
|
Clashed(TriggerClashed.class),
|
||||||
CounterAdded(TriggerCounterAdded.class),
|
CounterAdded(TriggerCounterAdded.class),
|
||||||
CounterAddedOnce(TriggerCounterAddedOnce.class),
|
CounterAddedOnce(TriggerCounterAddedOnce.class),
|
||||||
|
CounterAddedAll(TriggerCounterAddedAll.class),
|
||||||
Countered(TriggerCountered.class),
|
Countered(TriggerCountered.class),
|
||||||
CounterRemoved(TriggerCounterRemoved.class),
|
CounterRemoved(TriggerCounterRemoved.class),
|
||||||
CounterRemovedOnce(TriggerCounterRemovedOnce.class),
|
CounterRemovedOnce(TriggerCounterRemovedOnce.class),
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
|||||||
Game game = initAndCreateGame();
|
Game game = initAndCreateGame();
|
||||||
Player p = game.getPlayers().get(1);
|
Player p = game.getPlayers().get(1);
|
||||||
Card sorin = addCard("Sorin, Solemn Visitor", p);
|
Card sorin = addCard("Sorin, Solemn Visitor", p);
|
||||||
sorin.addCounter(CounterType.LOYALTY, 5, p, false);
|
sorin.addCounter(CounterType.LOYALTY, 5, p, false, null);
|
||||||
|
|
||||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
||||||
game.getAction().checkStateEffects(true);
|
game.getAction().checkStateEffects(true);
|
||||||
@@ -261,7 +261,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
|||||||
String bearCardName = "Runeclaw Bear";
|
String bearCardName = "Runeclaw Bear";
|
||||||
addCard(bearCardName, p);
|
addCard(bearCardName, p);
|
||||||
Card gideon = addCard("Gideon, Ally of Zendikar", p);
|
Card gideon = addCard("Gideon, Ally of Zendikar", p);
|
||||||
gideon.addCounter(CounterType.LOYALTY, 4, p, false);
|
gideon.addCounter(CounterType.LOYALTY, 4, p, false, null);
|
||||||
|
|
||||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
||||||
game.getAction().checkStateEffects(true);
|
game.getAction().checkStateEffects(true);
|
||||||
@@ -380,7 +380,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
|||||||
Game game = initAndCreateGame();
|
Game game = initAndCreateGame();
|
||||||
Player p = game.getPlayers().get(1);
|
Player p = game.getPlayers().get(1);
|
||||||
Card sarkhan = addCard(sarkhanCardName, p);
|
Card sarkhan = addCard(sarkhanCardName, p);
|
||||||
sarkhan.addCounter(CounterType.LOYALTY, 4, p, false);
|
sarkhan.addCounter(CounterType.LOYALTY, 4, p, false, null);
|
||||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
||||||
game.getAction().checkStateEffects(true);
|
game.getAction().checkStateEffects(true);
|
||||||
|
|
||||||
@@ -414,7 +414,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
|||||||
addCard(ornithoperCardName, p);
|
addCard(ornithoperCardName, p);
|
||||||
addCard(bearCardName, p);
|
addCard(bearCardName, p);
|
||||||
Card ajani = addCard(ajaniCardName, p);
|
Card ajani = addCard(ajaniCardName, p);
|
||||||
ajani.addCounter(CounterType.LOYALTY, 4, p, false);
|
ajani.addCounter(CounterType.LOYALTY, 4, p, false, null);
|
||||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
||||||
game.getAction().checkStateEffects(true);
|
game.getAction().checkStateEffects(true);
|
||||||
|
|
||||||
@@ -445,7 +445,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
|||||||
SpellAbility boltSA = boltCard.getFirstSpellAbility();
|
SpellAbility boltSA = boltCard.getFirstSpellAbility();
|
||||||
|
|
||||||
Card ajani = addCard(ajaniCardName, p);
|
Card ajani = addCard(ajaniCardName, p);
|
||||||
ajani.addCounter(CounterType.LOYALTY, 8, p, false);
|
ajani.addCounter(CounterType.LOYALTY, 8, p, false, null);
|
||||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
||||||
game.getAction().checkStateEffects(true);
|
game.getAction().checkStateEffects(true);
|
||||||
|
|
||||||
@@ -494,7 +494,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
|||||||
addCard("Swamp", p);
|
addCard("Swamp", p);
|
||||||
addCard("Swamp", p);
|
addCard("Swamp", p);
|
||||||
Card depths = addCard("Dark Depths", p);
|
Card depths = addCard("Dark Depths", p);
|
||||||
depths.addCounter(CounterType.ICE, 10, p, false);
|
depths.addCounter(CounterType.ICE, 10, p, false, null);
|
||||||
Card thespian = addCard("Thespian's Stage", p);
|
Card thespian = addCard("Thespian's Stage", p);
|
||||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
||||||
game.getAction().checkStateEffects(true);
|
game.getAction().checkStateEffects(true);
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
Name:Hungering Hydra
|
Name:Hungering Hydra
|
||||||
ManaCost:X G
|
ManaCost:X G
|
||||||
Types:Creature Hydra
|
Types:Creature Hydra
|
||||||
|
PT:0/0
|
||||||
K:CantBeBlockedByAmount GT1
|
K:CantBeBlockedByAmount GT1
|
||||||
K:etbCounter:P1P1:X
|
K:etbCounter:P1P1:X
|
||||||
SVar:X:Count$xPaid
|
SVar:X:Count$xPaid
|
||||||
T:Mode$ DamageDoneOnce | ValidTarget$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever CARDNAME is dealt damage, put that many +1/+1 counters on CARDNAME.
|
T:Mode$ DamageDoneOnce | ValidTarget$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever CARDNAME is dealt damage, put that many +1/+1 counters on CARDNAME.
|
||||||
SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ Y | References$ Y
|
SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ Y | References$ Y
|
||||||
SVar:Y:TriggerCount$DamageAmount
|
SVar:Y:TriggerCount$DamageAmount
|
||||||
DeckHas:Ability$Token
|
DeckHas:Ability$Counter
|
||||||
Oracle:Hungering Hydra enters the battlefield with X +1/+1 counters on it.\nHungering Hydra can't be blocked by more than one creature.\nWhenever Hungering Hydra is dealt damage, put that many +1/+1 counters on it. (It must survive the damage to get the counters.)
|
Oracle:Hungering Hydra enters the battlefield with X +1/+1 counters on it.\nHungering Hydra can't be blocked by more than one creature.\nWhenever Hungering Hydra is dealt damage, put that many +1/+1 counters on it. (It must survive the damage to get the counters.)
|
||||||
PT:0/0
|
|
||||||
@@ -2,8 +2,8 @@ Name:Melira, Sylvok Outcast
|
|||||||
ManaCost:1 G
|
ManaCost:1 G
|
||||||
Types:Legendary Creature Human Scout
|
Types:Legendary Creature Human Scout
|
||||||
PT:2/2
|
PT:2/2
|
||||||
K:Creatures you control can't have -1/-1 counters put on them.
|
S:Mode$ CantPutCounter | ValidPlayer$ You | CounterType$ POISON | Description$ You can't get poison counters.
|
||||||
S:Mode$ Continuous | Affected$ You | AddKeyword$ You can't get poison counters | Description$ You can't get poison counters.
|
S:Mode$ CantPutCounter | ValidCard$ Creature.YouCtrl | CounterType$ M1M1 | Description$ Creatures you control can't have -1/-1 counters put on them.
|
||||||
S:Mode$ Continuous | Affected$ Creature.OppCtrl | RemoveKeyword$ Infect | Description$ Creatures your opponents control lose infect.
|
S:Mode$ Continuous | Affected$ Creature.OppCtrl | RemoveKeyword$ Infect | Description$ Creatures your opponents control lose infect.
|
||||||
S:Mode$ Continuous | Affected$ Creature.YouCtrl+withPersist | AddSVar$ Sac
|
S:Mode$ Continuous | Affected$ Creature.YouCtrl+withPersist | AddSVar$ Sac
|
||||||
SVar:Sac:SVar:SacMe:3
|
SVar:Sac:SVar:SacMe:3
|
||||||
|
|||||||
@@ -2,6 +2,6 @@ Name:Melira's Keepers
|
|||||||
ManaCost:4 G
|
ManaCost:4 G
|
||||||
Types:Creature Human Warrior
|
Types:Creature Human Warrior
|
||||||
PT:4/4
|
PT:4/4
|
||||||
K:CARDNAME can't have counters put on it.
|
S:Mode$ CantPutCounter | ValidCard$ Card.Self | Description$ CARDNAME can't have counters put on it.
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/meliras_keepers.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/meliras_keepers.jpg
|
||||||
Oracle:Melira's Keepers can't have counters put on it.
|
Oracle:Melira's Keepers can't have counters put on it.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
Name:Solemnity
|
Name:Solemnity
|
||||||
ManaCost:2 W
|
ManaCost:2 W
|
||||||
Types:Enchantment
|
Types:Enchantment
|
||||||
S:Mode$ Continuous | Affected$ Player | AddKeyword$ PLAYER can't have counters put on him or her. | Description$ Players can't get counters.
|
S:Mode$ CantPutCounter | ValidPlayer$ Player | Description$ Players can't get counters.
|
||||||
S:Mode$ Continuous | Affected$ Creature,Artifact,Enchantment,Land | AddKeyword$ CARDNAME can't have counters put on it. | Description$ Counters can't be put on artifacts, creatures, enchantments or lands.
|
S:Mode$ CantPutCounter | ValidCard$ Creature,Artifact,Enchantment,Land | Description$ Counters can't be put on artifacts, creatures, enchantments or lands.
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/solemnity.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/solemnity.jpg
|
||||||
Oracle:Players can't get counters.\nCounters can't be put on artifacts, creatures, enchantments, or lands.
|
Oracle:Players can't get counters.\nCounters can't be put on artifacts, creatures, enchantments, or lands.
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ Types:Creature Human Cleric
|
|||||||
PT:1/4
|
PT:1/4
|
||||||
T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Battlefield | Execute$ TrigCharm | TriggerDescription$ When CARDNAME enters the battlefield, ABILITY
|
T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Battlefield | Execute$ TrigCharm | TriggerDescription$ When CARDNAME enters the battlefield, ABILITY
|
||||||
SVar:TrigCharm:DB$ Charm | Choices$ CreatureDBRemoveCounter,OpponentDBRemoveCounter | CharmNum$ 1
|
SVar:TrigCharm:DB$ Charm | Choices$ CreatureDBRemoveCounter,OpponentDBRemoveCounter | CharmNum$ 1
|
||||||
SVar:CreatureDBRemoveCounter:DB$ RemoveCounter | ValidTgts$ Creature | RememberObjects$ Targeted | TgtPrompt$ Select target creature | CounterType$ All | CounterNum$ All | SubAbility$ DBPumpCreature | SpellDescription$ Remove all counters from target creature. It can't have counters put on it for as long as CARDNAME remains on the battlefield.
|
SVar:CreatureDBRemoveCounter:DB$ RemoveCounter | ValidTgts$ Creature | TgtPrompt$ Select target creature | CounterType$ All | CounterNum$ All | SubAbility$ DBPumpCreature | SpellDescription$ Remove all counters from target creature. It can't have counters put on it for as long as CARDNAME remains on the battlefield.
|
||||||
SVar:OpponentDBRemoveCounter:DB$ RemoveCounter | ValidTgts$ Opponent | RememberObjects$ Targeted | TgtPrompt$ Select target opponent | CounterType$ All | CounterNum$ All | SubAbility$ DBPumpOpponent | SpellDescription$ Target opponent loses all counters. That player can't get counters for as long as CARDNAME remains on the battlefield.
|
SVar:OpponentDBRemoveCounter:DB$ RemoveCounter | ValidTgts$ Opponent | TgtPrompt$ Select target opponent | CounterType$ All | CounterNum$ All | SubAbility$ DBPumpOpponent | SpellDescription$ Target opponent loses all counters. That player can't get counters for as long as CARDNAME remains on the battlefield.
|
||||||
SVar:DBPumpCreature:DB$ Pump | Defined$ Targeted | KW$ CARDNAME can't have counters put on it. | UntilLoseControlOfHost$ True
|
SVar:DBPumpCreature:DB$ Effect | StaticAbilities$ DBCantPutCounterCreature | RememberObjects$ Targeted | Duration$ UntilHostLeavesPlay | References$ DBCantPutCounterCreature
|
||||||
SVar:DBPumpOpponent:DB$ Pump | Defined$ Targeted | KW$ PLAYER can't have counters put on him or her. | UntilLoseControlOfHost$ True
|
SVar:DBCantPutCounterCreature:Mode$ CantPutCounter | ValidCard$ Card.IsRemembered | EffectZone$ Command | Description$ It can't have counters put on it for as long as EFFECTSOURCE remains on the battlefield.
|
||||||
|
SVar:DBPumpOpponent:DB$ Effect | StaticAbilities$ DBCantPutCounterPlayer | RememberObjects$ Targeted | Duration$ UntilHostLeavesPlay | References$ DBCantPutCounterPlayer
|
||||||
|
SVar:DBCantPutCounterPlayer:Mode$ CantPutCounter | ValidPlayer$ Player.IsRemembered | EffectZone$ Command | Description$ That player can't get counters for as long as Suncleanser remains on the battlefield.
|
||||||
Oracle:When Suncleanser enters the battlefield, choose one —\n• Remove all counters from target creature. It can't have counters put on it for as long as Suncleanser remains on the battlefield.\n• Target opponent loses all counters. That player can't get counters for as long as Suncleanser remains on the battlefield.
|
Oracle:When Suncleanser enters the battlefield, choose one —\n• Remove all counters from target creature. It can't have counters put on it for as long as Suncleanser remains on the battlefield.\n• Target opponent loses all counters. That player can't get counters for as long as Suncleanser remains on the battlefield.
|
||||||
@@ -3,6 +3,6 @@ ManaCost:3
|
|||||||
Types:Artifact Creature Scarecrow
|
Types:Artifact Creature Scarecrow
|
||||||
PT:2/1
|
PT:2/1
|
||||||
K:Flying
|
K:Flying
|
||||||
K:CARDNAME can't have counters put on it.
|
S:Mode$ CantPutCounter | ValidCard$ Card.Self | Description$ CARDNAME can't have counters put on it.
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/tatterkite.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/tatterkite.jpg
|
||||||
Oracle:Flying\nTatterkite can't have counters put on it.
|
Oracle:Flying\nTatterkite can't have counters put on it.
|
||||||
|
|||||||
14
forge-gui/res/cardsfolder/upcoming/bioessence_hydra.txt
Normal file
14
forge-gui/res/cardsfolder/upcoming/bioessence_hydra.txt
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
Name:Bioessence Hydra
|
||||||
|
ManaCost:3 G U
|
||||||
|
Types:Creature Hydra Mutant
|
||||||
|
PT:4/4
|
||||||
|
K:Trample
|
||||||
|
K:etbCounter:P1P1:Y:no Condition:CARDNAME enters the battlefield with a +1/+1 counter on it for each loyalty counter on planeswalkers you control.
|
||||||
|
SVar:Y:Count$TotalCounters_LOYALTY_Planeswalker.YouCtrl
|
||||||
|
T:Mode$ CounterAddedAll | CounterType$ LOYALTY | Valid$ Planeswalker.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever one or more loyalty counters are put on planeswalkers you control, put that many +1/+1 counters on CARDNAME.
|
||||||
|
SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ Z | References$ Z
|
||||||
|
SVar:Z:TriggerCount$Amount
|
||||||
|
DeckHints:Type$Planeswalker
|
||||||
|
DeckHas:Ability$Token
|
||||||
|
Oracle:Trample\nBioessence Hydra enters the battlefield with a +1/+1 counter on it for each loyalty counter on planeswalkers you control.\nWhenever one or more loyalty counters are put on planeswalkers you control, put that many +1/+1 counters on Bioessence Hydra.
|
||||||
|
|
||||||
5
forge-gui/res/cardsfolder/upcoming/price_of_betrayal.txt
Normal file
5
forge-gui/res/cardsfolder/upcoming/price_of_betrayal.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
Name:Price of Betrayal
|
||||||
|
ManaCost:B
|
||||||
|
Types:Sorcery
|
||||||
|
A:SP$ RemoveCounter | Cost$ B | ValidTgts$ Artifact,Creature,Planeswalker,Opponent | TgtPrompt$ Select target artifact, creature, planeswalker, or opponent. | CounterType$ Any | CounterNum$ 5 | UpTo$ True | StackDescription$ SpellDescription | SpellDescription$ Remove up to five counters from target artifact, creature, planeswalker, or opponent.
|
||||||
|
Oracle:Remove up to five counters from target artifact, creature, planeswalker, or opponent.
|
||||||
@@ -201,7 +201,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player.canPayLife(c) && player.getController().confirmPayment(cost, "Pay " + c + " Life?", ability)) {
|
if (controller.confirmPayment(cost, "Do you want " + source + " to deal " + c + " damage to you?", ability)) {
|
||||||
return PaymentDecision.number(c);
|
return PaymentDecision.number(c);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -738,7 +738,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PaymentDecision visit(final CostPutCounter cost) {
|
public PaymentDecision visit(final CostPutCounter cost) {
|
||||||
final Integer c = cost.getNumberOfCounters(ability);
|
final Integer c = cost.convertAmount();
|
||||||
|
|
||||||
if (cost.payCostFromSource()) {
|
if (cost.payCostFromSource()) {
|
||||||
cost.setLastPaidAmount(c);
|
cost.setLastPaidAmount(c);
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import forge.FThreads;
|
|||||||
import forge.card.mana.ManaCost;
|
import forge.card.mana.ManaCost;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameActionUtil;
|
import forge.game.GameActionUtil;
|
||||||
import forge.game.GameLogEntryType;
|
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.ability.effects.CharmEffect;
|
import forge.game.ability.effects.CharmEffect;
|
||||||
@@ -394,58 +393,21 @@ public class HumanPlay {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (part instanceof CostDamage) {
|
else if (part instanceof CostDamage) {
|
||||||
int amount = getAmountFromPartX(part, source, sourceAbility);
|
// not a pay life but damage!
|
||||||
if (!p.canPayLife(amount)) {
|
PaymentDecision pd = part.accept(hcd);
|
||||||
|
|
||||||
|
if (pd == null)
|
||||||
return false;
|
return false;
|
||||||
}
|
else
|
||||||
|
part.payAsDecided(p, pd, sourceAbility);
|
||||||
if (!p.getController().confirmPayment(part, "Do you want " + source + " to deal " + amount + " damage to you?", sourceAbility)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
CardDamageMap damageMap = new CardDamageMap();
|
|
||||||
CardDamageMap preventMap = new CardDamageMap();
|
|
||||||
|
|
||||||
p.addDamage(amount, source, damageMap, preventMap, sourceAbility);
|
|
||||||
|
|
||||||
preventMap.triggerPreventDamage(false);
|
|
||||||
damageMap.triggerDamageDoneOnce(false, sourceAbility);
|
|
||||||
}
|
}
|
||||||
else if (part instanceof CostPutCounter) {
|
else if (part instanceof CostPutCounter) {
|
||||||
CounterType counterType = ((CostPutCounter) part).getCounter();
|
PaymentDecision pd = part.accept(hcd);
|
||||||
int amount = getAmountFromPartX(part, source, sourceAbility);
|
|
||||||
if (part.payCostFromSource()) {
|
|
||||||
if (!source.canReceiveCounters(counterType)) {
|
|
||||||
String message = TextUtil.concatNoSpace("Won't be able to pay upkeep for ", source.toString(), " but it can't have ", counterType.getName(), " counters put on it.");
|
|
||||||
p.getGame().getGameLog().add(GameLogEntryType.STACK_RESOLVE, message);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!p.getController().confirmPayment(part, "Do you want to put " + Lang.nounWithAmount(amount, counterType.getName() + " counter") + " on " + source + "?", sourceAbility)) {
|
if (pd == null)
|
||||||
return false;
|
return false;
|
||||||
}
|
else
|
||||||
|
part.payAsDecided(p, pd, sourceAbility);
|
||||||
source.addCounter(counterType, amount, p, false);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
CardCollectionView list = p.getGame().getCardsIn(ZoneType.Battlefield);
|
|
||||||
list = CardLists.getValidCards(list, part.getType().split(";"), p, source, sourceAbility);
|
|
||||||
if (list.isEmpty()) { return false; }
|
|
||||||
if (!p.getController().confirmPayment(part, "Do you want to put " + Lang.nounWithAmount(amount, counterType.getName() + " counter") + " on " + part.getTypeDescription() + "?", sourceAbility)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
while (amount > 0) {
|
|
||||||
InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, 1, 1, list, sourceAbility);
|
|
||||||
inp.setMessage("Select a card to add a counter to");
|
|
||||||
inp.setCancelAllowed(true);
|
|
||||||
inp.showAndWait();
|
|
||||||
if (inp.hasCancelled()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Card selected = inp.getFirstSelected();
|
|
||||||
selected.addCounter(counterType, 1, p, false);
|
|
||||||
amount--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (part instanceof CostRemoveCounter) {
|
else if (part instanceof CostRemoveCounter) {
|
||||||
CounterType counterType = ((CostRemoveCounter) part).counter;
|
CounterType counterType = ((CostRemoveCounter) part).counter;
|
||||||
|
|||||||
@@ -2190,7 +2190,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
if (subtract) {
|
if (subtract) {
|
||||||
card.subtractCounter(counter, count);
|
card.subtractCounter(counter, count);
|
||||||
} else {
|
} else {
|
||||||
card.addCounter(counter, count, card.getController(), false);
|
card.addCounter(counter, count, card.getController(), false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user