mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 18:58:00 +00:00
merge latest trunk
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -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[!!-~]3.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/Kang[!!-~]1.dck -text
|
||||
res/quest/duels/Kang[!!-~]2.dck -text
|
||||
|
||||
@@ -120,16 +120,23 @@ if __name__ == '__main__':
|
||||
|
||||
firstLine = cardfile.readline().strip()
|
||||
cardName = firstLine[5:]
|
||||
altName = None
|
||||
|
||||
print (cardName, fileName)
|
||||
validLines = []
|
||||
validLines.append(firstLine)
|
||||
|
||||
for line in cardfile.readlines():
|
||||
if line[:8] != "SetInfo:" and line[:8] != "SVar:Rar":
|
||||
validLines.append(line.strip())
|
||||
if line[:5] == "Name:":
|
||||
altName = line[5:].strip()
|
||||
cardfile.close()
|
||||
|
||||
print (cardName, altName, fileName)
|
||||
|
||||
if not cardName in mtgDataCards and not altName is None:
|
||||
cardName = altName
|
||||
|
||||
for e in mtgDataCards[cardName]:
|
||||
if not setCodeToForge[e] is None:
|
||||
validLines.append( "SetInfo:{} {}".format(setCodeToForge[e], mtgDataCards[cardName][e]) )
|
||||
|
||||
@@ -6,3 +6,4 @@ SVar:DBDig:DB$Dig | Defined$ TargetedController | DigNum$ 1 | Reveal$ True | Des
|
||||
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.
|
||||
SetInfo:COM Rare
|
||||
SetInfo:CM1 Rare
|
||||
@@ -12,3 +12,4 @@ SVar:RemAIDeck:True
|
||||
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.
|
||||
SetInfo:SCG Rare
|
||||
SetInfo:CM1 Rare
|
||||
@@ -8,3 +8,4 @@ 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.
|
||||
SetInfo:VIS Rare
|
||||
SetInfo:6ED Rare
|
||||
SetInfo:CM1 Rare
|
||||
@@ -8,3 +8,4 @@ SVar:TrigToken:AB$Token | Cost$ 0 | TokenAmount$ 1 | TokenName$ Insect | TokenTy
|
||||
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.
|
||||
SetInfo:PC2 Rare
|
||||
SetInfo:CM1 Rare
|
||||
@@ -15,3 +15,4 @@ 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.
|
||||
SetInfo:MRD Rare
|
||||
SetInfo:ARC Rare
|
||||
SetInfo:CM1 Rare
|
||||
@@ -8,3 +8,4 @@ SVar:PlayMain1:TRUE
|
||||
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.
|
||||
SetInfo:COM Rare
|
||||
SetInfo:CM1 Rare
|
||||
@@ -8,3 +8,4 @@ SVar:TrigChange:AB$ChangeZone | Cost$ 0 | Origin$ Hand | Destination$ Battlefiel
|
||||
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.
|
||||
SetInfo:COM Mythic
|
||||
SetInfo:CM1 Mythic
|
||||
@@ -6,3 +6,4 @@ A:AB$ ChangeZone | Cost$ Sac<1/CARDNAME> | Origin$ Graveyard | Destination$ Batt
|
||||
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.
|
||||
SetInfo:PTK Uncommon
|
||||
SetInfo:CM1 Uncommon
|
||||
@@ -8,3 +8,4 @@ S:Mode$ Continuous | Affected$ Creature.YouCtrl | AddKeyword$ Haste | Descriptio
|
||||
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.)
|
||||
SetInfo:PC2 Mythic
|
||||
SetInfo:CM1 Mythic
|
||||
@@ -6,3 +6,4 @@ SVar:TrigDraw:AB$Draw | Cost$ 1 | Defined$ You | NumCards$ 1
|
||||
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.
|
||||
SetInfo:MRD Rare
|
||||
SetInfo:CM1 Rare
|
||||
@@ -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: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.
|
||||
SetInfo:CM1 Rare
|
||||
SetInfo:JUD Rare
|
||||
@@ -6,3 +6,4 @@ SVar:TrigDraw:AB$Draw | Cost$ 0 | Defined$ You | UnlessCost$ 1 | UnlessPayer$ Tr
|
||||
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}.
|
||||
SetInfo:PCY Common
|
||||
SetInfo:CM1 Common
|
||||
@@ -5,3 +5,4 @@ SVar:RemAIDeck:True
|
||||
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.
|
||||
SetInfo:TMP Rare
|
||||
SetInfo:CM1 Rare
|
||||
@@ -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.
|
||||
SetInfo:5ED Rare
|
||||
SetInfo:LEG Uncommon
|
||||
SetInfo:CM1 Rare
|
||||
SetInfo:4ED Rare
|
||||
@@ -17,3 +17,4 @@ SVar:NeedsToPlayVar:MimeoInYard GE2
|
||||
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.
|
||||
SetInfo:COM Mythic
|
||||
SetInfo:CM1 Mythic
|
||||
@@ -10,3 +10,4 @@ SVar:TrigLoseLife:AB$ LoseLife | Cost$ 0 | Defined$ Player.Opponent | LifeAmount
|
||||
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.
|
||||
SetInfo:PC2 Mythic
|
||||
SetInfo:CM1 Mythic
|
||||
@@ -25,7 +25,7 @@ AQ ATQ # Antiquities
|
||||
CG UDS # Urza's Destiny
|
||||
CH CHR # Chronicles
|
||||
===CHK # Champions of Kamigawa
|
||||
---CM1 # Commander's Arsenal
|
||||
===CM1 # Commander's Arsenal
|
||||
CMD COM # Magic: The Gathering-Commander
|
||||
CON CFX # Conflux
|
||||
===CSP # Coldsnap
|
||||
|
||||
32
res/quest/duels/Jubilee 2.dck
Normal file
32
res/quest/duels/Jubilee 2.dck
Normal 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]
|
||||
@@ -8002,7 +8002,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
*
|
||||
* @param damage
|
||||
* a int.
|
||||
* @param possiblePrvenetion
|
||||
* @param possiblePrevention
|
||||
* a int.
|
||||
* @param source
|
||||
* a {@link forge.Card} object.
|
||||
@@ -8010,7 +8010,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
* a boolean.
|
||||
* @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) {
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -8070,7 +8070,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
* @return a int.
|
||||
*/
|
||||
@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)) {
|
||||
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"))) {
|
||||
final ArrayList<StaticAbility> staticAbilities = ca.getStaticAbilities();
|
||||
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;
|
||||
}
|
||||
|
||||
restDamage = this.staticDamagePrevention(restDamage, source, isCombat);
|
||||
restDamage = this.staticDamagePrevention(restDamage, source, isCombat, false);
|
||||
|
||||
if (restDamage == 0) {
|
||||
return 0;
|
||||
|
||||
@@ -139,7 +139,7 @@ public abstract class GameEntity extends MyObservable {
|
||||
* a boolean.
|
||||
* @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;
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,6 @@ public class SpellApiBased extends Spell {
|
||||
chance = ai.doTriggerNoCostWithSubs((AIPlayer)this.getActivatingPlayer(), this, mandatory);
|
||||
}
|
||||
chance = ai.doTriggerAI((AIPlayer)this.getActivatingPlayer(), this, mandatory);
|
||||
return chance;
|
||||
return chance && super.canPlayAI();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ public class BondEffect extends SpellAbilityEffect {
|
||||
Card partner = cards.get(0);
|
||||
// skip choice if only one card on list
|
||||
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
|
||||
|
||||
@@ -224,7 +224,7 @@ public class CardFactory {
|
||||
}
|
||||
}
|
||||
|
||||
controller.getController().mayPlaySpellAbilityForFree(copySA);
|
||||
controller.getController().playSpellAbilityForFree(copySA);
|
||||
|
||||
//c.addController(originalController);
|
||||
}
|
||||
|
||||
@@ -411,13 +411,19 @@ public class TargetSelection {
|
||||
|
||||
// If reached Minimum targets, enable OK button
|
||||
if (!tgt.isMinTargetsChosen(sa.getSourceCard(), sa) || tgt.isDividedAsYouChoose()) {
|
||||
if (mandatory && tgt.hasCandidates(sa, true)) {
|
||||
// Player has to click on a target
|
||||
ButtonUtil.disableAll();
|
||||
} else {
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
}
|
||||
} else {
|
||||
if (mandatory && tgt.hasCandidates(sa, true)) {
|
||||
// Player has to click on a target or ok
|
||||
ButtonUtil.enableOnlyOk();
|
||||
} else {
|
||||
ButtonUtil.enableAllFocusOk();
|
||||
}
|
||||
|
||||
if (mandatory && tgt.hasCandidates(sa, true)) {
|
||||
ButtonUtil.enableOnlyOk();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -253,12 +253,12 @@ public class StaticAbility {
|
||||
* the target
|
||||
* @param in
|
||||
* the in
|
||||
* @param b
|
||||
* @param isCombat
|
||||
* the b
|
||||
* @return the int
|
||||
*/
|
||||
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
|
||||
if (!this.params.get("Mode").equals(mode)) {
|
||||
@@ -270,7 +270,7 @@ public class StaticAbility {
|
||||
}
|
||||
|
||||
if (mode.equals("PreventDamage")) {
|
||||
return StaticAbilityPreventDamage.applyPreventDamageAbility(this, source, target, in, b);
|
||||
return StaticAbilityPreventDamage.applyPreventDamageAbility(this, source, target, in, isCombat, isTest);
|
||||
}
|
||||
|
||||
return in;
|
||||
|
||||
@@ -44,7 +44,7 @@ public class StaticAbilityPreventDamage {
|
||||
* @return the int
|
||||
*/
|
||||
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 Card hostCard = stAb.getHostCard();
|
||||
int restDamage = damage;
|
||||
@@ -71,9 +71,9 @@ public class StaticAbilityPreventDamage {
|
||||
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 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);
|
||||
|
||||
if (!confirmed) {
|
||||
|
||||
@@ -1857,7 +1857,7 @@ public class ComputerUtilCombat {
|
||||
}
|
||||
}
|
||||
|
||||
restDamage = target.staticDamagePrevention(restDamage, source, isCombat);
|
||||
restDamage = target.staticDamagePrevention(restDamage, source, isCombat, true);
|
||||
|
||||
return restDamage;
|
||||
}
|
||||
@@ -1882,7 +1882,7 @@ public class ComputerUtilCombat {
|
||||
int restDamage = damage;
|
||||
|
||||
restDamage = target.staticReplaceDamage(restDamage, source, isCombat);
|
||||
restDamage = target.staticDamagePrevention(restDamage, source, isCombat);
|
||||
restDamage = target.staticDamagePrevention(restDamage, source, isCombat, true);
|
||||
|
||||
return restDamage;
|
||||
}
|
||||
|
||||
@@ -672,7 +672,7 @@ public abstract class Player extends GameEntity implements Comparable<Player> {
|
||||
* @return a int.
|
||||
*/
|
||||
@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)) {
|
||||
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"))) {
|
||||
final ArrayList<StaticAbility> staticAbilities = ca.getStaticAbilities();
|
||||
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;
|
||||
}
|
||||
|
||||
restDamage = this.staticDamagePrevention(restDamage, source, isCombat);
|
||||
restDamage = this.staticDamagePrevention(restDamage, source, isCombat, false);
|
||||
|
||||
if (restDamage >= this.getPreventNextDamage()) {
|
||||
restDamage = restDamage - this.getPreventNextDamage();
|
||||
|
||||
@@ -76,7 +76,7 @@ public abstract class PlayerController {
|
||||
*/
|
||||
public abstract void playFromSuspend(Card c);
|
||||
public abstract boolean playCascade(Card cascadedCard, Card sourceCard);
|
||||
public abstract void mayPlaySpellAbilityForFree(SpellAbility copySA);
|
||||
public abstract void playSpellAbilityForFree(SpellAbility copySA);
|
||||
/**
|
||||
* @return the player
|
||||
*/
|
||||
|
||||
@@ -138,13 +138,14 @@ public class PlayerControllerAi extends PlayerController {
|
||||
* @see forge.game.player.PlayerController#mayPlaySpellAbilityForFree(forge.card.spellability.SpellAbility)
|
||||
*/
|
||||
@Override
|
||||
public void mayPlaySpellAbilityForFree(SpellAbility copySA) {
|
||||
public void playSpellAbilityForFree(SpellAbility copySA) {
|
||||
if (copySA instanceof Spell) {
|
||||
Spell spell = (Spell) copySA;
|
||||
if (spell.canPlayFromEffectAI(false, true)) {
|
||||
if (spell.canPlayFromEffectAI(true, true)) {
|
||||
ComputerUtil.playStackFree(getPlayer(), copySA);
|
||||
}
|
||||
} else if (copySA.canPlayAI()) {
|
||||
} else {
|
||||
copySA.canPlayAI();
|
||||
ComputerUtil.playStackFree(getPlayer(), copySA);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ public class PlayerControllerHuman extends PlayerController {
|
||||
* @see forge.game.player.PlayerController#mayPlaySpellAbilityForFree(forge.card.spellability.SpellAbility)
|
||||
*/
|
||||
@Override
|
||||
public void mayPlaySpellAbilityForFree(SpellAbility copySA) {
|
||||
public void playSpellAbilityForFree(SpellAbility copySA) {
|
||||
game.getActionPlay().playSpellAbilityForFree(copySA);
|
||||
}
|
||||
|
||||
|
||||
@@ -119,12 +119,18 @@ public final class SOverlayUtils {
|
||||
return overlay;
|
||||
}
|
||||
|
||||
private static boolean _overlayHasFocus;
|
||||
public static boolean overlayHasFocus() {
|
||||
return _overlayHasFocus;
|
||||
}
|
||||
|
||||
private static Component prevFocusOwner;
|
||||
public static void showOverlay() {
|
||||
prevFocusOwner = FocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner();
|
||||
FOverlay.SINGLETON_INSTANCE.getPanel().setVisible(true);
|
||||
// ensure no background element has focus
|
||||
FOverlay.SINGLETON_INSTANCE.getPanel().requestFocusInWindow();
|
||||
_overlayHasFocus = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,6 +143,7 @@ public final class SOverlayUtils {
|
||||
prevFocusOwner.requestFocusInWindow();
|
||||
prevFocusOwner = null;
|
||||
}
|
||||
_overlayHasFocus = false;
|
||||
}
|
||||
|
||||
public static void showTargetingOverlay() {
|
||||
|
||||
@@ -19,6 +19,7 @@ package forge.view;
|
||||
|
||||
import javax.swing.JButton;
|
||||
|
||||
import forge.gui.SOverlayUtils;
|
||||
import forge.gui.match.VMatchUI;
|
||||
|
||||
/**
|
||||
@@ -58,8 +59,12 @@ public class ButtonUtil {
|
||||
|
||||
private static void enableAndFocus(final JButton button) {
|
||||
button.setEnabled(true);
|
||||
|
||||
// ensure we don't steal focus from an overlay
|
||||
if (!SOverlayUtils.overlayHasFocus()) {
|
||||
button.requestFocusInWindow();
|
||||
}
|
||||
}
|
||||
|
||||
private static JButton getOk() {
|
||||
return VMatchUI.SINGLETON_INSTANCE.getBtnOK();
|
||||
|
||||
@@ -570,8 +570,17 @@ public abstract class CardPanelContainer extends JPanel {
|
||||
public final Card getHoveredCard(MouseEvent e) {
|
||||
// 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
|
||||
// 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());
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user