RadiationRework: use Trigger for InternalRadiation (#4799)

* RadiationRework: use Trigger for InternalRadiation

* InternalRadiationEffect: use GameAction::mill

* Radiation: use Num Param instead of Add/Remove like Poison

* Update bloatfly_swarm.txt

* Player: fix removeRadiationEffect on setCounter

---------

Co-authored-by: tool4ever <therealtoolkit@hotmail.com>
This commit is contained in:
Hans Mackowiak
2024-03-10 15:18:40 +01:00
committed by GitHub
parent 29d31071b7
commit 024b958539
21 changed files with 173 additions and 103 deletions

View File

@@ -201,6 +201,7 @@ public enum SpellApiToAi {
.put(ApiType.DamageResolve, AlwaysPlayAi.class)
.put(ApiType.InternalLegendaryRule, LegendaryRuleAi.class)
.put(ApiType.InternalIgnoreEffect, CannotPlayAi.class)
.put(ApiType.InternalRadiation, AlwaysPlayAi.class)
.build());
public SpellAbilityAi get(final ApiType api) {

View File

@@ -235,8 +235,7 @@ public class GameLogFormatter extends IGameEventVisitor.Base<GameLogEntry> {
ev.receiver.toString(), Lang.nounWithNumeralExceptOne(String.valueOf(change), radCtr),
ev.source.toString());
else message = localizer.getMessage("lblLogPlayerRadRemove",
ev.receiver.toString(), Lang.nounWithNumeralExceptOne(String.valueOf(Math.abs(change)), radCtr),
ev.source.toString());
ev.receiver.toString(), Lang.nounWithNumeralExceptOne(String.valueOf(Math.abs(change)), radCtr));
return new GameLogEntry(GameLogEntryType.DAMAGE, message);
}

View File

@@ -204,7 +204,9 @@ public enum ApiType {
DamageResolve (DamageResolveEffect.class),
ChangeZoneResolve (ChangeZoneResolveEffect.class),
InternalLegendaryRule (CharmEffect.class),
InternalIgnoreEffect (CharmEffect.class);
InternalIgnoreEffect (CharmEffect.class),
InternalRadiation (InternalRadiationEffect.class),
;
private final SpellAbilityEffect instanceEffect;
private final Class<? extends SpellAbilityEffect> clsEffect;

View File

@@ -0,0 +1,57 @@
package forge.game.ability.effects;
import java.util.Map;
import com.google.common.base.Predicates;
import com.google.common.collect.Maps;
import forge.game.Game;
import forge.game.ability.AbilityKey;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.CardCollectionView;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.card.CardZoneTable;
import forge.game.card.CounterEnumType;
import forge.game.player.Player;
import forge.game.player.PlayerCollection;
import forge.game.spellability.SpellAbility;
import forge.game.staticability.StaticAbilityGainLifeRadiation;
import forge.game.trigger.TriggerType;
import forge.game.zone.ZoneType;
public class InternalRadiationEffect extends SpellAbilityEffect {
@Override
public void resolve(SpellAbility sa) {
final Player p = sa.getActivatingPlayer();
final Game game = p.getGame();
int numRad = p.getCounters(CounterEnumType.RAD);
Map<AbilityKey, Object> moveParams = AbilityKey.newMap();
final CardZoneTable table = AbilityKey.addCardZoneTableParams(moveParams, sa);
final CardCollectionView milled = game.getAction().mill(new PlayerCollection(p), numRad, ZoneType.Graveyard, sa, moveParams);
table.triggerChangesZoneAll(game, sa);
int n = CardLists.count(milled, Predicates.not(CardPredicates.Presets.LANDS));
if (StaticAbilityGainLifeRadiation.gainLifeRadiation(p)) {
p.gainLife(n, sa.getHostCard(), sa);
} else {
final Map<Player, Integer> lossMap = Maps.newHashMap();
final int lost = p.loseLife(n, false, false);
if (lost > 0) {
lossMap.put(p, lost);
}
if (!lossMap.isEmpty()) { // Run triggers if any player actually lost life
final Map<AbilityKey, Object> runParams = AbilityKey.mapFromPIMap(lossMap);
game.getTriggerHandler().runTrigger(TriggerType.LifeLostAll, runParams, false);
}
}
// and remove n rad counter
p.removeRadCounters(n);
}
}

View File

@@ -1,43 +1,33 @@
package forge.game.ability.effects;
import com.google.common.collect.Maps;
import forge.game.Game;
import forge.game.GameEntityCounterTable;
import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.card.CounterEnumType;
import forge.game.event.GameEventPlayerRadiation;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import java.util.Map;
public class RadiationEffect extends SpellAbilityEffect {
@Override
public void resolve(SpellAbility sa) {
final Card host = sa.getHostCard();
final Player player = sa.getActivatingPlayer();
final Game game = host.getGame();
final int toAdd = AbilityUtils.calculateAmount(host, sa.getParamOrDefault("Add", "0"), sa);
final int toRem = AbilityUtils.calculateAmount(host, sa.getParamOrDefault("Remove", "0"), sa);
final Map<Player, Integer> list = Maps.newHashMap();
final int num = AbilityUtils.calculateAmount(host, sa.getParamOrDefault("Num", "0"), sa);
GameEntityCounterTable table = new GameEntityCounterTable();
for (final Player p : getTargetPlayers(sa)) {
if (!p.isInGame()) continue;
list.put(p, p.getCounters(CounterEnumType.RAD));
if (toAdd >= 1) p.addRadCounters(toAdd, host, table);
else if (toRem >= 1) p.removeRadCounters(toRem, host);
if (num >= 1) {
p.addRadCounters(num, player, table);
} else {
p.removeRadCounters(-num);
}
}
table.replaceCounterEffect(game, sa, true);
for (final Player p : list.keySet()) {
int oldCount = list.get(p);
int newCount = p.getCounters(CounterEnumType.RAD);
if (newCount > 0 && !p.hasRadiationEffect()) p.createRadiationEffect(host.getSetCode());
if (oldCount < newCount) game.fireEvent(new GameEventPlayerRadiation(p, host, newCount - oldCount));
}
}
}

View File

@@ -1,14 +1,13 @@
package forge.game.event;
import forge.game.card.Card;
import forge.game.player.Player;
public class GameEventPlayerRadiation extends GameEvent {
public final Player receiver;
public final Card source;
public final Player source;
public final int change;
public GameEventPlayerRadiation(Player recv, Card src, int chng) {
public GameEventPlayerRadiation(Player recv, Player src, int chng) {
receiver = recv;
source = src;
change = chng;

View File

@@ -17,7 +17,6 @@
*/
package forge.game.phase;
import com.google.common.base.Predicates;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
@@ -43,8 +42,6 @@ import forge.game.trigger.TriggerType;
import forge.game.zone.Zone;
import forge.game.zone.ZoneType;
import forge.util.CollectionSuppliers;
import forge.util.Lang;
import forge.util.Localizer;
import forge.util.TextUtil;
import forge.util.maps.HashMapOfLists;
import forge.util.maps.MapOfLists;
@@ -283,9 +280,6 @@ public class PhaseHandler implements java.io.Serializable {
if (playerTurn.isArchenemy()) {
playerTurn.setSchemeInMotion(null);
}
if (playerTurn.hasRadiationEffect()) {
handleRadiation();
}
GameEntityCounterTable table = new GameEntityCounterTable();
// all Saga get Lore counter at the begin of pre combat
for (Card c : playerTurn.getCardsIn(ZoneType.Battlefield)) {
@@ -527,35 +521,6 @@ public class PhaseHandler implements java.io.Serializable {
}
}
private void handleRadiation() {
int numRad = playerTurn.getCounters(CounterEnumType.RAD);
if (numRad == 0) playerTurn.removeRadiationEffect();
else {
final CardZoneTable table = new CardZoneTable(game.getLastStateBattlefield(), game.getLastStateGraveyard());
Map<AbilityKey, Object> moveParams = AbilityKey.newMap();
AbilityKey.addCardZoneTableParams(moveParams, table);
final SpellAbility sa = new SpellAbility.EmptySa(playerTurn.getRadiationEffect(), playerTurn);
final CardCollectionView milled = playerTurn.mill(numRad, ZoneType.Graveyard, sa, moveParams);
game.getAction().reveal(milled, playerTurn, false,
Localizer.getInstance().getMessage("lblMilledCards", playerTurn), false);
game.getGameLog().add(GameLogEntryType.ZONE_CHANGE, playerTurn + " milled " +
Lang.joinHomogenous(milled) + ".");
table.triggerChangesZoneAll(game, sa);
int n = CardLists.filter(milled, Predicates.not(CardPredicates.Presets.LANDS)).size();
final Map<Player, Integer> lossMap = Maps.newHashMap();
final int lost = playerTurn.loseLife(n, false, false);
if (lost > 0) {
lossMap.put(playerTurn, lost);
}
if (!lossMap.isEmpty()) { // Run triggers if any player actually lost life
final Map<AbilityKey, Object> runParams = AbilityKey.mapFromPIMap(lossMap);
game.getTriggerHandler().runTrigger(TriggerType.LifeLostAll, runParams, false);
}
playerTurn.removeRadCounters(n, playerTurn.getRadiationEffect());
}
}
private void declareAttackersTurnBasedAction() {
final Player whoDeclares = playerDeclaresAttackers == null || playerDeclaresAttackers.hasLost()
? playerTurn

View File

@@ -640,7 +640,7 @@ public class Player extends GameEntity implements Comparable<Player> {
return -1;
}
cnt -= lostEnergy;
this.setCounters(CounterEnumType.ENERGY, cnt, true);
this.setCounters(CounterEnumType.ENERGY, cnt, null, true);
return cnt;
}
@@ -863,7 +863,16 @@ public class Player extends GameEntity implements Comparable<Player> {
final int oldValue = getCounters(counterType);
final int newValue = addAmount + oldValue;
this.setCounters(counterType, newValue, fireEvents);
this.setCounters(counterType, newValue, source, fireEvents);
if (counterType.is(CounterEnumType.RAD) && newValue > 0) {
String setCode = null;
if (params.containsKey(AbilityKey.Cause)) {
SpellAbility cause = (SpellAbility) params.get(AbilityKey.Cause);
setCode = cause.getHostCard().getSetCode();
}
createRadiationEffect(setCode);
}
final Map<AbilityKey, Object> runParams = AbilityKey.mapFromPlayer(this);
runParams.put(AbilityKey.Source, source);
@@ -892,7 +901,7 @@ public class Player extends GameEntity implements Comparable<Player> {
final int delta = oldValue - newValue;
if (delta == 0) { return; }
setCounters(counterName, newValue, true);
setCounters(counterName, newValue, null, true);
/* TODO Run triggers when something cares
int curCounters = oldValue;
@@ -913,16 +922,25 @@ public class Player extends GameEntity implements Comparable<Player> {
getGame().fireEvent(new GameEventPlayerCounters(this, null, 0, 0));
}
public void setCounters(final CounterEnumType counterType, final Integer num, boolean fireEvents) {
this.setCounters(CounterType.get(counterType), num, fireEvents);
public void setCounters(final CounterEnumType counterType, final Integer num, Player source, boolean fireEvents) {
this.setCounters(CounterType.get(counterType), num, source, fireEvents);
}
public void setCounters(final CounterType counterType, final Integer num, boolean fireEvents) {
public void setCounters(final CounterType counterType, final Integer num, Player source, boolean fireEvents) {
Integer old = getCounters(counterType);
setCounters(counterType, num);
view.updateCounters(this);
if (fireEvents) {
getGame().fireEvent(new GameEventPlayerCounters(this, counterType, old, num));
if (counterType.is(CounterEnumType.POISON)) {
getGame().fireEvent(new GameEventPlayerPoisoned(this, source, old, num - old));
} else if (counterType.is(CounterEnumType.RAD)) {
getGame().fireEvent(new GameEventPlayerRadiation(this, source, num - old));
}
}
if (counterType.is(CounterEnumType.RAD) && num <= 0) {
removeRadiationEffect();
}
}
@@ -931,18 +949,20 @@ public class Player extends GameEntity implements Comparable<Player> {
counters = allCounters;
view.updateCounters(this);
getGame().fireEvent(new GameEventPlayerCounters(this, null, 0, 0));
// create Radiation Effect for GameState
if (counters.getOrDefault(CounterType.get(CounterEnumType.RAD), 0) > 0) {
this.createRadiationEffect(null);
} else {
this.removeRadiationEffect();
}
}
public final void addRadCounters(final int num, final Card source, GameEntityCounterTable table) {
addCounter(CounterEnumType.RAD, num, source.getController(), table);
public final void addRadCounters(final int num, final Player source, GameEntityCounterTable table) {
addCounter(CounterEnumType.RAD, num, source, table);
}
public final void removeRadCounters(final int num, final Card source) {
int oldRad = getCounters(CounterEnumType.RAD);
if (oldRad != 0) subtractCounter(CounterEnumType.RAD, num);
int newRad = getCounters(CounterEnumType.RAD);
if (newRad == 0) removeRadiationEffect();
if (oldRad != newRad) game.fireEvent(new GameEventPlayerRadiation(this, source, newRad - oldRad));
public final void removeRadCounters(final int num) {
subtractCounter(CounterEnumType.RAD, num);
}
// TODO Merge These calls into the primary counter calls
@@ -950,25 +970,13 @@ public class Player extends GameEntity implements Comparable<Player> {
return getCounters(CounterEnumType.POISON);
}
public final void setPoisonCounters(final int num, Player source) {
int oldPoison = getCounters(CounterEnumType.POISON);
setCounters(CounterEnumType.POISON, num, true);
game.fireEvent(new GameEventPlayerPoisoned(this, source, oldPoison, num));
setCounters(CounterEnumType.POISON, num, source, true);
}
public final void addPoisonCounters(final int num, final Player source, GameEntityCounterTable table) {
int oldPoison = getCounters(CounterEnumType.POISON);
addCounter(CounterEnumType.POISON, num, source, table);
if (oldPoison != getCounters(CounterEnumType.POISON)) {
game.fireEvent(new GameEventPlayerPoisoned(this, source, oldPoison, num));
}
}
public final void removePoisonCounters(final int num, final Player source) {
int oldPoison = getCounters(CounterEnumType.POISON);
subtractCounter(CounterEnumType.POISON, num);
if (oldPoison != getCounters(CounterEnumType.POISON)) {
game.fireEvent(new GameEventPlayerPoisoned(this, source, oldPoison, num));
}
}
// ================ POISON Merged =================================
public final void addChangedKeywords(final List<String> addKeywords, final List<String> removeKeywords, final Long timestamp, final long staticId) {
@@ -3453,12 +3461,18 @@ public class Player extends GameEntity implements Comparable<Player> {
radiationEffect.setImmutable(true);
radiationEffect.setImageKey("t:radiation");
radiationEffect.setName("Radiation");
radiationEffect.setSetCode(setCode);
String desc = "Mode$ Continuous | Affected$ Card.Self | Description$ At the beginning of your precombat " +
"main phase, if you have any rad counters, mill that many cards. For each nonland card milled " +
"this way, you lose 1 life and a rad counter.";
StaticAbility st = StaticAbility.create(desc, radiationEffect, radiationEffect.getCurrentState(), true);
radiationEffect.addStaticAbility(st);
if (setCode != null) {
radiationEffect.setSetCode(setCode);
}
String trigStr = "Mode$ Phase | PreCombatMain$ True | ValidPlayer$ You | TriggerZones$ Command | TriggerDescription$ " +
"At the beginning of your precombat main phase, if you have any rad counters, mill that many cards. For each nonland card milled this way, you lose 1 life and a rad counter.";
Trigger tr = TriggerHandler.parseTrigger(trigStr, radiationEffect, true);
SpellAbility sa = AbilityFactory.getAbility("DB$ InternalRadiation", radiationEffect);
tr.setOverridingAbility(sa);
radiationEffect.addTrigger(tr);
radiationEffect.updateStateForView();
}
com.add(radiationEffect);

View File

@@ -0,0 +1,33 @@
package forge.game.staticability;
import forge.game.Game;
import forge.game.card.Card;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
public class StaticAbilityGainLifeRadiation {
static String MODE = "GainLifeRadiation";
static public boolean gainLifeRadiation(Player player) {
final Game game = player.getGame();
for (final Card ca : game.getCardsIn(ZoneType.STATIC_ABILITIES_SOURCE_ZONES)) {
for (final StaticAbility stAb : ca.getStaticAbilities()) {
if (!stAb.checkConditions(MODE)) {
continue;
}
if (applyGainLifeRadiation(stAb, player)) {
return true;
}
}
}
return false;
}
static public boolean applyGainLifeRadiation(StaticAbility stAb, Player player) {
if (!stAb.matchesValidParam("ValidPlayer", player)) {
return false;
}
return true;
}
}

View File

@@ -5,5 +5,5 @@ K:Enchant creature
A:SP$ Attach | ValidTgts$ Creature | AILogic$ Pump
S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddPower$ 2 | AddToughness$ 2 | Goad$ True | Description$ Enchanted creature gets +2/+2 and is goaded. (It attacks each combat if able and attacks a player other than you if able.)
T:Mode$ Attacks | ValidCard$ Creature.EnchantedBy | Execute$ TrigRadiation | TriggerDescription$ Whenever enchanted creature attacks, defending player gets two rad counters.
SVar:TrigRadiation:DB$ Radiation | Defined$ TriggeredDefendingPlayer | Add$ 2
SVar:TrigRadiation:DB$ Radiation | Defined$ TriggeredDefendingPlayer | Num$ 2
Oracle:Enchant creature\nEnchanted creature gets +2/+2 and is goaded. (It attacks each combat if able and attacks a player other than you if able.)\nWhenever enchanted creature attacks, defending player gets two rad counters.

View File

@@ -6,7 +6,7 @@ K:Flying
K:etbCounter:P1P1:5
R:Event$ DamageDone | ActiveZones$ Battlefield | ValidTarget$ Card.Self+counters_GE1_P1P1 | ReplaceWith$ Counters | PreventionEffect$ True | AlwaysReplace$ True | Description$ If damage would be dealt to CARDNAME while it has a +1/+1 counter on it, prevent that damage, remove that many +1/+1 counters it, then give each player a rad counter for each +1/+1 counter removed this way.
SVar:Counters:DB$ RemoveCounter | Defined$ ReplacedTarget | CounterType$ P1P1 | CounterNum$ Y | RememberRemoved$ True | SubAbility$ DBRadiation
SVar:DBRadiation:DB$ Radiation | Defined$ Player | Add$ Y
SVar:DBRadiation:DB$ Radiation | Defined$ Player | Num$ Y | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:Y:ReplaceCount$DamageAmount
DeckHas:Ability$Counters

View File

@@ -2,7 +2,7 @@ Name:Contaminated Drink
ManaCost:X U B
Types:Instant
A:SP$ Draw | NumCards$ X | SubAbility$ DBRadiation | SpellDescription$ Draw X cards, then you get half X rad counters, rounded up.
SVar:DBRadiation:DB$ Radiation | Defined$ You | Add$ HalfXUp
SVar:DBRadiation:DB$ Radiation | Defined$ You | Num$ HalfXUp
SVar:X:Count$xPaid
SVar:HalfXUp:Count$xPaid/HalfUp
Oracle:Draw X cards, then you get half X rad counters, rounded up.

View File

@@ -6,7 +6,7 @@ K:Menace
T:Mode$ ChangesZone | ValidCard$ Creature.Other+YouCtrl | Origin$ Battlefield | Destination$ Graveyard | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever another creature you control dies, put a +1/+1 counter on CARDNAME.
SVar:TrigPutCounter:DB$ PutCounter | CounterType$ P1P1 | CounterNum$ 1
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigRadiation | TriggerDescription$ When CARDNAME dies, each opponent gets a number of rad counters equal to its power.
SVar:TrigRadiation:DB$ Radiation | Defined$ Opponent | Add$ TriggeredCard$CardPower
SVar:TrigRadiation:DB$ Radiation | Defined$ Opponent | Num$ TriggeredCard$CardPower
DeckHas:Ability$Counters
DeckHints:Ability$Sacrifice
Oracle:Menace\nWhenever another creature you control dies, put a +1/+1 counter on Feral Ghoul.\nWhen Feral Ghoul dies, each opponent gets a number of rad counters equal to its power.

View File

@@ -3,7 +3,7 @@ ManaCost:no cost
Types:Land
K:ETBReplacement:Other:DBTap:Optional
SVar:DBTap:DB$ Tap | ETB$ True | Defined$ Self | SubAbility$ DBRadiation | SpellDescription$ You may have CARDNAME enter the battlefield tapped. If you do, you get two rad counters.
SVar:DBRadiation:DB$ Radiation | Defined$ You | Add$ 2
SVar:DBRadiation:DB$ Radiation | Defined$ You | Num$ 2
A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}.
A:AB$ Draw | Cost$ 5 T | NumCards$ 1 | ReduceCost$ X | SpellDescription$ Draw a card. This ability costs {1} less to activate for each rad counter you have.
SVar:X:Count$YourCountersRAD

View File

@@ -5,7 +5,7 @@ PT:3/3
K:Flying
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigRadiation | TriggerDescription$ Whenever CARDNAME enters the battlefield or attacks, each player gets a rad counter.
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigRadiation | TriggerZones$ Battlefield | Secondary$ True | TriggerDescription$ Whenever CARDNAME enters the battlefield attacks, each player gets a rad counter.
SVar:TrigRadiation:DB$ Radiation | Defined$ Player | Add$ 1
SVar:TrigRadiation:DB$ Radiation | Defined$ Player | Num$ 1
T:Mode$ MilledAll | ValidPlayer$ Player | ValidCard$ Card.nonLand | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever one or more nonland cards are milled, put a +1/+1 counter on each of up to X target creatures, where X is the number of nonland cards milled this way.
SVar:TrigPutCounter:DB$ PutCounter | CounterNum$ 1 | CounterType$ P1P1 | TargetMin$ 0 | TargetMax$ TriggerCount$Amount | ValidTgts$ Creature | TgtPrompt$ Select up to X target creatures
DeckHints:Ability$Mill

View File

@@ -4,7 +4,7 @@ Types:Creature Crab Mutant
PT:4/4
K:Vigilance
T:Mode$ ChangesZone | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigRadiation | TriggerDescription$ When CARDNAME enters the battlefield, target player gets two rad counters.
SVar:TrigRadiation:DB$ Radiation | ValidTgts$ Player | Add$ 2
SVar:TrigRadiation:DB$ Radiation | ValidTgts$ Player | Num$ 2
T:Mode$ MilledAll | ValidPlayer$ Player | ValidCard$ Card.nonLand | TriggerZones$ Battlefield | Execute$ TrigDraw | ActivationLimit$ 1 | TriggerDescription$ Whenever one or more nonland cards are milled, draw a card, then put a +1/+1 counter on CARDNAME. This ability triggers only once each turn.
SVar:TrigDraw:DB$ Draw | Defined$ You | NumCards$ 1 | SubAbility$ DBPutCounter
SVar:DBPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1

View File

@@ -4,6 +4,6 @@ Types:Creature Mutant Warrior
PT:4/4
K:Ward:2
T:Mode$ ChangesZone | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigRadiation | TriggerDescription$ When CARDNAME enters the battlefield, target player gets four rad counters.
SVar:TrigRadiation:DB$ Radiation | ValidTgts$ Player | Add$ 4
SVar:TrigRadiation:DB$ Radiation | ValidTgts$ Player | Num$ 4
S:Mode$ CantBlockBy | ValidAttacker$ Card.Self | ValidDefender$ Player.Condition Counters.RAD | Description$ CARDNAME can't be blocked as long as defending player has a rad counter.
Oracle:Ward {2} (Whenever this creature becomes the target of a spell or ability an opponent controls, counter it unless that player pays {2}.)\nWhen Nightkin Ambusher enters the battlefield, target player gets four rad counters.\nNightkin Ambusher cant be blocked as long as defending player has a rad counter.

View File

@@ -2,7 +2,7 @@ Name:Nuclear Fallout
ManaCost:X B B
Types:Sorcery
A:SP$ PumpAll | ValidCards$ Creature | NumAtt$ -Y | NumDef$ -Y | SubAbility$ DBRadiation | SpellDescription$ Each creature gets twice -X/-X until end of turn
SVar:DBRadiation:DB$ Radiation | Defined$ Player | Add$ X | SpellDescription$ Each player gets X rad counters.
SVar:DBRadiation:DB$ Radiation | Defined$ Player | Num$ X | SpellDescription$ Each player gets X rad counters.
SVar:X:Count$xPaid
SVar:Y:SVar$X/Twice
Oracle:Each creature gets twice -X/-X until end of turn. Each player gets X rad counters.

View File

@@ -5,6 +5,6 @@ S:Mode$ Continuous | Affected$ Creature.EquippedBy | AddPower$ 3 | AddKeyword$ I
T:Mode$ Attacks | ValidCard$ Card.EquippedBy | Execute$ TrigEffect | TriggerDescription$ Whenever equipped creature attacks, until the end of defending player's next turn, that player gets two rad counters whenever they cast a spell.
SVar:TrigEffect:DB$ Effect | Duration$ UntilTheEndOfYourNextTurn | Triggers$ CastTrig | EffectOwner$ TriggeredDefendingPlayer
SVar:CastTrig:Mode$ SpellCast | ValidCard$ Card | ValidActivatingPlayer$ You | Execute$ TrigRadiation | TriggerDescription$ When you cast a spell, you get two rad counters
SVar:TrigRadiation:DB$ Radiation | Defined$ You | Add$ 2
SVar:TrigRadiation:DB$ Radiation | Defined$ You | Num$ 2
K:Equip:3
Oracle:Equipped creature gets +3/+0 and has intimidate. (It cant be blocked except by artifact creatures and/or creatures that share a color with it.)\nWhenever equipped creature attacks, until the end of defending players next turn, that player gets two rad counters whenever they cast a spell.\nEquip {3}

View File

@@ -0,0 +1,10 @@
Name:Strong, the Brutish Thespian
ManaCost:4 G G
Types:Legendary Creature Mutant Berserker
PT:7/7
K:Ward:2
T:Mode$ DamageDoneOnce | Execute$ TrigDamage | ValidTarget$ Card.Self | TriggerZones$ Battlefield | TriggerDescription$ Enrage — Whenever NICKNAME is dealt damage, you get three rad counters and put three +1/+1 counters on NICKNAME.
SVar:TrigDamage:DB$ Radiation | Defined$ You | Num$ 3 | SubAbility$ DBP1P1
SVar:DBP1P1:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 3
S:Mode$ GainLifeRadiation | ValidPlayer$ You | Description$ You gain life rather than lose life from radiation.
Oracle:Ward {2}\nEnrage — Whenever Strong is dealt damage, you get three rad counters and put three +1/+1 counters on Strong.\nYou gain life rather than lose life from radiation.

View File

@@ -1516,7 +1516,7 @@ lblNonCombat=non-combat
lblLogSourceDealsNDamageOfTypeToDest={0} deals {1} {2} damage to {3}{4}.
lblLogPlayerReceivesNPosionCounterFrom={0} receives {1} poison counter from {2}
lblLogPlayerRadiation={0} gets {1} from {2}.
lblLogPlayerRadRemove={0} removes {1} due to {2}.
lblLogPlayerRadRemove={0} removes {1}.
lblLogPlayerAssignedAttackerToAttackTarget={0} assigned {1} to attack {2}.
lblLogPlayerDidntBlockAttacker={0} didn''t block {1}.
lblLogPlayerAssignedBlockerToBlockAttacker={0} assigned {1} to block {2}.