Added TSR and HA4 sets, added/fixed primitives, improved Android downloader, fixed a crash when AI pays a Convoke alternative cost, fixed a random crash on Windows when opening zip files, fixed a random crash in destroy ability method (e.g. blasphemous act).

This commit is contained in:
Vittorio Alfieri
2021-03-09 19:07:31 +01:00
parent 2abb218164
commit 37ce334688
8 changed files with 2470 additions and 58 deletions

View File

@@ -1746,6 +1746,18 @@ public class ImgDownloader {
cardurl = "https://img.scryfall.com/cards/large/front/5/d/5dca90ef-1c17-4dcc-9fef-dab9ee92f590.jpg?1572490726";
else if(id.equals("473127t"))
cardurl = "https://img.scryfall.com/cards/large/front/9/4/94057dc6-e589-4a29-9bda-90f5bece96c4.jpg?1572489125";
else if(id.equals("295910t"))
cardurl = "https://c1.scryfall.com/file/scryfall-cards/large/front/7/b/7b993828-e139-4cb6-a329-487accc1c515.jpg?1563073064";
else if(id.equals("296315t"))
cardurl = "https://c1.scryfall.com/file/scryfall-cards/large/front/e/d/ed58cd8c-b11a-4109-b789-0eb92eaf0184.jpg?1614969127";
else if(id.equals("296247t"))
cardurl = "https://c1.scryfall.com/file/scryfall-cards/large/front/0/7/07027a7c-5843-4d78-9b86-8799363c0b82.jpg?1591319174";
else if(id.equals("296217t"))
cardurl = "https://c1.scryfall.com/file/scryfall-cards/large/front/e/7/e72daa68-0680-431c-a616-b3693fd58813.jpg?1614969153";
else if(id.equals("296145t"))
cardurl = "https://c1.scryfall.com/file/scryfall-cards/large/front/c/b/cbcb0668-e88c-4462-b079-34f140c0277e.jpg?1614969101";
else if(id.equals("295986t"))
cardurl = "https://c1.scryfall.com/file/scryfall-cards/large/front/4/a/4a2144f2-d4be-419e-bfca-116cedfdf18b.jpg?1614968857";
return cardurl;
}
@@ -2185,7 +2197,7 @@ public class ImgDownloader {
tokenurl = "https://img.scryfall.com/cards/large/front/4/f/4f8107b3-8539-4b9c-8d0d-c512c940838f.jpg?1592324480";
else if(id.equals("489403t") || id.equals("489358t") || id.equals("489372t"))
tokenurl = "https://img.scryfall.com/cards/large/front/9/5/959ed4bf-b276-45ed-b44d-c757e9c25846.jpg";
else if(id.equals("489562t"))
else if(id.equals("489562t") || id.equals("296282t"))
tokenurl="https://img.scryfall.com/cards/large/front/c/f/cf9a289f-cd3f-42a0-9296-8c7cc7d01a91.jpg?1561758108";
else if(id.equals("489363t"))
tokenurl="https://img.scryfall.com/cards/large/front/8/3/83dcacd3-8707-4354-a1a5-9863d677d67f.jpg?1562702177";
@@ -2240,6 +2252,8 @@ public class ImgDownloader {
else if(id.equals("508147t") || id.equals("508338t") || id.equals("508160t") || id.equals("508357t") ||
id.equals("508354t") || id.equals("508349t") || id.equals("508343t"))
tokenurl = "https://c1.scryfall.com/file/scryfall-cards/large/front/1/1/118d0655-5719-4512-8bc1-fe759669811b.jpg?1611206824";
else if(id.equals("295919t"))
tokenurl = "https://c1.scryfall.com/file/scryfall-cards/large/front/1/1/118d0655-5719-4512-8bc1-fe759669811b.jpg?1611206824";
return tokenurl;
}
@@ -2851,7 +2865,7 @@ public class ImgDownloader {
|| scryset.equals("PAL05") || scryset.equals("PAL06") || scryset.equals("PAL99") || scryset.equals("PARL") || scryset.equals("HA1")
|| scryset.equals("SLD") || scryset.equals("MB1") || scryset.equals("HA2") || scryset.equals("HA3") || scryset.equals("SS3")
|| scryset.equals("AKR") || scryset.equals("ANB") || scryset.equals("PLIST") || scryset.equals("KLR") || scryset.equals("CC1")
|| scryset.equals("ATH")){
|| scryset.equals("ATH") || scryset.equals("HA4") || scryset.equals("TSR")){
try {
doc = Jsoup.connect(imageurl + scryset.toLowerCase()).get();
Elements outlinks = doc.select("body a");
@@ -3042,7 +3056,7 @@ public class ImgDownloader {
&& !scryset.equals("PAL05") && !scryset.equals("PAL06") && !scryset.equals("PAL99") && !scryset.equals("PARL") && !scryset.equals("HA1")
&& !scryset.equals("SLD") && !scryset.equals("MB1") && !scryset.equals("HA2") && !scryset.equals("HA3") && !scryset.equals("SS3")
&& !scryset.equals("AKR") && !scryset.equals("ANB") && !scryset.equals("PLIST") && !scryset.equals("KLR") && !scryset.equals("CC1")
&& !scryset.equals("ATH")){
&& !scryset.equals("ATH") && !scryset.equals("HA4") && !scryset.equals("TSR")){
try {
doc = Jsoup.connect(imageurl + scryset.toLowerCase()).get();
Elements outlinks = doc.select("body a");
@@ -3157,7 +3171,7 @@ public class ImgDownloader {
&& !scryset.equals("PAL05") && !scryset.equals("PAL06") && !scryset.equals("PAL99") && !scryset.equals("PARL") && !scryset.equals("HA1")
&& !scryset.equals("SLD") && !scryset.equals("MB1") && !scryset.equals("HA2") && !scryset.equals("HA3") && !scryset.equals("SS3")
&& !scryset.equals("AKR") && !scryset.equals("ANB") && !scryset.equals("PLIST") && !scryset.equals("KLR") && !scryset.equals("CC1")
&& !scryset.equals("ATH")){
&& !scryset.equals("ATH") && !scryset.equals("HA4") && !scryset.equals("TSR")){
try {
doc = Jsoup.connect(imageurl + scryset.toLowerCase()).get();
} catch (Exception e) {
@@ -3323,7 +3337,8 @@ public class ImgDownloader {
|| scryset.equals("PAL01") || scryset.equals("PAL02") || scryset.equals("PAL03") || scryset.equals("PAL04") || scryset.equals("PAL05")
|| scryset.equals("PAL06") || scryset.equals("PAL99") || scryset.equals("PARL") || scryset.equals("HA1") || scryset.equals("SLD")
|| scryset.equals("MB1") || scryset.equals("HA2") || scryset.equals("HA3") || scryset.equals("SS3") || scryset.equals("AKR")
|| scryset.equals("ANB") || scryset.equals("PLIST") || scryset.equals("KLR") || scryset.equals("CC1") || scryset.equals("ATH")){
|| scryset.equals("ANB") || scryset.equals("PLIST") || scryset.equals("KLR") || scryset.equals("CC1") || scryset.equals("ATH")
|| scryset.equals("HA4") || scryset.equals("TSR")){
Elements metadata = doc.select("head meta");
if(metadata != null) {
for (int j = 0; j < metadata.size(); j++){

View File

@@ -0,0 +1,157 @@
[meta]
author=Wagic Team
name=Historic Anthology 4
orderindex=PRO-ZA.HA4
year=2021-03-11
total=30
[/meta]
[card]
primitive=Wolf
id=-295928
rarity=T
[/card]
[card]
primitive=Spider
id=-295921
rarity=T
[/card]
[card]
primitive=Beast
id=-295920
rarity=T
[/card]
[card]
primitive=Warrior
id=-295919
rarity=T
[/card]
[card]
primitive=Avatar
id=-295910
rarity=T
[/card]
[card]
primitive=Adorned Pouncer
id=295905
rarity=R
[/card]
[card]
primitive=Declaration in Stone
id=295906
rarity=R
[/card]
[card]
primitive=Thraben Inspector
id=295907
rarity=C
[/card]
[card]
primitive=Triumphant Reckoning
id=295908
rarity=M
[/card]
[card]
primitive=Iceberg Cancrix
id=295909
rarity=C
[/card]
[card]
primitive=Marit Lage's Slumber
id=295910
rarity=R
[/card]
[card]
primitive=Think Twice
id=295911
rarity=C
[/card]
[card]
primitive=Ammit Eternal
id=295912
rarity=R
[/card]
[card]
primitive=Death's Shadow
id=295913
rarity=R
[/card]
[card]
primitive=Faith of the Devoted
id=295914
rarity=U
[/card]
[card]
primitive=Torment of Scarabs
id=295915
rarity=U
[/card]
[card]
primitive=Flameblade Adept
id=295916
rarity=U
[/card]
[card]
primitive=Goblin Gaveleer
id=295917
rarity=C
[/card]
[card]
primitive=Harmless Offering
id=295918
rarity=R
[/card]
[card]
primitive=Lys Alana Huntmaster
id=295919
rarity=C
[/card]
[card]
primitive=Sawtusk Demolisher
id=295920
rarity=R
[/card]
[card]
primitive=Spider Spawning
id=295921
rarity=U
[/card]
[card]
primitive=Hamza, Guardian of Arashin
id=295922
rarity=U
[/card]
[card]
primitive=Collected Conjuring
id=295923
rarity=R
[/card]
[card]
primitive=Abomination of Llanowar
id=295924
rarity=U
[/card]
[card]
primitive=Bonesplitter
id=295925
rarity=C
[/card]
[card]
primitive=Coldsteel Heart
id=295926
rarity=U
[/card]
[card]
primitive=Inspiring Statuary
id=295927
rarity=R
[/card]
[card]
primitive=Sword of Body and Mind
id=295928
rarity=M
[/card]
[card]
primitive=Blinkmoth Nexus
id=295929
rarity=R
[/card]

File diff suppressed because it is too large Load Diff

View File

@@ -1273,6 +1273,21 @@ power=1
toughness=1
[/card]
[card]
name=Ana Battlemage
abilities=hasotherkicker
other={2}{U} name(Kicker blue)
kicker={1}{B} name(Kicker black or both)
auto=if paid(alternative) then target(player) ability$!name(Discard 3 cards) name(Discard 3 cards) target(<3>*|myhand) reject!$ targetedplayer
auto=if paid(kicker) then ability$!name(Tap creature) name(Tap creature) target(creature[-tapped]|battlefield) transforms((,newability[tap],newability[damage:power controller])) oneshot!$ controller
auto=if paid(kicker) then pay({2}{U}) name(Pay also kicker blue) target(player) ability$!name(Discard 3 cards) name(Discard 3 cards) target(<3>*|myhand) reject!$ targetedplayer
text=Kicker {2}{U} and/or {1}{B} (You may pay an additional {2}{U} and/or {1}{B} as you cast this spell.) -- When Ana Battlemage enters the battlefield, if it was kicked with its {2}{U} kicker, target player discards three cards. -- When Ana Battlemage enters the battlefield, if it was kicked with its {1}{B} kicker, tap target untapped creature and that creature deals damage equal to its power to its controller.
mana={2}{G}
type=Creature
subtype=Human Wizard
power=2
toughness=2
[/card]
[card]
name=Anara, Wolvid Familiar
abilities=partner
auto=this(variable{controllerturn}>0) lord(*[iscommander]|mybattlefield) indestructible
@@ -1448,8 +1463,8 @@ toughness=6
[/card]
[card]
name=Angel of Grace
abilities=flash, flying
auto=this(controllerlife >= 1) transforms((,newability[reduceto:1])) ueot
abilities=flash,flying
auto=this(controllerlife >= 1) transforms((,newability[reduceto:1]))
autograveyard={4}{W}{W}{E}:lifeset:10
text=Flash -- Flying -- When Angel of Grace enters the battlefield, until end of turn, damage that would reduce your life total to less than 1 reduces it to 1 instead. -- {4}{W}{W}, Exile Angel of Grace from your graveyard: Your life total becomes 10.
mana={3}{W}{W}
@@ -1522,6 +1537,15 @@ power=4
toughness=4
[/card]
[card]
name=Angel's Grace
abilities=split second
auto=all(*|mybattlefield) transforms((,newability[this(controllerlife >= 1) transforms((,newability[reduceto:1]))],newability[cantlose])) ueot
auto=all(*|opponentbattlefield) transforms((,newability[cantwin])) ueot
text=Split second (As long as this spell is on the stack, players can't cast spells or activate abilities that aren't mana abilities.) -- You can't lose the game this turn and your opponents can't win the game this turn. Until end of turn, damage that would reduce your life total to less than 1 reduces it to 1 instead.
mana={W}
type=Instant
[/card]
[card]
name=Angel's Trumpet
auto=lord(creature) transforms((,newability[vigilance],newability[@each my end restriction{didntattack}:tap(noevent) && damage:1 controller]))
text=All creatures have vigilance. -- At the beginning of each player's end step, tap all untapped creatures that player controls that didn't attack this turn. Angel's Trumpet deals damage to the player equal to the number of creatures tapped this way.
@@ -4522,6 +4546,16 @@ mana={2}{G}
type=Sorcery
[/card]
[card]
name=Benediction of Moons
abilities=exiledeath
auto=life:2 controller
auto=name(Haunt a creature) target(creature) counter(0/0.1.MoonsHaunted)
autoexile=@movedto(creature[counter{0/0.1.MoonsHaunted}]|graveyard) from(battlefield):life:2 controller
text=You gain 1 life for each player. -- Haunt (When this spell card is put into a graveyard after resolving, exile it haunting target creature.) -- When the creature Benediction of Moons haunts dies, you gain 1 life for each player.
mana={W}
type=Sorcery
[/card]
[card]
name=Benefaction of Rhonas
aicode=activate transforms((,newability[if type(*[creature;enchantment;zpos<=5]|mylibrary)~equalto~0 then all(*[zpos<=5]|mylibrary) moveto(mygraveyard) else target(*[zpos<=1]|mylibrary) transforms((,newability[target(*[creature;enchantment;zpos<=5]|mylibrary) moveto(myhand) and!( all(*[zpos<=5]|mylibrary) moveto(mygraveyard) )!])) oneshot])) oneshot
auto=if type(creature[zpos<=5]|mylibrary)~morethan~0 then if type(enchantment[zpos<=5]|mylibrary)~morethan~0 then name(Look top 5 cards) name(Look top 5 cards) name(Look top 5 cards) reveal:5 optionone name(Choose creature) target(creature|reveal) moveto(mylibrary) and!( becomes(tobecast) ueot )! optiononeend optiontwo name(Choose enchantment) target(enchantment|reveal) moveto(mylibrary) and!( becomes(tobecast) ueot && all(*|reveal) moveto(mygraveyard) )! optiontwoend afterrevealed all(tobecast|mylibrary) transforms((,newability[if cantargetcard(*[creature]|*) then choice name(Put creature in hand) name(Put creature in hand) moveto(myhand)],newability[if cantargetcard(*[creature]|*) then choice name(Put creature in graveyard) name(Put creature in graveyard) donothing],newability[if cantargetcard(*[enchantment]|*) then choice name(Put enchantment in hand) name(Put enchantment in hand) moveto(myhand)],newability[if cantargetcard(*[enchantment]|*) then choice name(Put enchantment in graveyard) name(Put enchantment in graveyard) moveto(mygraveyard)])) oneshot afterrevealedend revealend
@@ -4706,6 +4740,13 @@ mana={4}{G}{G}
type=Sorcery
[/card]
[card]
name=Bioshift
auto=target(creature[counter{1/1}|battlefield) transforms((,newability[thisforeach(counter{1/1.1}) may name(Move 1/1 counter) counter(1/1.-1) all(this) && counter(1/1) target(other creature|mybattlefield)])) oneshot
text=Move any number of +1/+1 counters from target creature onto another target creature with the same controller.
mana={GU}
type=Instant
[/card]
[card]
name=Biowaste Blob
auto=lord(*[ooze]|mybattlefield) 1/1
auto=@each my upkeep restriction{type(*[iscommander]|myBattlefield)~morethan~0}:clone all(this)
@@ -46957,8 +46998,8 @@ type=Land
[card]
name=Silundi Vision
autohand={0}:restriction{can play land} name(Silundi Isle) name(Silundi Isle) flip(Silundi Isle) forcetype(land)
aicode=activate target(instant,sorcery[zpos<=6]|mylibrary) moveto(myhand)
auto=name(Reveal 6 cards) reveal:6 optionone name(Get instant or sorcery) target(instant,sorcery|reveal) moveto(myhand) optiononeend optiontwo name(put on bottom) target(<6>*|reveal) bottomoflibrary optiontwoend revealend
aicode=activate target(*[instant;sorcery;zpos<=6]|mylibrary) moveto(myhand)
auto=name(Reveal 6 cards) reveal:6 optionone name(Get instant or sorcery) target(<upto:1>*[instant;sorcery]|reveal) moveto(myhand) optiononeend optiontwo name(put on bottom) target(<6>*|reveal) bottomoflibrary optiontwoend revealend
text=Look at the top six cards of your library. You may reveal an instant or sorcery card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.
mana={2}{U}
type=Instant

View File

@@ -279,21 +279,6 @@ mana={2}
type=Artifact
[/card]
[card]
name=Ana Battlemage
text=Kicker {2}{U} and/or {1}{B} (You may pay an additional {2}{U} and/or {1}{B} as you cast this spell.) -- When Ana Battlemage enters the battlefield, if it was kicked with its {2}{U} kicker, target player discards three cards. -- When Ana Battlemage enters the battlefield, if it was kicked with its {1}{B} kicker, tap target untapped creature and that creature deals damage equal to its power to its controller.
mana={2}{G}
type=Creature
subtype=Human Wizard
power=2
toughness=2
[/card]
[card]
name=Angel's Grace
text=Split second (As long as this spell is on the stack, players can't cast spells or activate abilities that aren't mana abilities.) -- You can't lose the game this turn and your opponents can't win the game this turn. Until end of turn, damage that would reduce your life total to less than 1 reduces it to 1 instead.
mana={W}
type=Instant
[/card]
[card]
name=Animate Library
text=Enchant your library -- Enchanted library is an artifact creature on the battlefield with power and toughness each equal to the number of cards in it. It's still a library. -- If enchanted library would leave the battlefield, exile Animate Library instead.
mana={4}{U}{U}
@@ -765,13 +750,6 @@ power=3
toughness=3
[/card]
[card]
name=Barrel Down Sokenzan
text=Sweep — Return any number of Mountains you control to their owner's hand. Barrel Down Sokenzan deals damage to target creature equal to twice the number of Mountains returned this way.
mana={2}{R}
type=Instant
subtype=Arcane
[/card]
[card]
name=Barrin's Unmaking
text=Return target permanent to its owner's hand if that permanent shares a color with the most common color among all permanents or a color tied for most common.
mana={1}{U}
@@ -872,12 +850,6 @@ mana={3}{R}
type=Sorcery
[/card]
[card]
name=Benediction of Moons
text=You gain 1 life for each player. -- Haunt (When this spell card is put into a graveyard after resolving, exile it haunting target creature.) -- When the creature Benediction of Moons haunts dies, you gain 1 life for each player.
mana={W}
type=Sorcery
[/card]
[card]
name=Benevolent Unicorn
text=If a spell would deal damage to a creature or player, it deals that much damage minus 1 to that creature or player instead.
mana={1}{W}
@@ -917,12 +889,6 @@ power=4
toughness=4
[/card]
[card]
name=Bioshift
text=Move any number of +1/+1 counters from target creature onto another target creature with the same controller.
mana={GU}
type=Instant
[/card]
[card]
name=Bite of the Black Rose
text=Will of the council — Starting with you, each player votes for sickness or psychosis. If sickness gets more votes, creatures your opponents control get -2/-2 until end of turn. If psychosis gets more votes or the vote is tied, each opponent discards two cards.
mana={3}{B}

View File

@@ -3289,11 +3289,21 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * ty
ManaCost* manaToPay = card->getManaCost();
if((!pMana->canAfford(card->getManaCost(),0) || card->getManaCost()->getKicker()))
gotPayments = canPayMana(card,card->getManaCost(),card->has(Constants::ANYTYPEOFMANA));
if(card->getManaCost()->getAlternative() && !gotPayments.size() && !pMana->canAfford(card->getManaCost(),0) && !card->getManaCost()->getKicker()){ // Now AI can cast cards using alternative cost.
localpayAlternative = true;
manaToPay = card->getManaCost()->getAlternative();
if(!pMana->canAfford(manaToPay,0))
gotPayments = canPayMana(card,card->getManaCost()->getAlternative(),card->has(Constants::ANYTYPEOFMANA));
if(card->getManaCost()->getAlternative() && !gotPayments.size() && !pMana->canAfford(card->getManaCost(),0) && !card->getManaCost()->getKicker()){ //Now AI can cast cards using alternative cost.
ManaCost * extra = card->getManaCost()->getAlternative(); //Fix a crash when AI try to pay convoke cost.
bool hasConvoke = false;
if(extra->extraCosts){
for(unsigned int i = 0; i < extra->extraCosts->costs.size() && !hasConvoke; i++){
if(dynamic_cast<Convoke*> (extra->extraCosts->costs[i]))
hasConvoke = true;
}
}
if(!hasConvoke){
localpayAlternative = true;
manaToPay = card->getManaCost()->getAlternative();
if(!pMana->canAfford(manaToPay,0))
gotPayments = canPayMana(card,card->getManaCost()->getAlternative(),card->has(Constants::ANYTYPEOFMANA));
}
}
//for preformence reason we only look for specific mana if the payment couldn't be made with pmana.
if ((currentCost > maxCost || hasX) && (gotPayments.size() || pMana->canAfford(manaToPay,card->has(Constants::ANYTYPEOFMANA))))

View File

@@ -6060,15 +6060,13 @@ int MTGAbility::removeFromGame()
//returns 1 if this ability needs to be removed from the list of active abilities
int MTGAbility::testDestroy()
{
if (game->mLayers->stackLayer()->has(this))
if(waitingForAnswer)
return 0;
if (waitingForAnswer)
return 0;
if (forceDestroy == 1)
if(forceDestroy == 1)
return 1;
if (forceDestroy == -1)
if(forceDestroy == -1)
return 0;
if (source->handEffects && game->isInHand(source))
if(source->handEffects && game->isInHand(source))
return 0;
if(source->graveEffects && game->isInGrave(source))
return 0;
@@ -6076,11 +6074,13 @@ int MTGAbility::testDestroy()
return 0;
if(source->commandZoneEffects && game->isInCommandZone(source))
return 0;
if(this->forcedAlive == 1)
if(forcedAlive == 1)
return 0;
if (!game->isInPlay(source))
if(game->mLayers->stackLayer()->has(this)) //Moved here to avoid a random crash (e.g. blasphemous act)
return 0;
if(!game->isInPlay(source))
return 1;
if (target && !dynamic_cast<Player*>(target) && !game->isInPlay((MTGCardInstance *) target))
if(target && !dynamic_cast<Player*>(target) && !game->isInPlay((MTGCardInstance *) target))
return 1;
return 0;
}