mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 20:58:03 +00:00
merge latest trunk
This commit is contained in:
274
CHANGES.txt
274
CHANGES.txt
@@ -1,7 +1,7 @@
|
|||||||
Forge Beta: 0#-##-2013 ver 1.3.9
|
Forge Beta: 03-01-2013 ver 1.3.9
|
||||||
|
|
||||||
|
|
||||||
12### cards in total.
|
12193 cards in total.
|
||||||
|
|
||||||
|
|
||||||
Release Notes:
|
Release Notes:
|
||||||
@@ -23,7 +23,7 @@ Work was also done on making the UI more keyboard-friendly. For example, the OK
|
|||||||
Gatecrash Guild Sealed game mode has been added. To use it, start a new Sealed Mode Game, select "Block / Set" and "Gatecrash Guild Sealed". Select the first (default) configuration in the "Choose Set Combination" dialog, and when asked to pick your boosters, choose the guild you want twice (once for the guild-specific booster, and then for the extra promo cards).
|
Gatecrash Guild Sealed game mode has been added. To use it, start a new Sealed Mode Game, select "Block / Set" and "Gatecrash Guild Sealed". Select the first (default) configuration in the "Choose Set Combination" dialog, and when asked to pick your boosters, choose the guild you want twice (once for the guild-specific booster, and then for the extra promo cards).
|
||||||
The following cards are not included in the guild boosters of this game mode because they are not currently implemented in Forge: Bane Alley Broker, Bioshift, Killing Glare, Simic Manipulator.
|
The following cards are not included in the guild boosters of this game mode because they are not currently implemented in Forge: Bane Alley Broker, Bioshift, Killing Glare, Simic Manipulator.
|
||||||
|
|
||||||
All Traditional sets are now up to 85% complete. Standard Format is supported at 99.19%. We are now at under 900 unsupported cards that are missing from Forge.
|
All Traditional sets are now up to 85% complete. Standard Format is supported at 99.19%. We are now at under 800 unsupported cards that are missing from Forge.
|
||||||
|
|
||||||
A person reported "Love the game but I seem to be having a problem using a draft pool to start a quest. It works for sealed for me but when I select the draft deck option it's always blank even if I have one or several drafts completed." This should now be fixed and draft decks should now show up in quest start combobox.
|
A person reported "Love the game but I seem to be having a problem using a draft pool to start a quest. It works for sealed for me but when I select the draft deck option it's always blank even if I have one or several drafts completed." This should now be fixed and draft decks should now show up in quest start combobox.
|
||||||
|
|
||||||
@@ -34,151 +34,155 @@ Our snapshot and beta releases should now display the correct SVN revision numbe
|
|||||||
|
|
||||||
New Cards:
|
New Cards:
|
||||||
|
|
||||||
Ghosts of the Innocent
|
Archery Training
|
||||||
Pendrell Flux
|
Aurelia's Fury
|
||||||
Disruption Aura
|
|
||||||
Library of Leng
|
|
||||||
Temporal Extortion
|
|
||||||
Aven Shrine
|
Aven Shrine
|
||||||
|
Barrin's Spite
|
||||||
|
Battletide Alchemist
|
||||||
|
Bioshift
|
||||||
|
Blind Seer
|
||||||
|
Blinding Powder
|
||||||
Bloom Tender
|
Bloom Tender
|
||||||
Bomb Squad
|
Bomb Squad
|
||||||
|
Bounty of the Hunt
|
||||||
|
Builder's Bane
|
||||||
Cabal Shrine
|
Cabal Shrine
|
||||||
|
Cannibalize
|
||||||
|
Cephalid Shrine
|
||||||
Chant of Vitu-Ghazi
|
Chant of Vitu-Ghazi
|
||||||
|
Chaoslace
|
||||||
|
Charm Peddler
|
||||||
|
Circle of Despair
|
||||||
|
Cleansing Meditation
|
||||||
|
Common Cause
|
||||||
|
Conflagrate
|
||||||
|
Conjurer's Ban
|
||||||
|
Cornered Market
|
||||||
Covenant of Minds
|
Covenant of Minds
|
||||||
Crashing Boars
|
Crashing Boars
|
||||||
Crush Underfoot
|
Crush Underfoot
|
||||||
|
Cryptic Gateway
|
||||||
|
Deathlace
|
||||||
|
Deepwood Elder
|
||||||
Desecrator Hag
|
Desecrator Hag
|
||||||
|
Disruption Aura
|
||||||
|
Duplicity
|
||||||
Dwarven Shrine
|
Dwarven Shrine
|
||||||
|
Eight-and-a-Half-Tails
|
||||||
|
Embolden
|
||||||
|
Endemic Plague
|
||||||
|
Epochrasite
|
||||||
|
Ersatz Gnomes
|
||||||
Eye for an Eye
|
Eye for an Eye
|
||||||
|
Eye of Singularity
|
||||||
|
Eye of Yawgmoth
|
||||||
|
Feint
|
||||||
|
Fiery Bombardment
|
||||||
|
Fiery Justice
|
||||||
|
Fire and Brimstone
|
||||||
|
Fire Covenant
|
||||||
|
Flash
|
||||||
|
Flickerform
|
||||||
|
Forbidden Crypt
|
||||||
|
Forked Lightning
|
||||||
|
Frostwielder
|
||||||
|
Game Preserve
|
||||||
|
Gargantuan Gorilla
|
||||||
|
Ghosts of the Innocent
|
||||||
|
Glamer Spinners
|
||||||
|
Guard Dogs
|
||||||
|
Hail of Arrows
|
||||||
|
Heartseeker
|
||||||
|
Heroic Defiance
|
||||||
Hint of Insanity
|
Hint of Insanity
|
||||||
Holistic Wisdom
|
Holistic Wisdom
|
||||||
Infectious Rage
|
Infectious Rage
|
||||||
Knowledge Exploitation
|
Infernal Harvest
|
||||||
Lightning Dart
|
Invoke Prejudice
|
||||||
Memory Crystal
|
Jaded Response
|
||||||
Mist of Stagnation
|
|
||||||
Moonring Mirror
|
|
||||||
Nantuko Shrine
|
|
||||||
Phyrexian Purge
|
|
||||||
Planeswalker's Mischief
|
|
||||||
Protean Hulk
|
|
||||||
Purgatory
|
|
||||||
Quenchable Fire
|
|
||||||
Retribution
|
|
||||||
Reviving Vapors
|
|
||||||
Reweave
|
|
||||||
Sapphire Drake
|
|
||||||
Searing Rays
|
|
||||||
Sphinx Ambassador
|
|
||||||
Talara's Bane
|
|
||||||
Thelon of Havenwood
|
|
||||||
Mist of Stagnation
|
|
||||||
Unforge
|
|
||||||
Warren Weirding
|
|
||||||
Worldpurge
|
|
||||||
Flash
|
|
||||||
Forked Lightning
|
|
||||||
Embolden
|
|
||||||
Jaws of Stone
|
Jaws of Stone
|
||||||
|
Killing Glare
|
||||||
|
Knollspine Invocation
|
||||||
|
Knowledge Exploitation
|
||||||
|
Kumano's Blessing
|
||||||
|
Kumano's Pupils
|
||||||
|
Kumano, Master Yamabushi
|
||||||
|
Leonin Bola
|
||||||
|
Library of Leng
|
||||||
|
Lifelace
|
||||||
|
Light from Within
|
||||||
|
Lightning Dart
|
||||||
Living Inferno
|
Living Inferno
|
||||||
Magmatic Core
|
Magmatic Core
|
||||||
Remedy
|
|
||||||
Rolling Thunder
|
|
||||||
Aurelia's Fury
|
|
||||||
Pollen Remedy
|
|
||||||
Conflagrate
|
|
||||||
Hail of Arrows
|
|
||||||
Fire Covenant
|
|
||||||
Meteor Shower
|
|
||||||
Infernal Harvest
|
|
||||||
Rock Slide
|
|
||||||
Serra's Hymn
|
|
||||||
Volcanic Wind
|
|
||||||
Spoils of War
|
|
||||||
Fiery Justice
|
|
||||||
Bounty of the Hunt
|
|
||||||
Shambling Swarm
|
|
||||||
Fire and Brimstone
|
|
||||||
Marble Priest
|
|
||||||
Talruum Piper
|
|
||||||
Endemic Plague
|
|
||||||
Feint
|
|
||||||
Reincarnation
|
|
||||||
Killing Glare
|
|
||||||
Gargantuan Gorilla
|
|
||||||
Psychic Allergy
|
|
||||||
Invoke Prejudice
|
|
||||||
Conjurer's Ban
|
|
||||||
Cephalid Shrine
|
|
||||||
Bioshift
|
|
||||||
Glamer Spinners
|
|
||||||
Mark of Eviction
|
|
||||||
Plague Boiler
|
|
||||||
Razia's Purification
|
|
||||||
Reins of the Vinesteed
|
|
||||||
Shared Animosity
|
|
||||||
Simic Guildmage
|
|
||||||
Rite of Ruin
|
|
||||||
Common Cause
|
|
||||||
Sabertooth Cobra
|
|
||||||
Archery Training
|
|
||||||
Barrin's Spite
|
|
||||||
Cryptic Gateway
|
|
||||||
Deepwood Elder
|
|
||||||
Knollspine Invocation
|
|
||||||
Eye of Yawgmoth
|
|
||||||
Spike Cannibal
|
|
||||||
Flickerform
|
|
||||||
Epochrasite
|
|
||||||
Eye of Singularity
|
|
||||||
Heroic Defiance
|
|
||||||
Forbidden Crypt
|
|
||||||
Charm Peddler
|
|
||||||
Heartseeker
|
|
||||||
Blinding Powder
|
|
||||||
Leonin Bola
|
|
||||||
Razor Boomerang
|
|
||||||
Surestrike Trident
|
|
||||||
Sunforger
|
|
||||||
Circle of Despair
|
|
||||||
Martyr's Cause
|
|
||||||
Cannibalize
|
|
||||||
Shuriken
|
|
||||||
Rally the Horde
|
|
||||||
Deathlace
|
|
||||||
Mana Vapors
|
Mana Vapors
|
||||||
Samite Elder
|
Marble Priest
|
||||||
Struggle for Sanity
|
Mark of Eviction
|
||||||
Takeno, Samurai General
|
Martyr's Cause
|
||||||
Thran Tome
|
Memory Crystal
|
||||||
Chaoslace
|
Meteor Shower
|
||||||
Lifelace
|
|
||||||
Moonlace
|
|
||||||
Purelace
|
|
||||||
Thoughtlace
|
|
||||||
Eight-and-a-Half-Tails
|
|
||||||
Pious Kitsune
|
|
||||||
Blind Seer
|
|
||||||
Ersatz Gnomes
|
|
||||||
Vodalian Mystic
|
|
||||||
Light from Within
|
|
||||||
Fiery Bombardment
|
|
||||||
Phosphorescent Feast
|
|
||||||
Guard Dogs
|
|
||||||
Jaded Response
|
|
||||||
Tainted Pact
|
|
||||||
Pledge of Loyalty
|
|
||||||
Mirror Golem
|
Mirror Golem
|
||||||
Reverent Mantra
|
Mist of Stagnation
|
||||||
Frostwielder
|
Mist of Stagnation
|
||||||
Kumano, Master Yamabushi
|
Moonlace
|
||||||
Kumano's Pupils
|
Moonring Mirror
|
||||||
Kumano's Blessing
|
Nantuko Shrine
|
||||||
Winnow
|
|
||||||
Cornered Market
|
|
||||||
Not of This World
|
Not of This World
|
||||||
Duplicity
|
Pendrell Flux
|
||||||
|
Phosphorescent Feast
|
||||||
|
Phyrexian Purge
|
||||||
|
Pious Kitsune
|
||||||
|
Plague Boiler
|
||||||
|
Planeswalker's Mischief
|
||||||
|
Pledge of Loyalty
|
||||||
|
Pollen Remedy
|
||||||
|
Protean Hulk
|
||||||
|
Psychic Allergy
|
||||||
|
Purelace
|
||||||
|
Purgatory
|
||||||
|
Quenchable Fire
|
||||||
|
Rally the Horde
|
||||||
|
Razia's Purification
|
||||||
|
Razor Boomerang
|
||||||
|
Reincarnation
|
||||||
|
Reins of the Vinesteed
|
||||||
|
Remedy
|
||||||
|
Retribution
|
||||||
|
Reverent Mantra
|
||||||
|
Reviving Vapors
|
||||||
|
Reweave
|
||||||
|
Rite of Ruin
|
||||||
|
Rock Slide
|
||||||
|
Rolling Thunder
|
||||||
|
Sabertooth Cobra
|
||||||
|
Samite Elder
|
||||||
|
Sapphire Drake
|
||||||
|
Searing Rays
|
||||||
|
Serra's Hymn
|
||||||
|
Shambling Swarm
|
||||||
|
Shared Animosity
|
||||||
|
Shuriken
|
||||||
|
Simic Guildmage
|
||||||
|
Sphinx Ambassador
|
||||||
|
Spike Cannibal
|
||||||
|
Spoils of War
|
||||||
|
Struggle for Sanity
|
||||||
|
Sunforger
|
||||||
|
Surestrike Trident
|
||||||
|
Tainted Pact
|
||||||
|
Takeno, Samurai General
|
||||||
|
Talara's Bane
|
||||||
|
Talruum Piper
|
||||||
|
Temporal Extortion
|
||||||
|
Thelon of Havenwood
|
||||||
Thought Gorger
|
Thought Gorger
|
||||||
|
Thoughtlace
|
||||||
|
Thran Tome
|
||||||
|
Unforge
|
||||||
|
Vodalian Mystic
|
||||||
|
Volcanic Wind
|
||||||
|
Warren Weirding
|
||||||
|
Winnow
|
||||||
|
Worldpurge
|
||||||
|
|
||||||
|
|
||||||
New Phenomenons:
|
New Phenomenons:
|
||||||
@@ -189,23 +193,25 @@ Planewide Disaster
|
|||||||
|
|
||||||
New Planes:
|
New Planes:
|
||||||
|
|
||||||
Undercity Reaches
|
|
||||||
Aretopolis
|
Aretopolis
|
||||||
|
Undercity Reaches
|
||||||
|
|
||||||
|
|
||||||
New Vanguard Avatars:
|
New Vanguard Avatars:
|
||||||
|
|
||||||
|
Arcanis the Omnipotent Avatar
|
||||||
|
Bosh, Iron Golem Avatar
|
||||||
Figure of Destiny Avatar
|
Figure of Destiny Avatar
|
||||||
|
Haakon Stromgald Scourge Avatar
|
||||||
|
Jaya Ballard Avatar
|
||||||
|
Maro Avatar
|
||||||
|
Master of the Wild Hunt Avatar
|
||||||
|
Necropotence Avatar
|
||||||
Sisters of Stone Death Avatar
|
Sisters of Stone Death Avatar
|
||||||
Stuffy Doll Avatar
|
Stuffy Doll Avatar
|
||||||
Two Headed Giant of Foriys Avatar
|
Two Headed Giant of Foriys Avatar
|
||||||
Viridian Zealot Avatar
|
|
||||||
Bosh, Iron Golem Avatar
|
|
||||||
Maro Avatar
|
|
||||||
Necropotence Avatar
|
|
||||||
Vampire Nocturnus Avatar
|
Vampire Nocturnus Avatar
|
||||||
Arcanis the Omnipotent Avatar
|
Viridian Zealot Avatar
|
||||||
Master of the Wild Hunt Avatar
|
|
||||||
|
|
||||||
|
|
||||||
Known Issues:
|
Known Issues:
|
||||||
|
|||||||
12
pom.xml
12
pom.xml
@@ -5,7 +5,7 @@
|
|||||||
<artifactId>forge</artifactId>
|
<artifactId>forge</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<name>Forge</name>
|
<name>Forge</name>
|
||||||
<version>1.3.9-SNAPSHOT</version>
|
<version>1.3.10-SNAPSHOT</version>
|
||||||
<description>
|
<description>
|
||||||
Forge lets you play the card game Magic: The Gathering against a computer opponent
|
Forge lets you play the card game Magic: The Gathering against a computer opponent
|
||||||
using all of the rules.
|
using all of the rules.
|
||||||
@@ -211,7 +211,7 @@
|
|||||||
<exportAntProperties>true</exportAntProperties>
|
<exportAntProperties>true</exportAntProperties>
|
||||||
<target>
|
<target>
|
||||||
<condition property="fullversionstring" value="${project.version}-r${forge.revision}${forge.specialStatus}" else="${project.version}-r${forge.revision}${forge.specialStatus} (mixed revisions detected; please update from the root directory)">
|
<condition property="fullversionstring" value="${project.version}-r${forge.revision}${forge.specialStatus}" else="${project.version}-r${forge.revision}${forge.specialStatus} (mixed revisions detected; please update from the root directory)">
|
||||||
<contains string="${forge.mixedRevisions}" substring="false"/>
|
<contains string="${forge.mixedRevisions}" substring="false" />
|
||||||
</condition>
|
</condition>
|
||||||
</target>
|
</target>
|
||||||
</configuration>
|
</configuration>
|
||||||
@@ -464,7 +464,7 @@
|
|||||||
</goals>
|
</goals>
|
||||||
</pluginExecutionFilter>
|
</pluginExecutionFilter>
|
||||||
<action>
|
<action>
|
||||||
<ignore/>
|
<ignore />
|
||||||
</action>
|
</action>
|
||||||
</pluginExecution>
|
</pluginExecution>
|
||||||
<pluginExecution>
|
<pluginExecution>
|
||||||
@@ -478,7 +478,7 @@
|
|||||||
</goals>
|
</goals>
|
||||||
</pluginExecutionFilter>
|
</pluginExecutionFilter>
|
||||||
<action>
|
<action>
|
||||||
<execute/>
|
<execute />
|
||||||
</action>
|
</action>
|
||||||
</pluginExecution>
|
</pluginExecution>
|
||||||
<pluginExecution>
|
<pluginExecution>
|
||||||
@@ -491,7 +491,7 @@
|
|||||||
</goals>
|
</goals>
|
||||||
</pluginExecutionFilter>
|
</pluginExecutionFilter>
|
||||||
<action>
|
<action>
|
||||||
<execute/>
|
<execute />
|
||||||
</action>
|
</action>
|
||||||
</pluginExecution>
|
</pluginExecution>
|
||||||
<pluginExecution>
|
<pluginExecution>
|
||||||
@@ -504,7 +504,7 @@
|
|||||||
</goals>
|
</goals>
|
||||||
</pluginExecutionFilter>
|
</pluginExecutionFilter>
|
||||||
<action>
|
<action>
|
||||||
<execute/>
|
<execute />
|
||||||
</action>
|
</action>
|
||||||
</pluginExecution>
|
</pluginExecution>
|
||||||
</pluginExecutions>
|
</pluginExecutions>
|
||||||
|
|||||||
@@ -186,13 +186,13 @@ while inputName != 'quit' :
|
|||||||
if text.find("When CARDNAME enters the battlefield") != -1 :
|
if text.find("When CARDNAME enters the battlefield") != -1 :
|
||||||
print "\n"+text
|
print "\n"+text
|
||||||
print "<Trigger Script Start>"
|
print "<Trigger Script Start>"
|
||||||
print 'T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.Self | Execute$ <TriggerFunc> | TriggerDescription$ '+text
|
print 'T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ <TriggerFunc> | TriggerDescription$ '+text
|
||||||
print 'SVar:<TriggerFunc>:AB$ <Added Triggered Ability HERE>'
|
print 'SVar:<TriggerFunc>:AB$ <Added Triggered Ability HERE>'
|
||||||
print "<Trigger Script End>\n"
|
print "<Trigger Script End>\n"
|
||||||
elif text.find("When CARDNAME leaves the battlefield") != -1 :
|
elif text.find("When CARDNAME leaves the battlefield") != -1 :
|
||||||
print "\n"+text
|
print "\n"+text
|
||||||
print "<Trigger Script Start>"
|
print "<Trigger Script Start>"
|
||||||
print 'T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Creature.Self | Execute$ <TriggerFunc> | TriggerDescription$ '+text
|
print 'T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Card.Self | Execute$ <TriggerFunc> | TriggerDescription$ '+text
|
||||||
print 'SVar:<TriggerFunc>:AB$ <Added Triggered Ability HERE>'
|
print 'SVar:<TriggerFunc>:AB$ <Added Triggered Ability HERE>'
|
||||||
print "<Trigger Script End>\n"
|
print "<Trigger Script End>\n"
|
||||||
elif text.find("Unleash") != -1 :
|
elif text.find("Unleash") != -1 :
|
||||||
|
|||||||
@@ -2,9 +2,12 @@ Name:Astral Slide
|
|||||||
ManaCost:2 W
|
ManaCost:2 W
|
||||||
Types:Enchantment
|
Types:Enchantment
|
||||||
T:Mode$ Cycled | ValidCard$ Card | Execute$ TrigExile | TriggerZones$ Battlefield | OptionalDecider$ You | TriggerDescription$ Whenever a player cycles a card, you may exile target creature. If you do, return the exiled card to the battlefield under its owner's control at the beginning of the next end step.
|
T:Mode$ Cycled | ValidCard$ Card | Execute$ TrigExile | TriggerZones$ Battlefield | OptionalDecider$ You | TriggerDescription$ Whenever a player cycles a card, you may exile target creature. If you do, return the exiled card to the battlefield under its owner's control at the beginning of the next end step.
|
||||||
SVar:TrigExile:AB$ ChangeZone | Cost$ 0 | ValidTgts$ Creature | TgtPrompt$ Select target creature | Origin$ Battlefield | Destination$ Exile | RememberTargets$ True | ForgetOtherTargets$ True | SubAbility$ DelTrig
|
SVar:TrigExile:AB$ ChangeZone | Cost$ 0 | ValidTgts$ Creature | TgtPrompt$ Select target creature | Origin$ Battlefield | Destination$ Exile | RememberChanged$ True | SubAbility$ DelTrigEffect
|
||||||
SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigBounce | TriggerDescription$ Return exiled creature to the battlefield.
|
SVar:DelTrigEffect:DB$ Effect | Triggers$ EOTTrig | SVars$ TrigBounce,RemoveEffect | RememberObjects$ Remembered | SubAbility$ DBCleanup | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ GE1
|
||||||
SVar:TrigBounce:AB$ ChangeZone | Cost$ 0 | Origin$ Exile | Destination$ Battlefield | Defined$ Remembered
|
SVar:EOTTrig:Mode$ Phase | Phase$ End of Turn | Execute$ TrigBounce | TriggerZones$ Command | TriggerDescription$ Return exiled creature to the battlefield.
|
||||||
|
SVar:TrigBounce:AB$ ChangeZone | Cost$ 0 | Origin$ Exile | Destination$ Battlefield | Defined$ Remembered | SubAbility$ RemoveEffect
|
||||||
|
SVar:RemoveEffect:DB$ ChangeZone | Origin$ Command | Destination$ Exile | Defined$ Self
|
||||||
|
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||||
SVar:RemAIDeck:True
|
SVar:RemAIDeck:True
|
||||||
SVar:Rarity:Uncommon
|
SVar:Rarity:Uncommon
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/astral_slide.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/astral_slide.jpg
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ Types:Creature Insect
|
|||||||
PT:0/1
|
PT:0/1
|
||||||
K:Flying
|
K:Flying
|
||||||
T:Mode$ Attacks | ValidCard$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigEffect | TriggerDescription$ When CARDNAME attacks, defending player can't cast spells this turn.
|
T:Mode$ Attacks | ValidCard$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigEffect | TriggerDescription$ When CARDNAME attacks, defending player can't cast spells this turn.
|
||||||
SVar:TrigEffect:AB$ Effect | Cost$ 0 | Name$ Xantid Swarm Effect | StaticAbilities$ CantBeCast
|
SVar:TrigEffect:AB$ Effect | Cost$ 0 | Name$ Xantid Swarm Effect | RememberObjects$ DefendingPlayer | StaticAbilities$ CantBeCast | SubAbility$ DBCleanup
|
||||||
SVar:CantBeCast:Mode$ CantBeCast | EffectZone$ Command | ValidCard$ Card | Caster$ DefendingPlayer | Description$ Defending player can't cast spells.
|
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||||
|
SVar:CantBeCast:Mode$ CantBeCast | EffectZone$ Command | ValidCard$ Card | Caster$ Player.IsRemembered | Description$ Defending player can't cast spells.
|
||||||
SVar:RemRandomDeck:True
|
SVar:RemRandomDeck:True
|
||||||
SVar:HasAttackEffect:TRUE
|
SVar:HasAttackEffect:TRUE
|
||||||
SVar:Rarity:Rare
|
SVar:Rarity:Rare
|
||||||
|
|||||||
@@ -293,3 +293,37 @@ http://www.cardforge.org/fpics/questAvatars/WereHyena.jpg
|
|||||||
http://www.cardforge.org/fpics/questAvatars/WitchDoctor.jpg
|
http://www.cardforge.org/fpics/questAvatars/WitchDoctor.jpg
|
||||||
http://www.cardforge.org/fpics/questAvatars/Yemaya.jpg
|
http://www.cardforge.org/fpics/questAvatars/Yemaya.jpg
|
||||||
http://www.cardforge.org/fpics/questAvatars/Yewa.jpg
|
http://www.cardforge.org/fpics/questAvatars/Yewa.jpg
|
||||||
|
#RAVNICA WORLD ICONS
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Agrus.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Aurelia.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Azorius-precon.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Bep.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Borborygmos.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Boros-precon.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Caprio.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Ghost%20Council.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Golgari-precon.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Gruul-precon.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Hameln.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Isperia.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Izzet-precon.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Jarad.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Kraj.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Lazav.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Lyzolda.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Momir.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Niv-Mizzet.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Orzhov-precon.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Rakdos.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Savra.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Selesnya-precon.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Simic-precon.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Sisters%20of%20Stone%20Death.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Sus Antigoon.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Szadek.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Teysa.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Token.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Tolsimir.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Trostani.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Ulasht.jpg
|
||||||
|
http://www.cardforge.org/fpics/questAvatars/Zegana.jpg
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package forge.deck;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
import forge.Card;
|
import forge.Card;
|
||||||
|
|
||||||
@@ -139,7 +140,7 @@ public class CardPool extends ItemPool<CardPrinted> {
|
|||||||
if ( cp != null)
|
if ( cp != null)
|
||||||
this.add(cp);
|
this.add(cp);
|
||||||
else
|
else
|
||||||
throw new RuntimeException(String.format("Card %s is not supported by Forge, as it's neither a known common card nor one of casual variants' card.", cardName));
|
throw new NoSuchElementException(String.format("Card %s is not supported by Forge, as it's neither a known common card nor one of casual variants' card.", cardName));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public abstract class PlayerController {
|
|||||||
*/
|
*/
|
||||||
public void passPriority() {
|
public void passPriority() {
|
||||||
PhaseHandler handler = game.getPhaseHandler();
|
PhaseHandler handler = game.getPhaseHandler();
|
||||||
// may pass only priority is has
|
|
||||||
if ( handler.getPriorityPlayer() == getPlayer() )
|
if ( handler.getPriorityPlayer() == getPlayer() )
|
||||||
game.getPhaseHandler().passPriority();
|
game.getPhaseHandler().passPriority();
|
||||||
}
|
}
|
||||||
@@ -95,5 +95,6 @@ public abstract class PlayerController {
|
|||||||
public Card chooseSingleCardForEffect(List<Card> sourceList, SpellAbility sa, String title) { return chooseSingleCardForEffect(sourceList, sa, title, false); }
|
public Card chooseSingleCardForEffect(List<Card> sourceList, SpellAbility sa, String title) { return chooseSingleCardForEffect(sourceList, sa, title, false); }
|
||||||
public abstract Card chooseSingleCardForEffect(List<Card> sourceList, SpellAbility sa, String title, boolean isOptional);
|
public abstract Card chooseSingleCardForEffect(List<Card> sourceList, SpellAbility sa, String title, boolean isOptional);
|
||||||
public abstract boolean confirmAction(SpellAbility sa, String mode, String message);
|
public abstract boolean confirmAction(SpellAbility sa, String mode, String message);
|
||||||
|
public abstract boolean getWillPlayOnFirstTurn(String message);
|
||||||
public abstract boolean confirmStaticApplication(Card hostCard, GameEntity affected, String logic, String message);
|
public abstract boolean confirmStaticApplication(Card hostCard, GameEntity affected, String logic, String message);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -198,6 +198,10 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
return brains.confirmAction(sa, mode, message);
|
return brains.confirmAction(sa, mode, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getWillPlayOnFirstTurn(String message) {
|
||||||
|
return true; // AI is brave :)
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public boolean confirmStaticApplication(Card hostCard, GameEntity affected, String logic, String message) {
|
public boolean confirmStaticApplication(Card hostCard, GameEntity affected, String logic, String message) {
|
||||||
return brains.confirmStaticApplication(hostCard, affected, logic, message);
|
return brains.confirmStaticApplication(hostCard, affected, logic, message);
|
||||||
|
|||||||
@@ -250,5 +250,14 @@ public class PlayerControllerHuman extends PlayerController {
|
|||||||
return GuiDialog.confirm(hostCard, message);
|
return GuiDialog.confirm(hostCard, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getWillPlayOnFirstTurn(String message) {
|
||||||
|
final String[] possibleValues = { "Play", "Draw" };
|
||||||
|
|
||||||
|
final Object playDraw = JOptionPane.showOptionDialog(null, message + "\n\nWould you like to play or draw?",
|
||||||
|
"Play or Draw?", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null,
|
||||||
|
possibleValues, possibleValues[0]);
|
||||||
|
|
||||||
|
return !playDraw.equals(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,6 +145,7 @@ public class QuestEventManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
targetIdx -= opponents.size();
|
targetIdx -= opponents.size();
|
||||||
|
|||||||
@@ -23,11 +23,9 @@ import java.awt.Rectangle;
|
|||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
|
|
||||||
import forge.Card;
|
import forge.Card;
|
||||||
import forge.view.arcane.util.CardPanelMouseListener;
|
import forge.view.arcane.util.CardPanelMouseListener;
|
||||||
|
|
||||||
@@ -76,6 +74,7 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
|||||||
* a {@link javax.swing.JScrollPane} object.
|
* a {@link javax.swing.JScrollPane} object.
|
||||||
* @param mirror
|
* @param mirror
|
||||||
* a boolean.
|
* a boolean.
|
||||||
|
* @param modelRef
|
||||||
*/
|
*/
|
||||||
public PlayArea(final JScrollPane scrollPane, final boolean mirror) {
|
public PlayArea(final JScrollPane scrollPane, final boolean mirror) {
|
||||||
super(scrollPane);
|
super(scrollPane);
|
||||||
@@ -196,46 +195,40 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
|||||||
this.playAreaWidth = rect.width;
|
this.playAreaWidth = rect.width;
|
||||||
this.playAreaHeight = rect.height;
|
this.playAreaHeight = rect.height;
|
||||||
|
|
||||||
final CardStackRow allLands = collectAllLands();
|
final CardStackRow lands = collectAllLands();
|
||||||
final CardStackRow allTokens = collectAllTokens();
|
final CardStackRow tokens = collectAllTokens();
|
||||||
final CardStackRow allCreatures = new CardStackRow(this.getCardPanels(), RowType.creatureNonToken);
|
final CardStackRow creatures = new CardStackRow(this.getCardPanels(), RowType.CreatureNonToken);
|
||||||
final CardStackRow allOthers = new CardStackRow(this.getCardPanels(), RowType.other);
|
final CardStackRow others = new CardStackRow(this.getCardPanels(), RowType.Other);
|
||||||
|
|
||||||
// should find an appropriate width of card
|
// should find an appropriate width of card
|
||||||
this.cardWidth = this.getCardWidthMax();
|
|
||||||
int maxCardWidth = this.getCardWidthMax();
|
int maxCardWidth = this.getCardWidthMax();
|
||||||
|
setCardWidth(maxCardWidth);
|
||||||
int minCardWidth = this.getCardWidthMin();
|
int minCardWidth = this.getCardWidthMin();
|
||||||
int lastGoodCardWidth = minCardWidth;
|
int lastGoodCardWidth = minCardWidth;
|
||||||
int deltaCardWidth = (maxCardWidth - minCardWidth) / 2;
|
int deltaCardWidth = (maxCardWidth - minCardWidth) / 2;
|
||||||
boolean workedLastTime = false;
|
List<CardStackRow> lastTemplate = null;
|
||||||
//boolean isFirstRun = true;
|
|
||||||
|
|
||||||
while (deltaCardWidth > 0) {
|
while (deltaCardWidth > 0) {
|
||||||
final CardStackRow creatures = (CardStackRow) allCreatures.clone();
|
List<CardStackRow> template = tryArrangePilesOfWidth(lands, tokens, creatures, others);
|
||||||
final CardStackRow tokens = (CardStackRow) allTokens.clone();
|
|
||||||
final CardStackRow lands = (CardStackRow) allLands.clone();
|
|
||||||
CardStackRow others = (CardStackRow) allOthers.clone();
|
|
||||||
workedLastTime = canAdjustWidth(lands, tokens, creatures, others);
|
|
||||||
|
|
||||||
deltaCardWidth = (cardWidth - lastGoodCardWidth) / 2;
|
deltaCardWidth = (getCardWidth() - lastGoodCardWidth) / 2;
|
||||||
if (workedLastTime) {
|
if (template != null) {
|
||||||
lastGoodCardWidth = cardWidth;
|
lastTemplate = template;
|
||||||
cardWidth += deltaCardWidth;
|
lastGoodCardWidth = getCardWidth();
|
||||||
|
setCardWidth(getCardWidth() + deltaCardWidth);
|
||||||
if (lastGoodCardWidth == maxCardWidth) {
|
if (lastGoodCardWidth == maxCardWidth) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
cardWidth -= deltaCardWidth;
|
setCardWidth(getCardWidth() - deltaCardWidth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cardWidth = lastGoodCardWidth;
|
setCardWidth(lastGoodCardWidth);
|
||||||
final CardStackRow creatures = (CardStackRow) allCreatures.clone();
|
if ( null == lastTemplate )
|
||||||
final CardStackRow tokens = (CardStackRow) allTokens.clone();
|
lastTemplate = tryArrangePilesOfWidth(lands, tokens, creatures, others);
|
||||||
final CardStackRow lands = (CardStackRow) allLands.clone();
|
|
||||||
CardStackRow others = (CardStackRow) allOthers.clone();
|
|
||||||
workedLastTime = canAdjustWidth(lands, tokens, creatures, others);
|
|
||||||
|
|
||||||
|
this.rows = lastTemplate;
|
||||||
// Get size of all the rows.
|
// Get size of all the rows.
|
||||||
int x, y = PlayArea.GUTTER_Y;
|
int x, y = PlayArea.GUTTER_Y;
|
||||||
int maxRowWidth = 0;
|
int maxRowWidth = 0;
|
||||||
@@ -252,25 +245,26 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
|||||||
}
|
}
|
||||||
this.setPreferredSize(new Dimension(maxRowWidth - this.cardSpacingX, y - this.cardSpacingY));
|
this.setPreferredSize(new Dimension(maxRowWidth - this.cardSpacingX, y - this.cardSpacingY));
|
||||||
this.revalidate();
|
this.revalidate();
|
||||||
positionAllCards();
|
positionAllCards(lastTemplate);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void positionAllCards() {
|
private void positionAllCards(List<CardStackRow> template) {
|
||||||
|
|
||||||
// Position all card panels.
|
// Position all card panels.
|
||||||
int x = 0;
|
int x = 0;
|
||||||
int y = PlayArea.GUTTER_Y;
|
int y = PlayArea.GUTTER_Y;
|
||||||
|
|
||||||
for (final CardStackRow row : this.rows) {
|
for (final CardStackRow row : template) {
|
||||||
int rowBottom = 0;
|
int rowBottom = 0;
|
||||||
x = PlayArea.GUTTER_X;
|
x = PlayArea.GUTTER_X;
|
||||||
for (int stackIndex = 0, stackCount = row.size(); stackIndex < stackCount; stackIndex++) {
|
for (int stackIndex = 0, stackCount = row.size(); stackIndex < stackCount; stackIndex++) {
|
||||||
final CardStack stack = row.get(stackIndex);
|
final CardStack stack = row.get(stackIndex);
|
||||||
// Align others to the right.
|
// Align others to the right.
|
||||||
if (RowType.other.isType(stack.get(0).getGameCard())) {
|
if (RowType.Other.isGoodFor(stack.get(0).getGameCard())) {
|
||||||
x = (this.playAreaWidth - PlayArea.GUTTER_X) + this.extraCardSpacingX;
|
x = (this.playAreaWidth - PlayArea.GUTTER_X) + this.extraCardSpacingX;
|
||||||
for (int i = stackIndex, n = row.size(); i < n; i++) {
|
for (int i = stackIndex, n = row.size(); i < n; i++) {
|
||||||
x -= row.get(i).getWidth();
|
CardStack r = row.get(i);
|
||||||
|
x -= r.getWidth();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int panelIndex = 0, panelCount = stack.size(); panelIndex < panelCount; panelIndex++) {
|
for (int panelIndex = 0, panelCount = stack.size(); panelIndex < panelCount; panelIndex++) {
|
||||||
@@ -279,68 +273,62 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
|||||||
this.setComponentZOrder(panel, panelIndex);
|
this.setComponentZOrder(panel, panelIndex);
|
||||||
final int panelX = x + (stackPosition * this.stackSpacingX);
|
final int panelX = x + (stackPosition * this.stackSpacingX);
|
||||||
final int panelY = y + (stackPosition * this.stackSpacingY);
|
final int panelY = y + (stackPosition * this.stackSpacingY);
|
||||||
panel.setCardBounds(panelX, panelY, this.cardWidth, this.cardHeight);
|
panel.setCardBounds(panelX, panelY, this.getCardWidth(), this.cardHeight);
|
||||||
}
|
}
|
||||||
rowBottom = Math.max(rowBottom, y + stack.getHeight());
|
rowBottom = Math.max(rowBottom, y + stack.getHeight());
|
||||||
x += stack.getWidth();
|
x += stack.getWidth() + cardSpacingX;
|
||||||
}
|
}
|
||||||
y = rowBottom;
|
y = rowBottom;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean canAdjustWidth(final CardStackRow lands, final CardStackRow tokens, final CardStackRow creatures, CardStackRow others) {
|
private List<CardStackRow> tryArrangePilesOfWidth(final CardStackRow lands, final CardStackRow tokens, final CardStackRow creatures, CardStackRow others) {
|
||||||
this.rows.clear();
|
List<CardStackRow> template = new ArrayList<PlayArea.CardStackRow>();
|
||||||
this.cardHeight = Math.round(this.cardWidth * CardPanel.ASPECT_RATIO);
|
|
||||||
this.extraCardSpacingX = Math.round(this.cardWidth * PlayArea.EXTRA_CARD_SPACING_X);
|
|
||||||
this.cardSpacingX = (this.cardHeight - this.cardWidth) + this.extraCardSpacingX;
|
|
||||||
this.cardSpacingY = Math.round(this.cardHeight * PlayArea.CARD_SPACING_Y);
|
|
||||||
this.stackSpacingX = Math.round(this.cardWidth * PlayArea.STACK_SPACING_X);
|
|
||||||
this.stackSpacingY = Math.round(this.cardHeight * PlayArea.STACK_SPACING_Y);
|
|
||||||
|
|
||||||
int afterFirstRow;
|
int afterFirstRow;
|
||||||
|
|
||||||
|
boolean landsFit, tokensFit, creaturesFit;
|
||||||
if (this.mirror) {
|
if (this.mirror) {
|
||||||
// Wrap all creatures and lands.
|
// Wrap all creatures and lands.
|
||||||
this.wrap(lands, this.rows, -1);
|
landsFit = this.planRow(lands, template, -1);
|
||||||
afterFirstRow = this.rows.size();
|
afterFirstRow = template.size();
|
||||||
this.wrap(tokens, this.rows, afterFirstRow);
|
tokensFit = this.planRow(tokens, template, afterFirstRow);
|
||||||
this.wrap(creatures, this.rows, this.rows.size());
|
creaturesFit = this.planRow(creatures, template, template.size());
|
||||||
} else {
|
} else {
|
||||||
// Wrap all creatures and lands.
|
// Wrap all creatures and lands.
|
||||||
this.wrap(creatures, this.rows, -1);
|
creaturesFit = this.planRow(creatures, template, -1);
|
||||||
afterFirstRow = this.rows.size();
|
afterFirstRow = template.size();
|
||||||
this.wrap(tokens, this.rows, afterFirstRow);
|
tokensFit = this.planRow(tokens, template, afterFirstRow);
|
||||||
this.wrap(lands, this.rows, this.rows.size());
|
landsFit = this.planRow(lands, template, template.size());
|
||||||
}
|
}
|
||||||
// Store the current rows and others.
|
|
||||||
final List<CardStackRow> storedRows = new ArrayList<CardStackRow>(this.rows.size());
|
if ( !landsFit || !creaturesFit || !tokensFit )
|
||||||
for (final CardStackRow row : this.rows) {
|
return null;
|
||||||
try {
|
|
||||||
storedRows.add((CardStackRow) row.clone());
|
// Other cards may be stored at end of usual rows or on their own row.
|
||||||
|
int cntOthers = others.size();
|
||||||
|
|
||||||
|
// Copy the template for the case 1st approach won't work
|
||||||
|
final List<CardStackRow> templateCopy = new ArrayList<CardStackRow>(template.size());
|
||||||
|
for (final CardStackRow row : template) {
|
||||||
|
templateCopy.add((CardStackRow) row.clone());
|
||||||
}
|
}
|
||||||
catch (NullPointerException e) {
|
|
||||||
System.out.println("Null pointer exception in Row Spacing. Possibly also part of the issue.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final CardStackRow storedOthers = (CardStackRow) others.clone();
|
|
||||||
// Fill in all rows with others.
|
// Fill in all rows with others.
|
||||||
for (final CardStackRow row : this.rows) {
|
int nextOther = 0;
|
||||||
this.fillRow(others, this.rows, row);
|
for (final CardStackRow row : template) {
|
||||||
|
nextOther = this.planOthersRow(others, nextOther, template, row);
|
||||||
|
if ( nextOther == cntOthers )
|
||||||
|
return template; // everything was successfully placed
|
||||||
}
|
}
|
||||||
// Stop if everything fits, otherwise revert back to the stored
|
|
||||||
// values.
|
template = templateCopy;
|
||||||
if (creatures.isEmpty() && tokens.isEmpty() && lands.isEmpty() && others.isEmpty()) {
|
// Try to put others on their own row(s)
|
||||||
return true;
|
if ( this.planRow(others, template, afterFirstRow) )
|
||||||
}
|
return template;
|
||||||
this.rows = storedRows;
|
|
||||||
others = storedOthers;
|
|
||||||
// Try to put others on their own row(s) and fill in the rest.
|
return null; // Cannot fit everything with that width;
|
||||||
this.wrap(others, this.rows, afterFirstRow);
|
|
||||||
for (final CardStackRow row : this.rows) {
|
|
||||||
this.fillRow(others, this.rows, row);
|
|
||||||
}
|
|
||||||
// If that still doesn't fit, scale down.
|
|
||||||
return creatures.isEmpty() && tokens.isEmpty() && lands.isEmpty() && others.isEmpty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -350,69 +338,53 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
|||||||
*
|
*
|
||||||
* @param sourceRow
|
* @param sourceRow
|
||||||
* a {@link forge.view.arcane.PlayArea.CardStackRow} object.
|
* a {@link forge.view.arcane.PlayArea.CardStackRow} object.
|
||||||
* @param rows
|
* @param template
|
||||||
* a {@link java.util.List} object.
|
* a {@link java.util.List} object.
|
||||||
* @param insertIndex
|
* @param insertIndex
|
||||||
* a int.
|
* a int.
|
||||||
* @return a int.
|
* @return a int.
|
||||||
*/
|
*/
|
||||||
// private int cntRepaints = 0;
|
// Won't modify the first parameter
|
||||||
private int wrap(final CardStackRow sourceRow, final List<CardStackRow> rows, final int insertIndex) {
|
private boolean planRow(final CardStackRow sourceRow, final List<CardStackRow> template, final int insertIndex) {
|
||||||
// The cards are sure to fit (with vertical scrolling) at the minimum
|
// The cards are sure to fit (with vertical scrolling) at the minimum
|
||||||
// card width.
|
// card width.
|
||||||
final boolean allowHeightOverflow = this.cardWidth == this.getCardWidthMin();
|
final boolean isMinimalSize = this.getCardWidth() == this.getCardWidthMin();
|
||||||
|
|
||||||
// System.err.format("[%d] @ %d - Repaint playarea - %s %n", new Date().getTime(), cntRepaints++, mirror ? "MIRROR" : "DIRECT");
|
// System.err.format("[%d] @ %d - Repaint playarea - %s %n", new Date().getTime(), cntRepaints++, mirror ? "MIRROR" : "DIRECT");
|
||||||
|
|
||||||
CardStackRow currentRow = new CardStackRow();
|
CardStackRow currentRow = new CardStackRow();
|
||||||
for (int i = 0, n = sourceRow.size() - 1; i <= n; i++) {
|
for (final CardStack stack : sourceRow) {
|
||||||
final CardStack stack = sourceRow.get(i);
|
|
||||||
// If the row is not empty and this stack doesn't fit, add the row.
|
|
||||||
final int rowWidth = currentRow.getWidth();
|
final int rowWidth = currentRow.getWidth();
|
||||||
if (!currentRow.isEmpty() && ((rowWidth + stack.getWidth()) > this.playAreaWidth)) {
|
// If the row is not empty and this stack doesn't fit, add the row.
|
||||||
|
if (rowWidth + stack.getWidth() > this.playAreaWidth && !currentRow.isEmpty() ) {
|
||||||
|
|
||||||
// Stop processing if the row is too wide or tall.
|
// Stop processing if the row is too wide or tall.
|
||||||
if (!allowHeightOverflow && (rowWidth > this.playAreaWidth)) {
|
if (rowWidth > this.playAreaWidth || this.getRowsHeight(template) + sourceRow.getHeight() > this.playAreaHeight) {
|
||||||
break;
|
if ( !isMinimalSize )
|
||||||
}
|
return false;
|
||||||
if (!allowHeightOverflow && ((this.getRowsHeight(rows) + sourceRow.getHeight()) > this.playAreaHeight)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
rows.add(insertIndex == -1 ? rows.size() : insertIndex, currentRow);
|
|
||||||
}
|
|
||||||
catch (ArrayIndexOutOfBoundsException e) {
|
|
||||||
System.out.println("ArrayIndex Out of Bounds when trying to add row in PlayArea. Someone fix this logic, "
|
|
||||||
+ " I believe it causes the no cards loading in issue we've noticed.");
|
|
||||||
// TODO: There's a crash here, maybe when rows == [null] and currentRow == [[Plant Wall]] and insertIndex is 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( insertIndex == -1)
|
||||||
|
template.add(currentRow);
|
||||||
|
else
|
||||||
|
template.add(insertIndex, currentRow);
|
||||||
|
|
||||||
currentRow = new CardStackRow();
|
currentRow = new CardStackRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
currentRow.add(stack);
|
currentRow.add(stack);
|
||||||
}
|
}
|
||||||
// Add the last row if it is not empty and it fits.
|
// Add the last row if it is not empty and it fits.
|
||||||
if (!currentRow.isEmpty()) {
|
if (!currentRow.isEmpty()) {
|
||||||
final int rowWidth = currentRow.getWidth();
|
final int rowWidth = currentRow.getWidth();
|
||||||
if (allowHeightOverflow
|
if (isMinimalSize || rowWidth <= this.playAreaWidth && this.getRowsHeight(template) + sourceRow.getHeight() <= this.playAreaHeight) {
|
||||||
|| (rowWidth <= this.playAreaWidth)
|
if ( insertIndex == -1)
|
||||||
&& (allowHeightOverflow || ((this.getRowsHeight(rows) + sourceRow.getHeight()) <= this.playAreaHeight))) {
|
template.add(currentRow);
|
||||||
try {
|
else
|
||||||
rows.add(insertIndex == -1 ? rows.size() : insertIndex, currentRow);
|
template.add(insertIndex, currentRow);
|
||||||
|
} else return false;
|
||||||
}
|
}
|
||||||
catch (ArrayIndexOutOfBoundsException e) {
|
return true;
|
||||||
System.out.println("ArrayIndex Out of Bounds when trying to add row in PlayArea. Someone fix this logic, "
|
|
||||||
+ " I believe it causes the no cards loading in issue we've noticed.");
|
|
||||||
// TODO: There's a crash here, maybe when rows == [null] and currentRow == [[Plant Wall]] and insertIndex is 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Remove the wrapped stacks from the source row.
|
|
||||||
for (int iRow = 0; iRow < rows.size(); iRow++) {
|
|
||||||
CardStackRow row = rows.get(iRow);
|
|
||||||
if (row != null) {
|
|
||||||
sourceRow.removeAll(row);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return insertIndex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -423,32 +395,30 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
|||||||
*
|
*
|
||||||
* @param sourceRow
|
* @param sourceRow
|
||||||
* a {@link forge.view.arcane.PlayArea.CardStackRow} object.
|
* a {@link forge.view.arcane.PlayArea.CardStackRow} object.
|
||||||
* @param rows
|
* @param template
|
||||||
* a {@link java.util.List} object.
|
* a {@link java.util.List} object.
|
||||||
* @param rows
|
* @param template
|
||||||
* a {@link java.util.List} object.
|
* a {@link java.util.List} object.
|
||||||
* @param row
|
* @param rowToFill
|
||||||
* a {@link forge.view.arcane.PlayArea.CardStackRow} object.
|
* a {@link forge.view.arcane.PlayArea.CardStackRow} object.
|
||||||
*/
|
*/
|
||||||
private void fillRow(final CardStackRow sourceRow, final List<CardStackRow> rows, final CardStackRow row) {
|
private int planOthersRow(final List<CardStack> sourceRow, final int firstPile, final List<CardStackRow> template, final CardStackRow rowToFill) {
|
||||||
int rowWidth = row.getWidth();
|
int rowWidth = rowToFill.getWidth();
|
||||||
|
|
||||||
final Iterator<CardStack> itr = sourceRow.iterator();
|
for (int i = firstPile; i < sourceRow.size(); i++ ) {
|
||||||
|
CardStack stack = sourceRow.get(i);
|
||||||
while (itr.hasNext()) {
|
|
||||||
final CardStack stack = itr.next();
|
|
||||||
|
|
||||||
rowWidth += stack.getWidth();
|
rowWidth += stack.getWidth();
|
||||||
if (rowWidth > this.playAreaWidth) {
|
if (rowWidth > this.playAreaWidth) return i; // cannot add any more piles in a row
|
||||||
break;
|
|
||||||
|
if (stack.getHeight() > rowToFill.getHeight()) { // if row becomes taller
|
||||||
|
int newAllRowsHeight = this.getRowsHeight(template) - rowToFill.getHeight() + stack.getHeight();
|
||||||
|
if ( newAllRowsHeight > this.playAreaHeight)
|
||||||
|
return i; // refuse to add here because it won't fit in height
|
||||||
}
|
}
|
||||||
if (stack.getHeight() > row.getHeight()
|
rowToFill.add(stack);
|
||||||
&& (((this.getRowsHeight(rows) - row.getHeight()) + stack.getHeight()) > this.playAreaHeight)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
row.add(stack);
|
|
||||||
itr.remove();
|
|
||||||
}
|
}
|
||||||
|
return sourceRow.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -509,20 +479,18 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static enum RowType {
|
private static enum RowType {
|
||||||
land, creature, creatureNonToken, other;
|
Land,
|
||||||
|
Creature,
|
||||||
|
CreatureNonToken,
|
||||||
|
Other;
|
||||||
|
|
||||||
public boolean isType(final Card card) {
|
public boolean isGoodFor(final Card card) {
|
||||||
switch (this) {
|
switch (this) {
|
||||||
case land:
|
case Land: return card.isLand();
|
||||||
return card.isLand();
|
case Creature: return card.isCreature();
|
||||||
case creature:
|
case CreatureNonToken: return card.isCreature() && !card.isToken();
|
||||||
return card.isCreature();
|
case Other: return !card.isLand() && !card.isCreature();
|
||||||
case creatureNonToken:
|
default: throw new RuntimeException("Unhandled type: " + this);
|
||||||
return card.isCreature() && !card.isToken();
|
|
||||||
case other:
|
|
||||||
return !card.isLand() && !card.isCreature();
|
|
||||||
default:
|
|
||||||
throw new RuntimeException("Unhandled type: " + this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -541,7 +509,7 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
|||||||
|
|
||||||
private void addAll(final List<CardPanel> cardPanels, final RowType type) {
|
private void addAll(final List<CardPanel> cardPanels, final RowType type) {
|
||||||
for (final CardPanel panel : cardPanels) {
|
for (final CardPanel panel : cardPanels) {
|
||||||
if (!type.isType(panel.getGameCard()) || (panel.getAttachedToPanel() != null)) {
|
if (!type.isGoodFor(panel.getGameCard()) || (panel.getAttachedToPanel() != null)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final CardStack stack = new CardStack();
|
final CardStack stack = new CardStack();
|
||||||
@@ -606,4 +574,17 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
|||||||
+ PlayArea.this.cardSpacingY;
|
+ PlayArea.this.cardSpacingY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private int getCardWidth() {
|
||||||
|
return cardWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setCardWidth(int cardWidth0) {
|
||||||
|
this.cardWidth = cardWidth0;
|
||||||
|
this.cardHeight = Math.round(this.cardWidth * CardPanel.ASPECT_RATIO);
|
||||||
|
this.extraCardSpacingX = Math.round(this.cardWidth * PlayArea.EXTRA_CARD_SPACING_X);
|
||||||
|
this.cardSpacingX = (this.cardHeight - this.cardWidth) + this.extraCardSpacingX;
|
||||||
|
this.cardSpacingY = Math.round(this.cardHeight * PlayArea.CARD_SPACING_Y);
|
||||||
|
this.stackSpacingX = Math.round(this.cardWidth * PlayArea.STACK_SPACING_X);
|
||||||
|
this.stackSpacingY = Math.round(this.cardHeight * PlayArea.STACK_SPACING_Y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user