Merge branch 'fightFix' into 'master'

FightEffect: some reworks to make it rules conform

Closes #589

See merge request core-developers/forge!643
This commit is contained in:
Michael Kamensky
2018-06-15 06:40:43 +00:00
13 changed files with 75 additions and 38 deletions

View File

@@ -33,6 +33,12 @@ public class FightAi extends SpellAbilityAi {
sa.resetTargets();
final Card source = sa.getHostCard();
// everything is defined or targeted above, can't do anything there?
if (sa.hasParam("Defined") && !sa.usesTargeting()) {
// TODO extend Logic for cards like Arena or Grothama
return true;
}
// Get creature lists
CardCollectionView aiCreatures = ai.getCreaturesInPlay();
aiCreatures = CardLists.getTargetableCards(aiCreatures, sa);

View File

@@ -41,10 +41,10 @@ public class FightEffect extends DamageBaseEffect {
public void resolve(SpellAbility sa) {
final Card host = sa.getHostCard();
List<Card> fighters = getFighters(sa);
final Game game = sa.getActivatingPlayer().getGame();
final Game game = host.getGame();
if (fighters.size() < 2 || !fighters.get(0).isInPlay()
|| !fighters.get(1).isInPlay()) {
// check is done in getFighters
if (fighters.size() < 2) {
return;
}
@@ -55,21 +55,7 @@ public class FightEffect extends DamageBaseEffect {
}
}
boolean fightToughness = sa.hasParam("FightWithToughness");
CardDamageMap damageMap = new CardDamageMap();
CardDamageMap preventMap = new CardDamageMap();
// Damage is dealt simultaneously, so we calculate the damage from source to target before it is applied
final int dmg1 = fightToughness ? fighters.get(0).getNetToughness() : fighters.get(0).getNetPower();
final int dmg2 = fightToughness ? fighters.get(1).getNetToughness() : fighters.get(1).getNetPower();
dealDamage(fighters.get(0), fighters.get(1), dmg1, damageMap, preventMap, sa);
dealDamage(fighters.get(1), fighters.get(0), dmg2, damageMap, preventMap, sa);
preventMap.triggerPreventDamage(false);
damageMap.triggerDamageDoneOnce(false, sa);
replaceDying(sa);
dealDamage(sa, fighters.get(0), fighters.get(1));
for (Card c : fighters) {
final Map<String, Object> runParams = Maps.newHashMap();
@@ -83,6 +69,8 @@ public class FightEffect extends DamageBaseEffect {
Card fighter1 = null;
Card fighter2 = null;
final Card host = sa.getHostCard();
final Game game = host.getGame();
List<Card> tgts = null;
if (sa.usesTargeting()) {
@@ -92,12 +80,25 @@ public class FightEffect extends DamageBaseEffect {
}
}
if (sa.hasParam("Defined")) {
List<Card> defined = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("Defined"), sa);
List<Card> defined = AbilityUtils.getDefinedCards(host, sa.getParam("Defined"), sa);
// Allow both fighters to come from defined list if first fighter not already found
if (sa.hasParam("ExtraDefined")) {
defined.addAll(AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("ExtraDefined"), sa));
defined.addAll(AbilityUtils.getDefinedCards(host, sa.getParam("ExtraDefined"), sa));
}
List<Card> remove = Lists.newArrayList();
for (final Card d : defined) {
final Card g = game.getCardState(d, null);
// 701.12b If a creature instructed to fight is no longer on the battlefield or is no longer a creature,
// no damage is dealt. If a creature is an illegal target
// for a resolving spell or ability that instructs it to fight, no damage is dealt.
if (g == null || !g.equalsWithTimestamp(d) || !d.isInPlay() || !d.isCreature()) {
// Test to see if the card we're trying to add is in the expected state
remove.add(d);
}
}
defined.removeAll(remove);
if (!defined.isEmpty()) {
if (defined.size() > 1 && fighter1 == null) {
fighter1 = defined.get(0);
@@ -120,9 +121,38 @@ public class FightEffect extends DamageBaseEffect {
return fighterList;
}
private void dealDamage(Card source, Card target, int damage, CardDamageMap damageMap, CardDamageMap preventMap, final SpellAbility sa) {
target.addDamage(damage, source, damageMap, preventMap, sa);
}
private void dealDamage(final SpellAbility sa, Card fighterA, Card fighterB) {
boolean fightToughness = sa.hasParam("FightWithToughness");
boolean usedDamageMap = true;
CardDamageMap damageMap = sa.getDamageMap();
CardDamageMap preventMap = sa.getPreventMap();
if (damageMap == null) {
// make a new damage map
damageMap = new CardDamageMap();
preventMap = new CardDamageMap();
usedDamageMap = false;
}
// 701.12c If a creature fights itself, it deals damage to itself equal to twice its power.
final int dmg1 = fightToughness ? fighterA.getNetToughness() : fighterA.getNetPower();
if (fighterA.equals(fighterB)) {
fighterA.addDamage(dmg1 * 2, fighterA, damageMap, preventMap, sa);
} else {
final int dmg2 = fightToughness ? fighterB.getNetToughness() : fighterB.getNetPower();
fighterB.addDamage(dmg1, fighterA, damageMap, preventMap, sa);
fighterA.addDamage(dmg2, fighterB, damageMap, preventMap, sa);
}
if (!usedDamageMap) {
preventMap.triggerPreventDamage(false);
damageMap.triggerDamageDoneOnce(false, sa);
}
replaceDying(sa);
}
}

View File

@@ -98,7 +98,8 @@ public abstract class Spell extends SpellAbility implements java.io.Serializable
boolean flash = false;
// do performanceMode only for cases where the activator is different than controller
if (!Spell.performanceMode && activator != null && !card.getController().equals(activator)) {
if (!Spell.performanceMode && activator != null && !card.getController().equals(activator)
&& !card.isInZone(ZoneType.Battlefield)) {
// always make a lki copy in this case?
card = CardUtil.getLKICopy(card);
card.setController(activator, 0);

View File

@@ -4,6 +4,6 @@ Types:Creature Human Archer
PT:1/4
K:Reach
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigFight | OptionalDecider$ You | TriggerDescription$ When CARDNAME enters the battlefield, you may have it fight another target creature. (Each deals damage equal to its power to the other.)
SVar:TrigFight:DB$ Fight | Defined$ TriggeredCard | ValidTgts$ Creature.Other | TgtPrompt$ Select another target creature
SVar:TrigFight:DB$ Fight | Defined$ TriggeredCardLKICopy | ValidTgts$ Creature.Other | TgtPrompt$ Select another target creature
SVar:Picture:http://www.wizards.com/global/images/magic/general/atzocan_archer.jpg
Oracle:Reach\nWhen Atzocan Archer enters the battlefield, you may have it fight another target creature. (Each deals damage equal to its power to the other.)
Oracle:Reach\nWhen Atzocan Archer enters the battlefield, you may have it fight another target creature. (Each deals damage equal to its power to the other.)

View File

@@ -8,7 +8,7 @@ SVar:STFlash:Mode$ Continuous | EffectZone$ Command | Affected$ Dinosaur.nonToke
SVar:HatchlingCast:Mode$ SpellCast | ValidCard$ Dinosaur | ValidActivatingPlayer$ You | Execute$ TrigHatchlingAnimate | TriggerZones$ Command | TriggerDescription$ Whenever you cast a Dinosaur spell this turn, it gains "When this creature enters the battlefield, you may have it fight another target creature."
SVar:TrigHatchlingAnimate:DB$ Animate | Defined$ TriggeredCard | Permanent$ True | Triggers$ TrigETBHatchling | sVars$ HatchlingFight
SVar:TrigETBHatchling:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ HatchlingFight | OptionalDecider$ You | TriggerDescription$ When this creature enters the battlefield, you may have it fight another target creature.
SVar:HatchlingFight:DB$ Fight | Defined$ TriggeredCard | ValidTgts$ Creature.Other | TgtPrompt$ Select another target creature
SVar:HatchlingFight:DB$ Fight | Defined$ TriggeredCardLKICopy | ValidTgts$ Creature.Other | TgtPrompt$ Select another target creature
DeckHints:Type$Dinosaur
SVar:Picture:http://www.wizards.com/global/images/magic/general/cherished_hatchling.jpg
Oracle:When Cherished Hatchling dies, you may cast Dinosaur spells this turn as though they had flash, and whenever you cast a Dinosaur spell this turn, it gains "When this creature enters the battlefield, you may have it fight another target creature."

View File

@@ -4,7 +4,7 @@ Types:Creature Dragon
PT:4/5
K:Flying
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigFight | OptionalDecider$ You | TriggerDescription$ When CARDNAME enters the battlefield, you may have it fight target creature you don't control.
SVar:TrigFight:DB$ Fight | Defined$ TriggeredCard | ValidTgts$ Creature.YouDontCtrl | TgtPrompt$ Choose target creature you don't control
SVar:TrigFight:DB$ Fight | Defined$ TriggeredCardLKICopy | ValidTgts$ Creature.YouDontCtrl | TgtPrompt$ Choose target creature you don't control
T:Mode$ Fight | ValidCard$ Creature.YouCtrl | TriggerZones$ Battlefield | Execute$ DelTrigPutCounter | TriggerDescription$ Whenever a creature you control fights, put two +1/+1 counters on it at the beginning of the next end step.
SVar:DelTrigPutCounter:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigPutCounter | RememberObjects$ TriggeredFighter | TriggerDescription$ Put two +1/+1 counters on it at the beginning of the next end step.
SVar:TrigPutCounter:DB$ PutCounter | Defined$ DelayTriggerRemembered | CounterType$ P1P1 | CounterNum$ 2

View File

@@ -8,6 +8,6 @@ SVar:KhansTrigger:Mode$ Phase | Phase$ Main1,Main2 | TriggerZones$ Battlefield |
SVar:ManaGain:DB$ Mana | Produced$ G G
SVar:Dragons:DB$ Animate | Defined$ Self | Triggers$ DragonsTrigger | Permanent$ True | SpellDescription$ Dragons
SVar:DragonsTrigger:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.YouCtrl+withFlying | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ AirFight | TriggerDescription$ Whenever a creature with flying enters the battlefield under your control, you may have it fight target creature you don't control.
SVar:AirFight:DB$ Fight | Defined$ TriggeredCard | ValidTgts$ Creature.YouDontCtrl | TgtPrompt$ Choose target creature you don't control | ConditionDefined$ TriggeredCard | ConditionPresent$ Creature
SVar:AirFight:DB$ Fight | Defined$ TriggeredCardLKICopy | ValidTgts$ Creature.YouDontCtrl | TgtPrompt$ Choose target creature you don't control
SVar:Picture:http://www.wizards.com/global/images/magic/general/frontier_siege.jpg
Oracle:As Frontier Siege enters the battlefield, choose Khans or Dragons.\n• Khans — At the beginning of each of your main phases, add {G}{G}.\n• Dragons — Whenever a creature with flying enters the battlefield under your control, you may have it fight target creature you don't control.

View File

@@ -4,7 +4,7 @@ Types:Legendary Creature Wurm
PT:10/8
S:Mode$ Continuous | Affected$ Creature.Other | AddTrigger$ GrothamaAttack | AddSVar$ HasAttackEffect | Description$ Other creatures have "Whenever this creature attacks, you may have it fight CARDNAME."
SVar:GrothamaAttack:Mode$ Attacks | ValidCard$ Card.Self | Execute$ GrothamaFight | OptionalDecider$ You | TriggerDescription$ Whenever this creature attacks, ABILITY.
SVar:GrothamaFight:DB$ Fight | Defined$ TriggeredAttacker | ExtraDefined$ OriginalHost | SpellDescription$ You may have it fight ORIGINALHOST
SVar:GrothamaFight:DB$ Fight | Defined$ TriggeredAttackerLKICopy | ExtraDefined$ OriginalHost | SpellDescription$ You may have it fight ORIGINALHOST
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Card.Self | Execute$ TrigRepeat | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME leaves the battlefield, each player draws cards equal to the amount of damage dealt to Grothama this turn by sources they controlled.
SVar:TrigRepeat:DB$ RepeatEach | RepeatPlayers$ Player | RepeatSubAbility$ TrigDraw
SVar:TrigDraw:DB$Draw | Defined$ Remembered | NumCards$ X | References$ X

View File

@@ -4,6 +4,6 @@ Types:Creature Beast
PT:6/6
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigFight | TriggerDescription$ Whenever CARDNAME or another creature enters the battlefield under your control, that creature fights target creature an opponent controls.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigFight | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another creature enters the battlefield under your control, that creature fights target creature an opponent controls.
SVar:TrigFight:DB$ Fight | Defined$ TriggeredCard | ValidTgts$ Creature.OppCtrl | TgtPrompt$ Select target creature an opponent controls.
SVar:TrigFight:DB$ Fight | Defined$ TriggeredCardLKICopy | ValidTgts$ Creature.OppCtrl | TgtPrompt$ Select target creature an opponent controls.
SVar:Picture:http://www.wizards.com/global/images/magic/general/gruul_ragebeast.jpg
Oracle:Whenever Gruul Ragebeast or another creature enters the battlefield under your control, that creature fights target creature an opponent controls.

View File

@@ -7,7 +7,7 @@ SVar:DBUntap:DB$ Untap | ValidTgts$ Land | TgtPrompt$ Choose target land | Targe
A:AB$ Dig | Cost$ SubCounter<2/LOYALTY> | Planeswalker$ True | DigNum$ 4 | Reveal$ True | ChangeNum$ 2 | ChangeValid$ Creature | AndOrValid$ Land | DestinationZone2$ Graveyard | Optional$ True | SpellDescription$ Reveal the top four cards of your library. You may put a creature card and/or a land card from among them into your hand. Put the rest into your graveyard.
A:AB$ Effect | Cost$ SubCounter<8/LOYALTY> | Planeswalker$ True | Ultimate$ True | Name$ Emblem - Kiora, Master of the Depths | Image$ emblem_kiora_master_of_the_depths | Triggers$ TrigFight | SVars$ DBFight | Duration$ Permanent | AILogic$ Always | SubAbility$ DBToken | SpellDescription$ You get an emblem with "Whenever a creature enters the battlefield under your control, you may have it fight target creature." Then create three 8/8 blue Octopus creature tokens.
SVar:TrigFight:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.YouCtrl | Execute$ DBFight | OptionalDecider$ You | TriggerZones$ Command | TriggerDescription$ Whenever a creature enters the battlefield under your control, you may have it fight target creature.
SVar:DBFight:DB$ Fight | Defined$ TriggeredCard | ValidTgts$ Creature | TgtPrompt$ Choose target creature
SVar:DBFight:DB$ Fight | Defined$ TriggeredCardLKICopy | ValidTgts$ Creature | TgtPrompt$ Choose target creature
SVar:DBToken:DB$ Token | TokenAmount$ 3 | TokenName$ Octopus | TokenTypes$ Creature,Octopus | TokenOwner$ You | TokenColors$ Blue | TokenPower$ 8 | TokenToughness$ 8
SVar:Picture:http://www.wizards.com/global/images/magic/general/kiora_master_of_the_depths.jpg
Oracle:[+1]: Untap up to one target creature and up to one target land.\n[-2]: Reveal the top four cards of your library. You may put a creature card and/or a land card from among them into your hand. Put the rest into your graveyard.\n[-8]: You get an emblem with "Whenever a creature enters the battlefield under your control, you may have it fight target creature." Then create three 8/8 blue Octopus creature tokens.
Oracle:[+1]: Untap up to one target creature and up to one target land.\n[-2]: Reveal the top four cards of your library. You may put a creature card and/or a land card from among them into your hand. Put the rest into your graveyard.\n[-8]: You get an emblem with "Whenever a creature enters the battlefield under your control, you may have it fight target creature." Then create three 8/8 blue Octopus creature tokens.

View File

@@ -3,7 +3,7 @@ ManaCost:3 G G
Types:Creature Elk
PT:4/3
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigFight | OptionalDecider$ You | TriggerDescription$ When CARDNAME enters the battlefield, you may have it fight target creature you don't control.
SVar:TrigFight:DB$ Fight | Defined$ TriggeredCard | ValidTgts$ Creature.YouDontCtrl | TgtPrompt$ Choose target creature you don't control
SVar:TrigFight:DB$ Fight | Defined$ TriggeredCardLKICopy | ValidTgts$ Creature.YouDontCtrl | TgtPrompt$ Choose target creature you don't control
SVar:PlayMain1:TRUE
SVar:Picture:http://www.wizards.com/global/images/magic/general/somberwald_stag.jpg
Oracle:When Somberwald Stag enters the battlefield, you may have it fight target creature you don't control.

View File

@@ -5,6 +5,6 @@ PT:4/5
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigManifest | TriggerDescription$ When CARDNAME enters the battlefield, manifest the top card of your library. (Put that card onto the battlefield face down as a 2/2 creature. You may turn it face up at any time for its mana cost if it is a creature card.)
SVar:TrigManifest:DB$ Manifest | Amount$ 1 | Defined$ TopOfLibrary
T:Mode$ TurnFaceUp | ValidCard$ Permanent.Creature+YouCtrl | Execute$ TrigFight | TriggerZones$ Battlefield | OptionalDecider$ You | TriggerDescription$ Whenever a permanent you control is turned face up, if it is a creature, you may have it fight target creature you don't control.
SVar:TrigFight:DB$ Fight | Defined$ TriggeredCard | ValidTgts$ Creature.YouDontCtrl | TgtPrompt$ Select target creature you don't control | ConditionDefined$ TriggeredCard | ConditionPresent$ Creature
SVar:TrigFight:DB$ Fight | Defined$ TriggeredCardLKICopy | ValidTgts$ Creature.YouDontCtrl | TgtPrompt$ Select target creature you don't control
SVar:Picture:http://www.wizards.com/global/images/magic/general/temur_war_shaman.jpg
Oracle:When Temur War Shaman enters the battlefield, manifest the top card of your library. (Put that card onto the battlefield face down as a 2/2 creature. Turn it face up any time for its mana cost if it's a creature card.)\nWhenever a permanent you control is turned face up, if it's a creature, you may have it fight target creature you don't control.

View File

@@ -4,6 +4,6 @@ Types:Creature Dinosaur
PT:5/5
K:Kicker:2 G
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self+kicked | Execute$ TrigKicker | TriggerDescription$ When CARDNAME enters the battlefield, if it was kicked, it fights another target creature.
SVar:TrigKicker:DB$ Fight | Defined$ TriggeredCard | ValidTgts$ Creature.Other | TgtPrompt$ Choose another target creature
SVar:TrigKicker:DB$ Fight | Defined$ TriggeredCardLKICopy | ValidTgts$ Creature.Other | TgtPrompt$ Choose another target creature
SVar:PlayMain1:TRUE
Oracle:Kicker {2}{G} (You may pay an additional {2}{G} as you cast this spell.)\nWhen Territorial Allosaurus enters the battlefield, if it was kicked, it fights another target creature.
Oracle:Kicker {2}{G} (You may pay an additional {2}{G} as you cast this spell.)\nWhen Territorial Allosaurus enters the battlefield, if it was kicked, it fights another target creature.