merge latest trunk

This commit is contained in:
myk
2013-03-04 22:29:05 +00:00
36 changed files with 136 additions and 52 deletions

1
.gitattributes vendored
View File

@@ -12986,6 +12986,7 @@ res/quest/duels/Joe[!!-~]Kidd[!!-~]1.dck -text
res/quest/duels/Joe[!!-~]Kidd[!!-~]2.dck -text res/quest/duels/Joe[!!-~]Kidd[!!-~]2.dck -text
res/quest/duels/Joe[!!-~]Kidd[!!-~]3.dck -text res/quest/duels/Joe[!!-~]Kidd[!!-~]3.dck -text
res/quest/duels/Joker[!!-~]2.dck -text res/quest/duels/Joker[!!-~]2.dck -text
res/quest/duels/Jubilee[!!-~]2.dck -text
res/quest/duels/Kane[!!-~]3.dck -text res/quest/duels/Kane[!!-~]3.dck -text
res/quest/duels/Kang[!!-~]1.dck -text res/quest/duels/Kang[!!-~]1.dck -text
res/quest/duels/Kang[!!-~]2.dck -text res/quest/duels/Kang[!!-~]2.dck -text

View File

@@ -120,16 +120,23 @@ if __name__ == '__main__':
firstLine = cardfile.readline().strip() firstLine = cardfile.readline().strip()
cardName = firstLine[5:] cardName = firstLine[5:]
altName = None
print (cardName, fileName)
validLines = [] validLines = []
validLines.append(firstLine) validLines.append(firstLine)
for line in cardfile.readlines(): for line in cardfile.readlines():
if line[:8] != "SetInfo:" and line[:8] != "SVar:Rar": if line[:8] != "SetInfo:" and line[:8] != "SVar:Rar":
validLines.append(line.strip()) validLines.append(line.strip())
if line[:5] == "Name:":
altName = line[5:].strip()
cardfile.close() cardfile.close()
print (cardName, altName, fileName)
if not cardName in mtgDataCards and not altName is None:
cardName = altName
for e in mtgDataCards[cardName]: for e in mtgDataCards[cardName]:
if not setCodeToForge[e] is None: if not setCodeToForge[e] is None:
validLines.append( "SetInfo:{} {}".format(setCodeToForge[e], mtgDataCards[cardName][e]) ) validLines.append( "SetInfo:{} {}".format(setCodeToForge[e], mtgDataCards[cardName][e]) )

View File

@@ -5,4 +5,5 @@ A:SP$ ChangeZone | Cost$ 2 R | Origin$ Battlefield | Destination$ Library | Vali
SVar:DBDig:DB$Dig | Defined$ TargetedController | DigNum$ 1 | Reveal$ True | DestinationZone$ Battlefield | DestinationZone2$ Library | LibraryPosition2$ 0 | ChangeNum$ All | ChangeValid$ Permanent SVar:DBDig:DB$Dig | Defined$ TargetedController | DigNum$ 1 | Reveal$ True | DestinationZone$ Battlefield | DestinationZone2$ Library | LibraryPosition2$ 0 | ChangeNum$ All | ChangeValid$ Permanent
SVar:Picture:http://www.wizards.com/global/images/magic/general/chaos_warp.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/chaos_warp.jpg
Oracle:The owner of target permanent shuffles it into his or her library, then reveals the top card of his or her library. If it's a permanent card, he or she puts it onto the battlefield. Oracle:The owner of target permanent shuffles it into his or her library, then reveals the top card of his or her library. If it's a permanent card, he or she puts it onto the battlefield.
SetInfo:COM Rare SetInfo:COM Rare
SetInfo:CM1 Rare

View File

@@ -11,4 +11,5 @@ SVar:DecreeX:Remembered$Amount
SVar:RemAIDeck:True SVar:RemAIDeck:True
SVar:Picture:http://www.wizards.com/global/images/magic/general/decree_of_pain.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/decree_of_pain.jpg
Oracle:Destroy all creatures. They can't be regenerated. Draw a card for each creature destroyed this way.\nCycling {3}{B}{B} ({3}{B}{B}, Discard this card: Draw a card.)\nWhen you cycle Decree of Pain, all creatures get -2/-2 until end of turn. Oracle:Destroy all creatures. They can't be regenerated. Draw a card for each creature destroyed this way.\nCycling {3}{B}{B} ({3}{B}{B}, Discard this card: Draw a card.)\nWhen you cycle Decree of Pain, all creatures get -2/-2 until end of turn.
SetInfo:SCG Rare SetInfo:SCG Rare
SetInfo:CM1 Rare

View File

@@ -7,4 +7,5 @@ SVar:X:Targeted$Valid Artifact,Creature
SVar:Picture:http://www.wizards.com/global/images/magic/general/desertion.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/desertion.jpg
Oracle:Counter target spell. If an artifact or creature spell is countered this way, put that card onto the battlefield under your control instead of into its owner's graveyard. Oracle:Counter target spell. If an artifact or creature spell is countered this way, put that card onto the battlefield under your control instead of into its owner's graveyard.
SetInfo:VIS Rare SetInfo:VIS Rare
SetInfo:6ED Rare SetInfo:6ED Rare
SetInfo:CM1 Rare

View File

@@ -7,4 +7,5 @@ T:Mode$ SpellCast | ValidCard$ Card | ValidActivatingPlayer$ Opponent | TriggerZ
SVar:TrigToken:AB$Token | Cost$ 0 | TokenAmount$ 1 | TokenName$ Insect | TokenTypes$ Creature,Insect | TokenOwner$ You | TokenColors$ Green | TokenPower$ 1 | TokenToughness$ 1 SVar:TrigToken:AB$Token | Cost$ 0 | TokenAmount$ 1 | TokenName$ Insect | TokenTypes$ Creature,Insect | TokenOwner$ You | TokenColors$ Green | TokenPower$ 1 | TokenToughness$ 1
SVar:Picture:http://www.wizards.com/global/images/magic/general/dragonlair_spider.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/dragonlair_spider.jpg
Oracle:Reach\nWhenever an opponent casts a spell, put a 1/1 green Insect creature token onto the battlefield. Oracle:Reach\nWhenever an opponent casts a spell, put a 1/1 green Insect creature token onto the battlefield.
SetInfo:PC2 Rare SetInfo:PC2 Rare
SetInfo:CM1 Rare

View File

@@ -14,4 +14,5 @@ SVar:Z:Imprinted$Valid Creature
SVar:Picture:http://www.wizards.com/global/images/magic/general/duplicant.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/duplicant.jpg
Oracle:Imprint - When Duplicant enters the battlefield, you may exile target nontoken creature.\nAs long as the exiled card is a creature card, Duplicant has that card's power, toughness, and creature types. It's still a Shapeshifter. Oracle:Imprint - When Duplicant enters the battlefield, you may exile target nontoken creature.\nAs long as the exiled card is a creature card, Duplicant has that card's power, toughness, and creature types. It's still a Shapeshifter.
SetInfo:MRD Rare SetInfo:MRD Rare
SetInfo:ARC Rare SetInfo:ARC Rare
SetInfo:CM1 Rare

View File

@@ -7,4 +7,5 @@ SVar:TrigDraw:AB$ Draw | Cost$ 0 | NumCards$ 1 | Defined$ TriggeredSourceControl
SVar:PlayMain1:TRUE SVar:PlayMain1:TRUE
SVar:Picture:http://www.wizards.com/global/images/magic/general/edric_spymaster_of_trest.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/edric_spymaster_of_trest.jpg
Oracle:Whenever a creature deals combat damage to one of your opponents, its controller may draw a card. Oracle:Whenever a creature deals combat damage to one of your opponents, its controller may draw a card.
SetInfo:COM Rare SetInfo:COM Rare
SetInfo:CM1 Rare

View File

@@ -7,4 +7,5 @@ T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigChange | TriggerZones$ Bat
SVar:TrigChange:AB$ChangeZone | Cost$ 0 | Origin$ Hand | Destination$ Battlefield | ChangeType$ Creature.Angel+YouCtrl,Creature.Demon+YouCtrl,Creature.Dragon+YouCtrl | Tapped$ True | Attacking$ True SVar:TrigChange:AB$ChangeZone | Cost$ 0 | Origin$ Hand | Destination$ Battlefield | ChangeType$ Creature.Angel+YouCtrl,Creature.Demon+YouCtrl,Creature.Dragon+YouCtrl | Tapped$ True | Attacking$ True
SVar:Picture:http://www.wizards.com/global/images/magic/general/kaalia_of_the_vast.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/kaalia_of_the_vast.jpg
Oracle:Flying\nWhenever Kaalia of the Vast attacks an opponent, you may put an Angel, Demon, or Dragon creature card from your hand onto the battlefield tapped and attacking that opponent. Oracle:Flying\nWhenever Kaalia of the Vast attacks an opponent, you may put an Angel, Demon, or Dragon creature card from your hand onto the battlefield tapped and attacking that opponent.
SetInfo:COM Mythic SetInfo:COM Mythic
SetInfo:CM1 Mythic

View File

@@ -5,4 +5,5 @@ PT:1/1
A:AB$ ChangeZone | Cost$ Sac<1/CARDNAME> | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Creature.Legendary+YouCtrl | TgtPrompt$ Select a target legendary creature card from your graveyard | ChangeNum$ 1 | PlayerTurn$ True | ActivationPhases$ Upkeep->BeginCombat | SpellDescription$ Return target legendary creature card from your graveyard to the battlefield. Activate this ability only during your turn, before attackers are declared. A:AB$ ChangeZone | Cost$ Sac<1/CARDNAME> | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Creature.Legendary+YouCtrl | TgtPrompt$ Select a target legendary creature card from your graveyard | ChangeNum$ 1 | PlayerTurn$ True | ActivationPhases$ Upkeep->BeginCombat | SpellDescription$ Return target legendary creature card from your graveyard to the battlefield. Activate this ability only during your turn, before attackers are declared.
SVar:Picture:http://www.wizards.com/global/images/magic/general/loyal_retainers.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/loyal_retainers.jpg
Oracle:Sacrifice Loyal Retainers: Return target legendary creature card from your graveyard to the battlefield. Activate this ability only during your turn, before attackers are declared. Oracle:Sacrifice Loyal Retainers: Return target legendary creature card from your graveyard to the battlefield. Activate this ability only during your turn, before attackers are declared.
SetInfo:PTK Uncommon SetInfo:PTK Uncommon
SetInfo:CM1 Uncommon

View File

@@ -7,4 +7,5 @@ K:Cascade
S:Mode$ Continuous | Affected$ Creature.YouCtrl | AddKeyword$ Haste | Description$ Creatures you control have haste. S:Mode$ Continuous | Affected$ Creature.YouCtrl | AddKeyword$ Haste | Description$ Creatures you control have haste.
SVar:Picture:http://www.wizards.com/global/images/magic/general/maelstrom_wanderer.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/maelstrom_wanderer.jpg
Oracle:Creatures you control have haste.\nCascade, cascade (When you cast this spell, exile cards from the top of your library until you exile a nonland card that costs less. You may cast it without paying its mana cost. Put the exiled cards on the bottom in a random order. Then do it again.) Oracle:Creatures you control have haste.\nCascade, cascade (When you cast this spell, exile cards from the top of your library until you exile a nonland card that costs less. You may cast it without paying its mana cost. Put the exiled cards on the bottom in a random order. Then do it again.)
SetInfo:PC2 Mythic SetInfo:PC2 Mythic
SetInfo:CM1 Mythic

View File

@@ -5,4 +5,5 @@ T:Mode$ Drawn | ValidCard$ Card.OppOwn | TriggerZones$ Battlefield | OptionalDec
SVar:TrigDraw:AB$Draw | Cost$ 1 | Defined$ You | NumCards$ 1 SVar:TrigDraw:AB$Draw | Cost$ 1 | Defined$ You | NumCards$ 1
SVar:Picture:http://www.wizards.com/global/images/magic/general/minds_eye.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/minds_eye.jpg
Oracle:Whenever an opponent draws a card, you may pay {1}. If you do, draw a card. Oracle:Whenever an opponent draws a card, you may pay {1}. If you do, draw a card.
SetInfo:MRD Rare SetInfo:MRD Rare
SetInfo:CM1 Rare

View File

@@ -6,4 +6,5 @@ T:Mode$ TapsForMana | ValidCard$ Land.YouCtrl | Execute$ TrigMana | TriggerZones
SVar:TrigMana:AB$ManaReflected | Cost$ 0 | ColorOrType$ Type | Valid$ Defined.Triggered | ReflectProperty$ Produced | Defined$ TriggeredPlayer SVar:TrigMana:AB$ManaReflected | Cost$ 0 | ColorOrType$ Type | Valid$ Defined.Triggered | ReflectProperty$ Produced | Defined$ TriggeredPlayer
SVar:Picture:http://www.wizards.com/global/images/magic/general/miraris_wake.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/miraris_wake.jpg
Oracle:Creatures you control get +1/+1.\nWhenever you tap a land for mana, add one mana to your mana pool of any type that land produced. Oracle:Creatures you control get +1/+1.\nWhenever you tap a land for mana, add one mana to your mana pool of any type that land produced.
SetInfo:CM1 Rare
SetInfo:JUD Rare SetInfo:JUD Rare

View File

@@ -5,4 +5,5 @@ T:Mode$ SpellCast | ValidCard$ Card | ValidActivatingPlayer$ Opponent | TriggerZ
SVar:TrigDraw:AB$Draw | Cost$ 0 | Defined$ You | UnlessCost$ 1 | UnlessPayer$ TriggeredPlayer | NumCards$ 1 SVar:TrigDraw:AB$Draw | Cost$ 0 | Defined$ You | UnlessCost$ 1 | UnlessPayer$ TriggeredPlayer | NumCards$ 1
SVar:Picture:http://www.wizards.com/global/images/magic/general/rhystic_study.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/rhystic_study.jpg
Oracle:Whenever an opponent casts a spell, you may draw a card unless that player pays {1}. Oracle:Whenever an opponent casts a spell, you may draw a card unless that player pays {1}.
SetInfo:PCY Common SetInfo:PCY Common
SetInfo:CM1 Common

View File

@@ -4,4 +4,5 @@ Types:Artifact
SVar:RemAIDeck:True SVar:RemAIDeck:True
SVar:Picture:http://www.wizards.com/global/images/magic/general/scroll_rack.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/scroll_rack.jpg
Oracle:{1}, {T}: Exile any number of cards from your hand face down. Put that many cards from the top of your library into your hand. Then look at the exiled cards and put them on top of your library in any order. Oracle:{1}, {T}: Exile any number of cards from your hand face down. Put that many cards from the top of your library into your hand. Then look at the exiled cards and put them on top of your library in any order.
SetInfo:TMP Rare SetInfo:TMP Rare
SetInfo:CM1 Rare

View File

@@ -12,4 +12,5 @@ SVar:Picture:http://www.wizards.com/global/images/magic/general/sylvan_library.j
Oracle:At the beginning of your draw step, you may draw two additional cards. If you do, choose two cards in your hand drawn this turn. For each of those cards, pay 4 life or put the card on top of your library. Oracle:At the beginning of your draw step, you may draw two additional cards. If you do, choose two cards in your hand drawn this turn. For each of those cards, pay 4 life or put the card on top of your library.
SetInfo:5ED Rare SetInfo:5ED Rare
SetInfo:LEG Uncommon SetInfo:LEG Uncommon
SetInfo:CM1 Rare
SetInfo:4ED Rare SetInfo:4ED Rare

View File

@@ -16,4 +16,5 @@ SVar:MimeoX:Remembered$CardPower
SVar:NeedsToPlayVar:MimeoInYard GE2 SVar:NeedsToPlayVar:MimeoInYard GE2
SVar:Picture:http://www.wizards.com/global/images/magic/general/the_mimeoplasm.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/the_mimeoplasm.jpg
Oracle:As The Mimeoplasm enters the battlefield, you may exile two creature cards from graveyards. If you do, it enters the battlefield as a copy of one of those cards with a number of additional +1/+1 counters on it equal to the power of the other card. Oracle:As The Mimeoplasm enters the battlefield, you may exile two creature cards from graveyards. If you do, it enters the battlefield as a copy of one of those cards with a number of additional +1/+1 counters on it equal to the power of the other card.
SetInfo:COM Mythic SetInfo:COM Mythic
SetInfo:CM1 Mythic

View File

@@ -9,4 +9,5 @@ T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Creatu
SVar:TrigLoseLife:AB$ LoseLife | Cost$ 0 | Defined$ Player.Opponent | LifeAmount$ 1 SVar:TrigLoseLife:AB$ LoseLife | Cost$ 0 | Defined$ Player.Opponent | LifeAmount$ 1
SVar:Picture:http://www.wizards.com/global/images/magic/general/vela_the_night_clad.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/vela_the_night_clad.jpg
Oracle:Intimidate\nOther creatures you control have intimidate.\nWhenever Vela the Night-Clad or another creature you control leaves the battlefield, each opponent loses 1 life. Oracle:Intimidate\nOther creatures you control have intimidate.\nWhenever Vela the Night-Clad or another creature you control leaves the battlefield, each opponent loses 1 life.
SetInfo:PC2 Mythic SetInfo:PC2 Mythic
SetInfo:CM1 Mythic

View File

@@ -25,7 +25,7 @@ AQ ATQ # Antiquities
CG UDS # Urza's Destiny CG UDS # Urza's Destiny
CH CHR # Chronicles CH CHR # Chronicles
===CHK # Champions of Kamigawa ===CHK # Champions of Kamigawa
---CM1 # Commander's Arsenal ===CM1 # Commander's Arsenal
CMD COM # Magic: The Gathering-Commander CMD COM # Magic: The Gathering-Commander
CON CFX # Conflux CON CFX # Conflux
===CSP # Coldsnap ===CSP # Coldsnap

View File

@@ -0,0 +1,32 @@
[duel]
[metadata]
Name=Jubilee 2
Title=Jubilee
Difficulty=medium
Description=WUBRG multicolored creature Deck with Blessing of the Nephilim and Knight of New Alara
Icon=Jubilee.jpg
Deck Type=constructed
[main]
1 Tropical Island
3 Tundra
3 Savannah
4 Flooded Strand
1 Windswept Heath
2 Vivid Creek
1 Vivid Grove
2 Vivid Meadow
4 Seaside Citadel
2 Reflecting Pool
1 Pillar of the Paruns
4 Blessing of the Nephilim
4 Civic Saber
4 Jaded Response
4 Knight of New Alara
4 Pledge of Loyalty
4 Bant Sureblade
4 Esper Stormblade
1 Fusion Elemental
2 Naya Hushblade
1 Horde of Notions
4 Transguild Courier
[sideboard]

View File

@@ -8002,7 +8002,7 @@ public class Card extends GameEntity implements Comparable<Card> {
* *
* @param damage * @param damage
* a int. * a int.
* @param possiblePrvenetion * @param possiblePrevention
* a int. * a int.
* @param source * @param source
* a {@link forge.Card} object. * a {@link forge.Card} object.
@@ -8010,7 +8010,7 @@ public class Card extends GameEntity implements Comparable<Card> {
* a boolean. * a boolean.
* @return a int. * @return a int.
*/ */
public final int staticDamagePrevention(final int damage, final int possiblePrvenetion, final Card source, public final int staticDamagePrevention(final int damage, final int possiblePrevention, final Card source,
final boolean isCombat) { final boolean isCombat) {
if (Singletons.getModel().getGame().getStaticEffects().getGlobalRuleChange(GlobalRuleChange.noPrevention)) { if (Singletons.getModel().getGame().getStaticEffects().getGlobalRuleChange(GlobalRuleChange.noPrevention)) {
@@ -8047,9 +8047,9 @@ public class Card extends GameEntity implements Comparable<Card> {
} }
} }
int restDamage = damage - possiblePrvenetion; int restDamage = damage - possiblePrevention;
restDamage = this.staticDamagePrevention(restDamage, source, isCombat); restDamage = this.staticDamagePrevention(restDamage, source, isCombat, true);
return restDamage; return restDamage;
} }
@@ -8070,7 +8070,7 @@ public class Card extends GameEntity implements Comparable<Card> {
* @return a int. * @return a int.
*/ */
@Override @Override
public final int staticDamagePrevention(final int damageIn, final Card source, final boolean isCombat) { public final int staticDamagePrevention(final int damageIn, final Card source, final boolean isCombat, final boolean isTest) {
if (Singletons.getModel().getGame().getStaticEffects().getGlobalRuleChange(GlobalRuleChange.noPrevention)) { if (Singletons.getModel().getGame().getStaticEffects().getGlobalRuleChange(GlobalRuleChange.noPrevention)) {
return damageIn; return damageIn;
@@ -8138,7 +8138,7 @@ public class Card extends GameEntity implements Comparable<Card> {
for (final Card ca : Singletons.getModel().getGame().getCardsIn(ZoneType.listValueOf("Battlefield,Command"))) { for (final Card ca : Singletons.getModel().getGame().getCardsIn(ZoneType.listValueOf("Battlefield,Command"))) {
final ArrayList<StaticAbility> staticAbilities = ca.getStaticAbilities(); final ArrayList<StaticAbility> staticAbilities = ca.getStaticAbilities();
for (final StaticAbility stAb : staticAbilities) { for (final StaticAbility stAb : staticAbilities) {
restDamage = stAb.applyAbility("PreventDamage", source, this, restDamage, isCombat); restDamage = stAb.applyAbility("PreventDamage", source, this, restDamage, isCombat, isTest);
} }
} }
@@ -8198,7 +8198,7 @@ public class Card extends GameEntity implements Comparable<Card> {
return 0; return 0;
} }
restDamage = this.staticDamagePrevention(restDamage, source, isCombat); restDamage = this.staticDamagePrevention(restDamage, source, isCombat, false);
if (restDamage == 0) { if (restDamage == 0) {
return 0; return 0;

View File

@@ -139,7 +139,7 @@ public abstract class GameEntity extends MyObservable {
* a boolean. * a boolean.
* @return a int. * @return a int.
*/ */
public int staticDamagePrevention(final int damage, final Card source, final boolean isCombat) { public int staticDamagePrevention(final int damage, final Card source, final boolean isCombat, final boolean isTest) {
return 0; return 0;
} }

View File

@@ -60,6 +60,6 @@ public class SpellApiBased extends Spell {
chance = ai.doTriggerNoCostWithSubs((AIPlayer)this.getActivatingPlayer(), this, mandatory); chance = ai.doTriggerNoCostWithSubs((AIPlayer)this.getActivatingPlayer(), this, mandatory);
} }
chance = ai.doTriggerAI((AIPlayer)this.getActivatingPlayer(), this, mandatory); chance = ai.doTriggerAI((AIPlayer)this.getActivatingPlayer(), this, mandatory);
return chance; return chance && super.canPlayAI();
} }
} }

View File

@@ -30,7 +30,7 @@ public class BondEffect extends SpellAbilityEffect {
Card partner = cards.get(0); Card partner = cards.get(0);
// skip choice if only one card on list // skip choice if only one card on list
if (cards.size() > 1) { if (cards.size() > 1) {
sa.getActivatingPlayer().getController().chooseSingleCardForEffect(cards, sa, "Select a card to pair with"); partner = sa.getActivatingPlayer().getController().chooseSingleCardForEffect(cards, sa, "Select a card to pair with");
} }
// pair choices together // pair choices together

View File

@@ -224,7 +224,7 @@ public class CardFactory {
} }
} }
controller.getController().mayPlaySpellAbilityForFree(copySA); controller.getController().playSpellAbilityForFree(copySA);
//c.addController(originalController); //c.addController(originalController);
} }

View File

@@ -411,13 +411,19 @@ public class TargetSelection {
// If reached Minimum targets, enable OK button // If reached Minimum targets, enable OK button
if (!tgt.isMinTargetsChosen(sa.getSourceCard(), sa) || tgt.isDividedAsYouChoose()) { if (!tgt.isMinTargetsChosen(sa.getSourceCard(), sa) || tgt.isDividedAsYouChoose()) {
ButtonUtil.enableOnlyCancel(); if (mandatory && tgt.hasCandidates(sa, true)) {
// Player has to click on a target
ButtonUtil.disableAll();
} else {
ButtonUtil.enableOnlyCancel();
}
} else { } else {
ButtonUtil.enableAllFocusOk(); if (mandatory && tgt.hasCandidates(sa, true)) {
} // Player has to click on a target or ok
ButtonUtil.enableOnlyOk();
if (mandatory && tgt.hasCandidates(sa, true)) { } else {
ButtonUtil.enableOnlyOk(); ButtonUtil.enableAllFocusOk();
}
} }
} }

View File

@@ -253,12 +253,12 @@ public class StaticAbility {
* the target * the target
* @param in * @param in
* the in * the in
* @param b * @param isCombat
* the b * the b
* @return the int * @return the int
*/ */
public final int applyAbility(final String mode, final Card source, final GameEntity target, final int in, public final int applyAbility(final String mode, final Card source, final GameEntity target, final int in,
final boolean b) { final boolean isCombat, final boolean isTest) {
// don't apply the ability if it hasn't got the right mode // don't apply the ability if it hasn't got the right mode
if (!this.params.get("Mode").equals(mode)) { if (!this.params.get("Mode").equals(mode)) {
@@ -270,7 +270,7 @@ public class StaticAbility {
} }
if (mode.equals("PreventDamage")) { if (mode.equals("PreventDamage")) {
return StaticAbilityPreventDamage.applyPreventDamageAbility(this, source, target, in, b); return StaticAbilityPreventDamage.applyPreventDamageAbility(this, source, target, in, isCombat, isTest);
} }
return in; return in;

View File

@@ -44,7 +44,7 @@ public class StaticAbilityPreventDamage {
* @return the int * @return the int
*/ */
public static int applyPreventDamageAbility(final StaticAbility stAb, final Card source, final GameEntity target, public static int applyPreventDamageAbility(final StaticAbility stAb, final Card source, final GameEntity target,
final int damage, final boolean isCombat) { final int damage, final boolean isCombat, final boolean isTest) {
final HashMap<String, String> params = stAb.getMapParams(); final HashMap<String, String> params = stAb.getMapParams();
final Card hostCard = stAb.getHostCard(); final Card hostCard = stAb.getHostCard();
int restDamage = damage; int restDamage = damage;
@@ -71,9 +71,9 @@ public class StaticAbilityPreventDamage {
return restDamage; return restDamage;
} }
if (params.containsKey("Optional")) { //Assume if param is present it should be optional if (!isTest && params.containsKey("Optional")) { //Assume if param is present it should be optional
final String logic = params.containsKey("AILogic") ? params.get("AILogic") : ""; final String logic = params.containsKey("AILogic") ? params.get("AILogic") : "";
final String message = "Apply the effect of " + hostCard + "?"; final String message = "Apply the effect of " + hostCard + "? (Affected: " + target + ")";
boolean confirmed = hostCard.getController().getController().confirmStaticApplication(hostCard, target, logic, message); boolean confirmed = hostCard.getController().getController().confirmStaticApplication(hostCard, target, logic, message);
if (!confirmed) { if (!confirmed) {

View File

@@ -1857,7 +1857,7 @@ public class ComputerUtilCombat {
} }
} }
restDamage = target.staticDamagePrevention(restDamage, source, isCombat); restDamage = target.staticDamagePrevention(restDamage, source, isCombat, true);
return restDamage; return restDamage;
} }
@@ -1882,7 +1882,7 @@ public class ComputerUtilCombat {
int restDamage = damage; int restDamage = damage;
restDamage = target.staticReplaceDamage(restDamage, source, isCombat); restDamage = target.staticReplaceDamage(restDamage, source, isCombat);
restDamage = target.staticDamagePrevention(restDamage, source, isCombat); restDamage = target.staticDamagePrevention(restDamage, source, isCombat, true);
return restDamage; return restDamage;
} }

View File

@@ -672,7 +672,7 @@ public abstract class Player extends GameEntity implements Comparable<Player> {
* @return a int. * @return a int.
*/ */
@Override @Override
public final int staticDamagePrevention(final int damage, final Card source, final boolean isCombat) { public final int staticDamagePrevention(final int damage, final Card source, final boolean isCombat, final boolean isTest) {
if (Singletons.getModel().getGame().getStaticEffects().getGlobalRuleChange(GlobalRuleChange.noPrevention)) { if (Singletons.getModel().getGame().getStaticEffects().getGlobalRuleChange(GlobalRuleChange.noPrevention)) {
return damage; return damage;
@@ -709,7 +709,7 @@ public abstract class Player extends GameEntity implements Comparable<Player> {
for (final Card ca : game.getCardsIn(ZoneType.listValueOf("Battlefield,Command"))) { for (final Card ca : game.getCardsIn(ZoneType.listValueOf("Battlefield,Command"))) {
final ArrayList<StaticAbility> staticAbilities = ca.getStaticAbilities(); final ArrayList<StaticAbility> staticAbilities = ca.getStaticAbilities();
for (final StaticAbility stAb : staticAbilities) { for (final StaticAbility stAb : staticAbilities) {
restDamage = stAb.applyAbility("PreventDamage", source, this, restDamage, isCombat); restDamage = stAb.applyAbility("PreventDamage", source, this, restDamage, isCombat, isTest);
} }
} }
@@ -884,7 +884,7 @@ public abstract class Player extends GameEntity implements Comparable<Player> {
return 0; return 0;
} }
restDamage = this.staticDamagePrevention(restDamage, source, isCombat); restDamage = this.staticDamagePrevention(restDamage, source, isCombat, false);
if (restDamage >= this.getPreventNextDamage()) { if (restDamage >= this.getPreventNextDamage()) {
restDamage = restDamage - this.getPreventNextDamage(); restDamage = restDamage - this.getPreventNextDamage();

View File

@@ -76,7 +76,7 @@ public abstract class PlayerController {
*/ */
public abstract void playFromSuspend(Card c); public abstract void playFromSuspend(Card c);
public abstract boolean playCascade(Card cascadedCard, Card sourceCard); public abstract boolean playCascade(Card cascadedCard, Card sourceCard);
public abstract void mayPlaySpellAbilityForFree(SpellAbility copySA); public abstract void playSpellAbilityForFree(SpellAbility copySA);
/** /**
* @return the player * @return the player
*/ */

View File

@@ -138,13 +138,14 @@ public class PlayerControllerAi extends PlayerController {
* @see forge.game.player.PlayerController#mayPlaySpellAbilityForFree(forge.card.spellability.SpellAbility) * @see forge.game.player.PlayerController#mayPlaySpellAbilityForFree(forge.card.spellability.SpellAbility)
*/ */
@Override @Override
public void mayPlaySpellAbilityForFree(SpellAbility copySA) { public void playSpellAbilityForFree(SpellAbility copySA) {
if (copySA instanceof Spell) { if (copySA instanceof Spell) {
Spell spell = (Spell) copySA; Spell spell = (Spell) copySA;
if (spell.canPlayFromEffectAI(false, true)) { if (spell.canPlayFromEffectAI(true, true)) {
ComputerUtil.playStackFree(getPlayer(), copySA); ComputerUtil.playStackFree(getPlayer(), copySA);
} }
} else if (copySA.canPlayAI()) { } else {
copySA.canPlayAI();
ComputerUtil.playStackFree(getPlayer(), copySA); ComputerUtil.playStackFree(getPlayer(), copySA);
} }
} }

View File

@@ -113,7 +113,7 @@ public class PlayerControllerHuman extends PlayerController {
* @see forge.game.player.PlayerController#mayPlaySpellAbilityForFree(forge.card.spellability.SpellAbility) * @see forge.game.player.PlayerController#mayPlaySpellAbilityForFree(forge.card.spellability.SpellAbility)
*/ */
@Override @Override
public void mayPlaySpellAbilityForFree(SpellAbility copySA) { public void playSpellAbilityForFree(SpellAbility copySA) {
game.getActionPlay().playSpellAbilityForFree(copySA); game.getActionPlay().playSpellAbilityForFree(copySA);
} }

View File

@@ -119,12 +119,18 @@ public final class SOverlayUtils {
return overlay; return overlay;
} }
private static boolean _overlayHasFocus;
public static boolean overlayHasFocus() {
return _overlayHasFocus;
}
private static Component prevFocusOwner; private static Component prevFocusOwner;
public static void showOverlay() { public static void showOverlay() {
prevFocusOwner = FocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner(); prevFocusOwner = FocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner();
FOverlay.SINGLETON_INSTANCE.getPanel().setVisible(true); FOverlay.SINGLETON_INSTANCE.getPanel().setVisible(true);
// ensure no background element has focus // ensure no background element has focus
FOverlay.SINGLETON_INSTANCE.getPanel().requestFocusInWindow(); FOverlay.SINGLETON_INSTANCE.getPanel().requestFocusInWindow();
_overlayHasFocus = true;
} }
/** /**
@@ -137,6 +143,7 @@ public final class SOverlayUtils {
prevFocusOwner.requestFocusInWindow(); prevFocusOwner.requestFocusInWindow();
prevFocusOwner = null; prevFocusOwner = null;
} }
_overlayHasFocus = false;
} }
public static void showTargetingOverlay() { public static void showTargetingOverlay() {

View File

@@ -19,6 +19,7 @@ package forge.view;
import javax.swing.JButton; import javax.swing.JButton;
import forge.gui.SOverlayUtils;
import forge.gui.match.VMatchUI; import forge.gui.match.VMatchUI;
/** /**
@@ -50,7 +51,7 @@ public class ButtonUtil {
getOk().setEnabled(false); getOk().setEnabled(false);
getCancel().setEnabled(false); getCancel().setEnabled(false);
} }
public static void enableAllFocusOk() { public static void enableAllFocusOk() {
enableAndFocus(getOk()); enableAndFocus(getOk());
getCancel().setEnabled(true); getCancel().setEnabled(true);
@@ -58,7 +59,11 @@ public class ButtonUtil {
private static void enableAndFocus(final JButton button) { private static void enableAndFocus(final JButton button) {
button.setEnabled(true); button.setEnabled(true);
button.requestFocusInWindow();
// ensure we don't steal focus from an overlay
if (!SOverlayUtils.overlayHasFocus()) {
button.requestFocusInWindow();
}
} }
private static JButton getOk() { private static JButton getOk() {

View File

@@ -570,8 +570,17 @@ public abstract class CardPanelContainer extends JPanel {
public final Card getHoveredCard(MouseEvent e) { public final Card getHoveredCard(MouseEvent e) {
// re-evaluate cursor position so if we hovered over a card, alt-tabbed out of the application, then // re-evaluate cursor position so if we hovered over a card, alt-tabbed out of the application, then
// clicked back on the application somewhere else, the last hovered card won't register the click // clicked back on the application somewhere else, the last hovered card won't register the click
// this cannot protect against alt tabbing off then re-focusing on the application by clicking on
// the already-hovered card, though, since we cannot tell the difference between that and clicking
// on the hovered card when the app already has focus.
CardPanel p = getCardPanel(e.getX(), e.getY()); CardPanel p = getCardPanel(e.getX(), e.getY());
return (p == null && p == hoveredPanel) ? null : p.getGameCard();
// if cursor has jumped, for example via the above alt-tabbing example, fix the card hover highlight
if (null != hoveredPanel && p != hoveredPanel) {
mouseOut(hoveredPanel, e);
}
return (null == p || p != hoveredPanel) ? null : p.getGameCard();
} }
/** /**