mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 18:58:00 +00:00
Card: Wither damage as property, use Static for Everlasting Torment (#3502)
* Card: Wither damage as property, use Static for Everlasting Torment * Update Card.java
This commit is contained in:
@@ -1402,8 +1402,7 @@ public class AiAttackController {
|
||||
boolean hasCombatEffect = attacker.getSVar("HasCombatEffect").equals("TRUE") || "Blocked".equals(attacker.getSVar("HasAttackEffect"));
|
||||
|
||||
if (!hasCombatEffect) {
|
||||
if (attacker.hasKeyword(Keyword.WITHER) || attacker.hasKeyword(Keyword.INFECT)
|
||||
|| attacker.hasKeyword(Keyword.LIFELINK) || attacker.hasKeyword(Keyword.AFFLICT)) {
|
||||
if (attacker.isWitherDamage() || attacker.hasKeyword(Keyword.LIFELINK) || attacker.hasKeyword(Keyword.AFFLICT)) {
|
||||
hasCombatEffect = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -605,8 +605,7 @@ public class ComputerUtilCombat {
|
||||
}
|
||||
|
||||
} // flanking
|
||||
if (attacker.hasKeyword(Keyword.INDESTRUCTIBLE)
|
||||
&& !(defender.hasKeyword(Keyword.WITHER) || defender.hasKeyword(Keyword.INFECT))) {
|
||||
if (attacker.hasKeyword(Keyword.INDESTRUCTIBLE) && !defender.isWitherDamage()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -719,8 +718,7 @@ public class ComputerUtilCombat {
|
||||
int firstStrikeBlockerDmg = 0;
|
||||
|
||||
for (final Card defender : blockers) {
|
||||
if (!(defender.hasKeyword(Keyword.WITHER) || defender.hasKeyword(Keyword.INFECT))
|
||||
&& canDestroyAttacker(ai, attacker, defender, combat, true)) {
|
||||
if (!(defender.isWitherDamage()) && canDestroyAttacker(ai, attacker, defender, combat, true)) {
|
||||
return true;
|
||||
}
|
||||
if (defender.hasFirstStrike() || defender.hasDoubleStrike()) {
|
||||
@@ -901,7 +899,7 @@ public class ComputerUtilCombat {
|
||||
// if the attacker has first strike and wither the blocker will deal
|
||||
// less damage than expected
|
||||
if (dealsFirstStrikeDamage(attacker, withoutAbilities, null)
|
||||
&& (attacker.hasKeyword(Keyword.WITHER) || attacker.hasKeyword(Keyword.INFECT))
|
||||
&& attacker.isWitherDamage()
|
||||
&& !dealsFirstStrikeDamage(blocker, withoutAbilities, null)
|
||||
&& blocker.canReceiveCounters(CounterEnumType.M1M1)) {
|
||||
power -= attacker.getNetCombatDamage();
|
||||
@@ -1193,7 +1191,7 @@ public class ComputerUtilCombat {
|
||||
// less damage than expected
|
||||
if (null != blocker) {
|
||||
if (dealsFirstStrikeDamage(blocker, withoutAbilities, combat)
|
||||
&& (blocker.hasKeyword(Keyword.WITHER) || blocker.hasKeyword(Keyword.INFECT))
|
||||
&& blocker.isWitherDamage()
|
||||
&& !dealsFirstStrikeDamage(attacker, withoutAbilities, combat)
|
||||
&& attacker.canReceiveCounters(CounterEnumType.M1M1)) {
|
||||
power -= blocker.getNetCombatDamage();
|
||||
@@ -1689,7 +1687,7 @@ public class ComputerUtilCombat {
|
||||
} // flanking
|
||||
|
||||
if (((attacker.hasKeyword(Keyword.INDESTRUCTIBLE) || (!withoutAbilities && ComputerUtil.canRegenerate(ai, attacker)))
|
||||
&& !(blocker.hasKeyword(Keyword.WITHER) || blocker.hasKeyword(Keyword.INFECT)))
|
||||
&& !(blocker.isWitherDamage()))
|
||||
|| (attacker.hasKeyword(Keyword.PERSIST) && !attacker.canReceiveCounters(CounterEnumType.M1M1) && (attacker
|
||||
.getCounters(CounterEnumType.M1M1) == 0))
|
||||
|| (attacker.hasKeyword(Keyword.UNDYING) && !attacker.canReceiveCounters(CounterEnumType.P1P1) && (attacker
|
||||
@@ -1795,8 +1793,7 @@ public class ComputerUtilCombat {
|
||||
final List<Card> attackers = combat.getAttackersBlockedBy(blocker);
|
||||
|
||||
for (Card attacker : attackers) {
|
||||
if (!(attacker.hasKeyword(Keyword.WITHER) || attacker.hasKeyword(Keyword.INFECT))
|
||||
&& canDestroyBlocker(ai, blocker, attacker, combat, true)) {
|
||||
if (!(attacker.isWitherDamage()) && canDestroyBlocker(ai, blocker, attacker, combat, true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1902,8 +1899,8 @@ public class ComputerUtilCombat {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (((blocker.hasKeyword(Keyword.INDESTRUCTIBLE) || (!withoutAbilities && ComputerUtil.canRegenerate(ai, blocker))) && !(attacker
|
||||
.hasKeyword(Keyword.WITHER) || attacker.hasKeyword(Keyword.INFECT)))
|
||||
if (((blocker.hasKeyword(Keyword.INDESTRUCTIBLE) || (!withoutAbilities && ComputerUtil.canRegenerate(ai, blocker)))
|
||||
&& !attacker.isWitherDamage())
|
||||
|| (blocker.hasKeyword(Keyword.PERSIST) && !blocker.canReceiveCounters(CounterEnumType.M1M1) && blocker
|
||||
.getCounters(CounterEnumType.M1M1) == 0)
|
||||
|| (blocker.hasKeyword(Keyword.UNDYING) && !blocker.canReceiveCounters(CounterEnumType.P1P1) && blocker
|
||||
@@ -2158,7 +2155,7 @@ public class ComputerUtilCombat {
|
||||
int killDamage = getDamageToKill(c, false);
|
||||
|
||||
if (c.hasKeyword(Keyword.INDESTRUCTIBLE) || c.getCounters(CounterEnumType.SHIELD) > 0 || (c.getShieldCount() > 0 && c.canBeShielded())) {
|
||||
if (!(source.hasKeyword(Keyword.WITHER) || source.hasKeyword(Keyword.INFECT))) {
|
||||
if (!source.isWitherDamage()) {
|
||||
return maxDamage + 1;
|
||||
}
|
||||
} else if (source.hasKeyword(Keyword.DEATHTOUCH) && c.isCreature()) {
|
||||
|
||||
@@ -498,8 +498,8 @@ public class SpecialCardAi {
|
||||
// Already enough to kill the blockers and survive, don't overpump
|
||||
return false;
|
||||
}
|
||||
if (oppCantDie && !source.hasKeyword(Keyword.TRAMPLE) && !source.hasKeyword(Keyword.WITHER)
|
||||
&& !source.hasKeyword(Keyword.INFECT) && predictedPT.getLeft() <= oppT) {
|
||||
if (oppCantDie && !source.hasKeyword(Keyword.TRAMPLE) && !source.isWitherDamage()
|
||||
&& predictedPT.getLeft() <= oppT) {
|
||||
// Can't kill or cripple anyone, as well as can't Trample over, so don't pump
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -201,8 +201,7 @@ public class AttachAi extends SpellAbilityAi {
|
||||
boolean dangerous = false;
|
||||
int totalAtkPower = 0;
|
||||
for (Card attacker : combat.getBlockers(attachTarget)) {
|
||||
if (attacker.hasKeyword(Keyword.DEATHTOUCH) || attacker.hasKeyword(Keyword.INFECT)
|
||||
|| attacker.hasKeyword(Keyword.WITHER)) {
|
||||
if (attacker.hasKeyword(Keyword.DEATHTOUCH) || attacker.isWitherDamage()) {
|
||||
dangerous = true;
|
||||
}
|
||||
totalAtkPower += attacker.getNetPower();
|
||||
|
||||
@@ -350,7 +350,7 @@ public abstract class PumpAiBase extends SpellAbilityAi {
|
||||
return !ph.isPlayerTurn(opp) && ((combat != null && combat.isAttacking(card)) || CombatUtil.canAttack(card, opp))
|
||||
&& !ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS);
|
||||
} else if (keyword.endsWith("Wither")) {
|
||||
if (newPower <= 0 || card.hasKeyword(Keyword.INFECT)) {
|
||||
if (newPower <= 0 || card.isWitherDamage()) {
|
||||
return false;
|
||||
}
|
||||
return combat != null && (combat.isBlocking(card) || (combat.isAttacking(card) && combat.isBlocked(card)));
|
||||
|
||||
@@ -22,7 +22,6 @@ package forge.game;
|
||||
*/
|
||||
public enum GlobalRuleChange {
|
||||
|
||||
alwaysWither ("All damage is dealt as though its source had wither."),
|
||||
attackerChoosesBlockers ("The attacking player chooses how each creature blocks each combat."),
|
||||
manaBurn ("A player losing unspent mana causes that player to lose that much life."),
|
||||
noNight ("It can't become night."),
|
||||
|
||||
@@ -35,7 +35,6 @@ import forge.game.GameActionUtil;
|
||||
import forge.game.GameEntity;
|
||||
import forge.game.GameEntityCounterTable;
|
||||
import forge.game.GameStage;
|
||||
import forge.game.GlobalRuleChange;
|
||||
import forge.game.IHasSVars;
|
||||
import forge.game.ability.AbilityFactory;
|
||||
import forge.game.ability.AbilityKey;
|
||||
@@ -5821,10 +5820,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
subtractCounter(CounterType.get(CounterEnumType.DEFENSE), damageIn, true);
|
||||
}
|
||||
if (isCreature()) {
|
||||
boolean wither = game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.alwaysWither)
|
||||
|| source.hasKeyword(Keyword.WITHER) || source.hasKeyword(Keyword.INFECT);
|
||||
|
||||
if (wither) { // 120.3d
|
||||
if (source.isWitherDamage()) { // 120.3d
|
||||
addCounter(CounterEnumType.M1M1, damageIn, source.getController(), counterTable);
|
||||
damageType = DamageType.M1M1Counters;
|
||||
}
|
||||
@@ -7478,4 +7474,11 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
}
|
||||
return !StaticAbilityActivateAbilityAsIfHaste.canActivate(this);
|
||||
}
|
||||
|
||||
public boolean isWitherDamage() {
|
||||
if (this.hasKeyword(Keyword.WITHER) || this.hasKeyword(Keyword.INFECT)) {
|
||||
return true;
|
||||
}
|
||||
return StaticAbilityWitherDamage.isWitherDamage(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package forge.game.staticability;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
public class StaticAbilityWitherDamage {
|
||||
|
||||
static String MODE = "WitherDamage";
|
||||
|
||||
static public boolean isWitherDamage(Card source) {
|
||||
final Game game = source.getGame();
|
||||
for (final Card ca : game.getCardsIn(ZoneType.STATIC_ABILITIES_SOURCE_ZONES)) {
|
||||
for (final StaticAbility stAb : ca.getStaticAbilities()) {
|
||||
if (!stAb.checkConditions(MODE)) {
|
||||
continue;
|
||||
}
|
||||
if (applyWitherDamageAbility(stAb, source)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static public boolean applyWitherDamageAbility(StaticAbility stAb, Card source) {
|
||||
if (!stAb.matchesValidParam("ValidCard", source)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ ManaCost:2 BR
|
||||
Types:Enchantment
|
||||
S:Mode$ CantGainLife | ValidPlayer$ Player | Description$ Players can't gain life.
|
||||
S:Mode$ CantPreventDamage | Description$ Damage can't be prevented.
|
||||
S:Mode$ Continuous | GlobalRule$ All damage is dealt as though its source had wither. | Description$ All damage is dealt as though its source had wither. (A source with wither deals damage to creatures in the form of -1/-1 counters.)
|
||||
S:Mode$ WitherDamage | Description$ All damage is dealt as though its source had wither. (A source with wither deals damage to creatures in the form of -1/-1 counters.)
|
||||
SVar:NonStackingEffect:True
|
||||
AI:RemoveDeck:Random
|
||||
Oracle:Players can't gain life.\nDamage can't be prevented.\nAll damage is dealt as though its source had wither. (A source with wither deals damage to creatures in the form of -1/-1 counters.)
|
||||
|
||||
Reference in New Issue
Block a user