ONE: Toxic Keyword (#2213)

* ONE: Toxic Keyword

* more scripts

* Proliferate Trigger

* add proliferate trigger

* ~ add Toxic to ai part

* ~ more toxic cards

* add Venser Corpse Puppet

* ~ fix jiang

* ~ fix venser

* predictPoisonFromTriggers Toxic+Double Strike
This commit is contained in:
Hans Mackowiak
2023-01-08 21:13:58 +01:00
committed by GitHub
parent e198b8dafa
commit fb3f14db71
25 changed files with 150 additions and 15 deletions

View File

@@ -2475,11 +2475,14 @@ public class ComputerUtilCombat {
}
}
poison += pd;
if (pd > 0 && attacker.hasDoubleStrike()) {
poison += pd;
}
// TODO: Predict replacement effects for counters (doubled, reduced, additional counters, etc.)
}
// intern toxic effect
poison += attacker.getKeywordMagnitude(Keyword.TOXIC);
}
if (attacker.hasDoubleStrike())
{
poison *= 2;
}
return poison;
}

View File

@@ -5,6 +5,7 @@ import java.util.List;
import forge.game.Game;
import forge.game.GameEntity;
import forge.game.GameEntityCounterTable;
import forge.game.ability.AbilityKey;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.card.CardLists;
@@ -14,6 +15,7 @@ import forge.game.player.Player;
import forge.game.player.PlayerController;
import forge.game.player.PlayerPredicates;
import forge.game.spellability.SpellAbility;
import forge.game.trigger.TriggerType;
import forge.game.zone.ZoneType;
import forge.util.Localizer;
import forge.util.collect.FCollection;
@@ -52,5 +54,7 @@ public class CountersProliferateEffect extends SpellAbilityEffect {
}
}
table.replaceCounterEffect(game, sa, true);
game.getTriggerHandler().runTrigger(TriggerType.Proliferate, AbilityKey.mapFromPlayer(p), false);
}
}

View File

@@ -2251,7 +2251,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|| keyword.startsWith("Fabricate") || keyword.startsWith("Soulshift") || keyword.startsWith("Bushido")
|| keyword.startsWith("Crew") || keyword.startsWith("Tribute") || keyword.startsWith("Absorb")
|| keyword.startsWith("Graft") || keyword.startsWith("Fading") || keyword.startsWith("Vanishing")
|| keyword.startsWith("Afterlife") || keyword.startsWith("Hideaway")
|| keyword.startsWith("Afterlife") || keyword.startsWith("Hideaway") || keyword.startsWith("Toxic")
|| keyword.startsWith("Afflict") || keyword.startsWith ("Poisonous") || keyword.startsWith("Rampage")
|| keyword.startsWith("Renown") || keyword.startsWith("Annihilator") || keyword.startsWith("Devour")) {
final String[] k = keyword.split(":");

View File

@@ -170,6 +170,7 @@ public enum Keyword {
SURGE("Surge", KeywordWithCost.class, false, "You may cast this spell for its surge cost if you or a teammate has cast another spell this turn."),
SUSPEND("Suspend", Suspend.class, false, "Rather than cast this card from your hand, you may pay %s and exile it with {%d:time counter} on it. At the beginning of your upkeep, remove a time counter. When the last is removed, cast it without paying its mana cost."),
TOTEM_ARMOR("Totem armor", SimpleKeyword.class, true, "If enchanted permanent would be destroyed, instead remove all damage marked on it and destroy this Aura."),
TOXIC("Toxic", KeywordWithAmount.class, false, "Players dealt combat damage by this creature also get {%d:poison counter}."),
TRAINING("Training", SimpleKeyword.class, false, "Whenever this creature attacks with another creature with greater power, put a +1/+1 counter on this creature."),
TRAMPLE("Trample", Trample.class, true, "This creature can deal excess combat damage to the player or planeswalker it's attacking."),
TRANSFIGURE("Transfigure", KeywordWithCost.class, false, "%s, Sacrifice this creature: Search your library for a creature card with the same mana value as this creature and put that card onto the battlefield, then shuffle. Transfigure only as a sorcery."),

View File

@@ -671,8 +671,9 @@ public class Player extends GameEntity implements Comparable<Player> {
boolean infect = source.hasKeyword(Keyword.INFECT)
|| hasKeyword("All damage is dealt to you as though its source had infect.");
int poisonCounters = 0;
if (infect) {
addPoisonCounters(amount, source.getController(), counterTable);
poisonCounters += amount;
}
else if (!hasKeyword("Damage doesn't cause you to lose life.")) {
// rule 118.2. Damage dealt to a player normally causes that player to lose that much life.
@@ -684,6 +685,14 @@ public class Player extends GameEntity implements Comparable<Player> {
}
}
if (isCombat) {
poisonCounters += source.getKeywordMagnitude(Keyword.TOXIC);
}
if (poisonCounters > 0) {
addPoisonCounters(poisonCounters, source.getController(), counterTable);
}
//Oathbreaker, Tiny Leaders, and Brawl ignore commander damage rule
if (source.isCommander() && isCombat
&& !this.getGame().getRules().hasAppliedVariant(GameType.Oathbreaker)

View File

@@ -0,0 +1,36 @@
package forge.game.trigger;
import java.util.Map;
import forge.game.ability.AbilityKey;
import forge.game.card.Card;
import forge.game.spellability.SpellAbility;
import forge.util.Localizer;
public class TriggerProliferate extends Trigger {
public TriggerProliferate(Map<String, String> params, Card host, boolean intrinsic) {
super(params, host, intrinsic);
}
@Override
public boolean performTest(Map<AbilityKey, Object> runParams) {
if (!matchesValidParam("ValidPlayer", runParams.get(AbilityKey.Player))) {
return false;
}
return true;
}
@Override
public void setTriggeringObjects(SpellAbility sa, Map<AbilityKey, Object> runParams) {
sa.setTriggeringObjectsFrom(runParams, AbilityKey.Player);
}
@Override
public String getImportantStackObjects(SpellAbility sa) {
StringBuilder sb = new StringBuilder();
sb.append(Localizer.getInstance().getMessage("lblPlayer")).append(": ").append(sa.getTriggeringObject(AbilityKey.Player));
return sb.toString();
}
}

View File

@@ -94,6 +94,7 @@ public enum TriggerType {
PlanarDice(TriggerPlanarDice.class),
PlaneswalkedFrom(TriggerPlaneswalkedFrom.class),
PlaneswalkedTo(TriggerPlaneswalkedTo.class),
Proliferate(TriggerProliferate.class),
Regenerated(TriggerRegenerated.class),
Revealed(TriggerRevealed.class),
RolledDie(TriggerRolledDie.class),

View File

@@ -1,8 +1,8 @@
Name:Bitterblossom
ManaCost:1 B
Types:Tribal Enchantment Faerie
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ At the beginning of your upkeep, you lose 1 life and create a 1/1 black Faerie Rogue creature token with flying.
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ b_1_1_faerie_rogue_flying | TokenOwner$ You | SubAbility$ DB
SVar:DB:DB$ LoseLife | LifeAmount$ 1
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigLoseLife | TriggerDescription$ At the beginning of your upkeep, you lose 1 life and create a 1/1 black Faerie Rogue creature token with flying.
SVar:TrigLoseLife:DB$ LoseLife | LifeAmount$ 1 | SubAbility$ DBToken
SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ b_1_1_faerie_rogue_flying | TokenOwner$ You
SVar:AICastPreference:NeverCastIfLifeBelow$ 4
Oracle:At the beginning of your upkeep, you lose 1 life and create a 1/1 black Faerie Rogue creature token with flying.

View File

@@ -3,7 +3,7 @@ ManaCost:4 G
Types:Legendary Planeswalker Yanggu
Loyalty:4
A:AB$ Pump | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ +2 | NumDef$ +2 | SpellDescription$ Target creature gets +2/+2 until end of turn.
A:AB$ Token | Cost$ SubCounter<1/LOYALTY> | Planeswalker$ True | TokenAmount$ 1 | TokenScript$ mowu | TokenOwner$ You | SpellDescription$ If you don't control a creature named Mowu, create Mowu, a legendary 3/3 green Dog creature token. | IsPresent$ Creature.YouCtrl+namedMowu | PresentCompare$ EQ0
A:AB$ Token | Cost$ SubCounter<1/LOYALTY> | Planeswalker$ True | TokenAmount$ 1 | TokenScript$ mowu | TokenOwner$ You | SpellDescription$ If you don't control a creature named Mowu, create Mowu, a legendary 3/3 green Dog creature token. | ConditionPresent$ Creature.YouCtrl+namedMowu | ConditionCompare$ EQ0
A:AB$ Pump | Cost$ SubCounter<5/LOYALTY> | Planeswalker$ True | Ultimate$ True | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ +X | NumDef$ +X | KW$ Trample | SpellDescription$ Until end of turn, target creature gains trample and gets +X/+X, where X is the number of lands you control.
SVar:X:Count$TypeYouCtrl.Land
Oracle:[+1]: Target creature gets +2/+2 until end of turn.\n[-1]: If you don't control a creature named Mowu, create Mowu, a legendary 3/3 green Dog creature token.\n[-5]: Until end of turn, target creature gains trample and gets +X/+X, where X is the number of lands you control.

View File

@@ -0,0 +1,10 @@
Name:Blightbelly Rat
ManaCost:1 B
Types:Creature Phyrexian Rat
PT:2/2
K:Toxic:1
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigProliferate | TriggerDescription$ When CARDNAME dies, proliferate.
SVar:TrigProliferate:DB$ Proliferate
DeckHas:Ability$Proliferate
DeckNeeds:Ability$Counters
Oracle:Toxic 1 (Players dealt combat damage by this creature also get a poison counter.)\nWhen Blightbelly Rat dies, proliferate.

View File

@@ -0,0 +1,12 @@
Name:Ezuri, Stalker of Spheres
ManaCost:2 G U
Types:Legendary Creature Phyrexian Elf Warrior
PT:3/3
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigProliferate | TriggerDescription$ When CARDNAME enters the battlefield, you may pay {3}. If you do, proliferate twice.
SVar:TrigProliferate:AB$ Proliferate | Cost$ 3 | SubAbility$ TrigProliferate2
SVar:TrigProliferate2:DB$ Proliferate
T:Mode$ Proliferate | ValidPlayer$ You | Execute$ TrigDraw | TriggerDescription$ Whenever you proliferate, draw a card.
SVar:TrigDraw:DB$ Draw
DeckHas:Ability$Proliferate|Counters
DeckNeeds:Ability$Counters
Oracle:When Ezuri, Stalker of Spheres enters the battlefield, you may pay {3}. If you do, proliferate twice.\nWhenever you proliferate, draw a card.

View File

@@ -0,0 +1,8 @@
Name:Mirrex
ManaCost:no cost
Types:Land Sphere
A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}.
A:AB$ Mana | Cost$ T | Produced$ Any | IsPresent$ Card.Self+ThisTurnEntered | SpellDescription$ Add one mana of any color. Activate only if CARDNAME entered the battlefield this turn.
A:AB$ Token | Cost$ 3 T | TokenScript$ c_1_1_a_phyrexian_mite_toxic_noblock | TokenOwner$ You | SpellDescription$ Create a 1/1 colorless Phyrexian Mite artifact creature token with toxic 1 and "This creature can't block." (Players dealt combat damage by it also get a poison counter.)
DeckHas:Ability$Token & Type$Phyrexian|Mite|Artifact
Oracle:{T}: Add {C}.\n{T}: Add one mana of any color. Activate only if Mirrex entered the battlefield this turn.\n{3},{T}: Create a 1/1 colorless Phyrexian Mite artifact creature token with toxic 1 and "This creature can't block." (Players dealt combat damage by it also get a poison counter.)

View File

@@ -0,0 +1,7 @@
Name:Myr Convert
ManaCost:2
Types:Artifact Creature Phyrexian Myr
PT:2/1
K:Toxic:1
A:AB$ Mana | Cost$ T PayLife<2> | Produced$ Any | SpellDescription$ Add one mana of any color.
Oracle:Toxic 1 (Players dealt combat damage by this creature also get a poison counter.)\nT, Pay 2 life: Add one mana of any color.

View File

@@ -0,0 +1,9 @@
Name:Necrogen Rotpriest
ManaCost:2 B G
Types:Creature Phyrexian Zombie Cleric
PT:1/5
K:Toxic:2
T:Mode$ DamageDone | ValidSource$ Creature.YouCtrl+withToxic | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigPoison | TriggerZones$ Battlefield | TriggerDescription$ Whenever a creature you control with toxic deals combat damage to a player, that player gets an additional poison counter.
SVar:TrigPoison:DB$ Poison | Defined$ TriggeredTarget | Num$ 1
A:AB$ Pump | Cost$ 1 B G | ValidTgts$ Creature.YouCtrl+withToxic | TgtPrompt$ Select target creature you control with toxic | KW$ Deathtouch | SpellDescription$ Target creature you control with toxic gains deathtouch until end of turn.
Oracle:Toxic 2 (Players dealt combat damage by this creature also get two poison counters.)\nWhenever a creature you control with toxic deals combat damage to a player, that player gets an additional poison counter.\n1BG: Target creature you control with toxic gains deathtouch until end of turn.

View File

@@ -0,0 +1,9 @@
Name:Skrelv's Hive
ManaCost:1 W
Types:Enchantment
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigLoseLife | TriggerDescription$ At the beginning of your upkeep, you lose 1 life and create a 1/1 colorless Phyrexian Mite artifact creature token with toxic 1 and "This creature can't block."
SVar:TrigLoseLife:DB$ LoseLife | LifeAmount$ 1 | SubAbility$ DBToken
SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_1_1_a_phyrexian_mite_toxic_noblock | TokenOwner$ You
S:Mode$ Continuous | Affected$ Creature.YouCtrl+withToxic | AddKeyword$ Lifelink | CheckSVar$ X | SVarCompare$ GE3 | Description$ Corrupted - As long as an opponent has three or more poison counters, creatures you control with toxic have lifelink.
SVar:X:PlayerCountOpponents$HighestPoisonCounters
Oracle:At the beginning of your upkeep, you lose 1 life and create a 1/1 colorless Phyrexian Mite artifact creature token with toxic 1 and "This creature can't block."\nCorrupted - As long as an opponent has three or more poison counters, creatures you control with toxic have lifelink.

View File

@@ -0,0 +1,12 @@
Name:Venser, Corpse Puppet
ManaCost:U B
Types:Legendary Creature Phyrexian Zombie Wizard
PT:1/3
K:Lifelink
K:Toxic:1
T:Mode$ Proliferate | ValidPlayer$ You | Execute$ TrigChoose | TriggerDescription$ Whenever you proliferate, ABILITY
SVar:TrigChoose:DB$ Charm | Choices$ DBToken,DBPump
SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ the_hollow_sentinel | TokenOwner$ You | ConditionPresent$ Creature.YouCtrl+namedThe Hollow Sentinel | ConditionCompare$ EQ0 | SpellDescription$ If you don't control a creature named The Hollow Sentinel, create The Hollow Sentinel, a legendary 3/3 colorless Phyrexian Golem artifact creature token.
SVar:DBPump:DB$ Pump | ValidTgts$ Creature.Artifact+YouCtrl | TgtPrompt$ Select target artifact creature you control | KW$ Flying & Lifelink | SpellDescription$ Target artifact creature you control gains flying and lifelink until end of turn.
Oracle:Lifelink, toxic 1\nWhenever you proliferate, choose one -\n• If you don't control a creature named The Hollow Sentinel, create The Hollow Sentinel, a legendary 3/3 colorless Phyrexian Golem artifact creature token.\n• Target artifact creature you control gains flying and lifelink until end of turn.

View File

@@ -11,6 +11,7 @@ Lair
Locus
Mine
Power-Plant
Sphere:Spheres
Tower
Urza's
[CreatureTypes]
@@ -166,6 +167,7 @@ Merfolk:Merfolk
Metathran:Metathrans
Minion:Minions
Minotaur:Minotaurs
Mite:Mites
Mole:Moles
Monger:Mongers
Mongoose:Mongooses

View File

@@ -4,5 +4,5 @@ Types:Creature Bird
Colors:black
PT:1/1
K:Flying
K:CARDNAME can't block.
S:Mode$ CantBlockBy | ValidBlocker$ Creature.Self | Description$ CARDNAME can't block.
Oracle:Flying\nThis creature can't block.

View File

@@ -2,7 +2,7 @@ Name:Goblin Construct Token
ManaCost:no cost
PT:0/1
Types:Artifact Creature Goblin Construct
K:CARDNAME can't block.
S:Mode$ CantBlockBy | ValidBlocker$ Creature.Self | Description$ CARDNAME can't block.
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ TrigDealDamage | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of your upkeep, CARDNAME deals 1 damage to you.
SVar:TrigDealDamage:DB$ DealDamage | Defined$ You | NumDmg$ 1
Oracle:This creature can't block.\nAt the beginning of your upkeep, this creature deals 1 damage to you.

View File

@@ -0,0 +1,7 @@
Name:Phyrexian Mite Token
ManaCost:no cost
Types:Artifact Creature Phyrexian Mite
PT:1/1
K:Toxic:1
S:Mode$ CantBlockBy | ValidBlocker$ Creature.Self | Description$ CARDNAME can't block
Oracle:Toxic 1\nThis creature can't block.

View File

@@ -2,5 +2,5 @@ Name:Robot Token
ManaCost:no cost
Types:Artifact Creature Robot
PT:4/4
S:Mode$ CantBlockBy | ValidBlocker$ Creature.Self | Description$ CARDNAME can't block
S:Mode$ CantBlockBy | ValidBlocker$ Creature.Self | Description$ CARDNAME can't block.
Oracle:This creature can't block.

View File

@@ -3,5 +3,5 @@ ManaCost:no cost
Types:Creature Goblin
Colors:red
PT:1/1
K:CARDNAME can't block.
S:Mode$ CantBlockBy | ValidBlocker$ Creature.Self | Description$ CARDNAME can't block.
Oracle:This creature can't block.

View File

@@ -3,6 +3,6 @@ ManaCost:no cost
Types:Creature Pirate
Colors:red
PT:1/1
K:CARDNAME can't block.
S:Mode$ CantBlockBy | ValidBlocker$ Creature.Self | Description$ CARDNAME can't block.
S:Mode$ MustAttack | ValidCreature$ Creature.YouCtrl | Description$ Creatures you control attack each combat if able.
Oracle:This creature can't block.\nCreatures you control attack each combat if able.

View File

@@ -3,5 +3,5 @@ ManaCost:no cost
Types:Creature Satyr
Colors:red
PT:1/1
K:CARDNAME can't block.
S:Mode$ CantBlockBy | ValidBlocker$ Creature.Self | Description$ CARDNAME can't block.
Oracle:This creature can't block.

View File

@@ -0,0 +1,5 @@
Name:The Hollow Sentinel
ManaCost:no cost
Types:Legendary Creature Phyrexian Golem
PT:3/3
Oracle: