Fix date in Dat files, Added IKO and HA3 sets, updated the manifest and build files, Added SD card support for Android, Fix the Android app crash when resuming from background, Improved Android downloader, added finger sliding popup menu for Android devices without sidebar menu, fixed several crashes during game, added the mutating card ability, fixed the adventure card ability, added new borderline primitives.

This commit is contained in:
valfieri
2020-06-10 00:10:59 +02:00
parent 275eb9e06e
commit 8645cb9e1e
48 changed files with 9268 additions and 3312 deletions

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="0221" android:installLocation="preferExternal" android:versionName="@string/app_version" package="net.wagic.app">
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="0223" android:installLocation="preferExternal" android:versionName="@string/app_version" package="net.wagic.app">
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>

View File

@@ -4,6 +4,7 @@
android:id="@+id/mainLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:keepScreenOn="true"
>
<TextView
android:layout_width="fill_parent"

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Wagic</string>
<string name="app_version">0.22.2</string>
<string name="info_text">Wagic v0.22.2\\nAll Rights Reserved.</string>
<string name="app_version">0.22.3</string>
<string name="info_text">All Rights Reserved.</string>
</resources>

View File

@@ -1382,7 +1382,13 @@ public class ImgDownloader {
cardurl = "https://img.scryfall.com/cards/large/front/1/d/1dee8c94-cdc8-42b2-a393-0c0c8e439125.jpg?1586453065";
else if(id.equals("484902t") || id.equals("484904t"))
cardurl = "https://img.scryfall.com/cards/large/front/7/2/720f3e68-84c0-462e-a0d1-90236ccc494a.jpg?1562539782";
else if(id.equals("294690t"))
cardurl = "https://img.scryfall.com/cards/large/front/0/8/082c3bad-3fea-4c3f-8263-4b16139bb32a.jpg?1562701890";
else if(id.equals("47963911t"))
cardurl = "https://img.scryfall.com/cards/large/front/f/9/f918b740-1984-4090-8886-9e290a698b95.jpg?1586451994";
else if(id.equals("479634t"))
cardurl = "https://img.scryfall.com/cards/large/front/a/9/a9cc7c63-5d13-4fd6-af9d-4a26c2bab8e6.jpg?1588521003";
return cardurl;
}
@@ -1824,7 +1830,7 @@ public class ImgDownloader {
id.equals("470620") || id.equals("470754") || id.equals("470750") || id.equals("470739") || id.equals("470708") || id.equals("470581") ||
id.equals("470578") || id.equals("470571") || id.equals("470552") || id.equals("394490") || id.equals("114921") || id.equals("49775") ||
id.equals("473123") || id.equals("473160") || id.equals("16743") || id.equals("16741") || id.equals("294493") || id.equals("293253") ||
id.equals("293198") || id.equals("479634") || id.equals("479702"))
id.equals("293198") || id.equals("479634") || id.equals("479702"))
return false;
return true;
}
@@ -2071,11 +2077,6 @@ public class ImgDownloader {
ThumbY = 64;
}
if(borderless){
Border = (int)Math.round(ImgX*0.04);
BorderThumb = (int)Math.round(ThumbX*0.04);
}
File baseFolder = new File(basePath);
File[] listOfFiles = baseFolder.listFiles();
Map<String, String> mappa = new HashMap<String, String>();
@@ -2132,6 +2133,29 @@ public class ImgDownloader {
int lastIndex = lines.indexOf(findStr);
String totals = lines.substring(lastIndex, lines.indexOf("\n", lastIndex));
totalcards = Integer.parseInt(totals.split("=")[1]);
if(borderless){
findStr = "year=";
lastIndex = lines.indexOf(findStr);
String date = lines.substring(lastIndex, lines.indexOf("\n", lastIndex));
int year = Integer.parseInt(date.split("=")[1].split("-")[0]);
int month = 1;
int day = 1;
if(date.split("=")[1].split("-").length > 1) {
month = Integer.parseInt(date.split("=")[1].split("-")[1]);
if(date.split("=")[1].split("-").length > 2) {
day = Integer.parseInt(date.split("=")[1].split("-")[2]);
}
}
if(year > 2014 || (year == 2014 && month > 6) || (year == 2014 && month == 6 && day > 15)){
Border = (int)Math.round(ImgX*0.02);
BorderThumb = (int)Math.round(ThumbX*0.02);
} else {
Border = (int)Math.round(ImgX*0.04);
BorderThumb = (int)Math.round(ThumbX*0.04);
}
}
while (lines.contains("[card]")) {
findStr = "[card]";
lastIndex = lines.indexOf(findStr);
@@ -2388,7 +2412,7 @@ public class ImgDownloader {
|| scryset.equals("PMPS08") || scryset.equals("PMPS09") || scryset.equals("PMPS10") || scryset.equals("PMPS11") || scryset.equals("GN2")
|| scryset.equals("PAL00") || 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("SLD") || scryset.equals("MB1") || scryset.equals("HA2") || scryset.equals("HA3")){
try {
doc = Jsoup.connect(imageurl + scryset.toLowerCase()).get();
Elements outlinks = doc.select("body a");
@@ -2577,7 +2601,7 @@ public class ImgDownloader {
&& !scryset.equals("PMPS08") && !scryset.equals("PMPS09") && !scryset.equals("PMPS10") && !scryset.equals("PMPS11") && !scryset.equals("GN2")
&& !scryset.equals("PAL00") && !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("SLD") && !scryset.equals("MB1") && !scryset.equals("HA2") && !scryset.equals("HA3")){
try {
doc = Jsoup.connect(imageurl + scryset.toLowerCase()).get();
Elements outlinks = doc.select("body a");
@@ -2690,7 +2714,7 @@ public class ImgDownloader {
&& !scryset.equals("PMPS08") && !scryset.equals("PMPS09") && !scryset.equals("PMPS10") && !scryset.equals("PMPS11") && !scryset.equals("GN2")
&& !scryset.equals("PAL00") && !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("SLD") && !scryset.equals("MB1") && !scryset.equals("HA2") && !scryset.equals("HA3")){
try {
doc = Jsoup.connect(imageurl + scryset.toLowerCase()).get();
} catch (Exception e) {
@@ -2855,7 +2879,7 @@ public class ImgDownloader {
|| scryset.equals("PMPS09") || scryset.equals("PMPS10") || scryset.equals("PMPS11") || scryset.equals("GN2") || scryset.equals("PAL00")
|| 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("MB1") || scryset.equals("HA2") || scryset.equals("HA3")){
Elements metadata = doc.select("head meta");
if(metadata != null) {
for (int j = 0; j < metadata.size(); j++){

View File

@@ -23,7 +23,7 @@ public class StorageOptions
public static int count = 0;
public static String defaultMountPoint;
public static void determineStorageOptions()
public static void determineStorageOptions(android.content.Context mContext)
{
initializeMountPoints();
if (findForcemount()){
@@ -36,6 +36,16 @@ public class StorageOptions
}
compareMountsWithVold();
testAndCleanMountsList();
File[] externalStorageVolumes = mContext.getExternalFilesDirs("");
for(int i = 0; i < externalStorageVolumes.length; i++){
mMounts.add(externalStorageVolumes[i].getAbsolutePath());
}
for(int i = 0; i < mMounts.size(); i++){
for(int j = 0; j < mMounts.size(); j++){
if(i!=j && mMounts.get(i).startsWith(mMounts.get(j)))
mMounts.remove(i);
}
}
setProperties();
}
@@ -264,22 +274,22 @@ public class StorageOptions
for (String path : mMounts)
{//with forcemount menu
if ("/mnt/sdcard".equalsIgnoreCase(path) || "/storage/sdcard0".equalsIgnoreCase(path))
mLabels.add("Internal SD " + "[" + path + "]");
mLabels.add("Internal SD " + "[" + path + "/]");
else if (path.contains("emulated"))
mLabels.add("Emulated SD " + " [" + path + "]");
mLabels.add("Emulated SD " + " [" + path + "/]");
else
mLabels.add("External SD " + " [" + path + "]");
mLabels.add("External SD " + " [" + path + "/]");
}
}
else
{
for (String path : mMounts)
{
// TODO: /mnt/sdcard is assumed to always mean internal storage. Use this comparison until there is a better way to do this
if ("/mnt/sdcard".equalsIgnoreCase(path))
mLabels.add("Built-in Storage");
// TODO: /mnt/sdcard and emulated are assumed to always mean internal storage. Use this comparison until there is a better way to do this
if ("/mnt/sdcard".equalsIgnoreCase(path) || path.contains("emulated"))
mLabels.add("Built-in Storage " + "[" + path + "/]");
else
mLabels.add("External SD Card " + i++);
mLabels.add("External SD Card " + "[" + path + "/]");
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
author=Wagic Team
name=Born of the Gods
block=Theros
year=2014
year=2014-02-07
total=165
[/meta]
[card]

View File

@@ -1,7 +1,7 @@
[meta]
author=Wagic Team
name=Commander 2014
year=2014
year=2014-11-07
total=337
[/meta]
[card]

View File

@@ -1,7 +1,7 @@
[meta]
author=Wagic Team
name=Magic: The Gathering—Conspiracy
year=2014
year=2014-06-06
total=197
[/meta]
[card]

View File

@@ -359,7 +359,6 @@ primitive=Eldrazi Scion
id=-417465
rarity=T
[/card]
[/card]
[card]
primitive=Demon
id=-417480

View File

@@ -0,0 +1,161 @@
[meta]
author=Wagic Team
name=Historic Anthology 3
year=2020-05-21
total=31
[/meta]
[card]
primitive=Soldier
id=-294701
rarity=T
[/card]
[card]
primitive=Bird
id=-294700
rarity=T
[/card]
[card]
primitive=Wurm
id=-294698
rarity=T
[/card]
[card]
primitive=Spirit
id=-294690
rarity=T
[/card]
[card]
primitive=Akroma's Memorial
id=294680
rarity=M
[/card]
[card]
primitive=Ancient Ziggurat
id=294681
rarity=U
[/card]
[card]
primitive=Body Double
id=294682
rarity=R
[/card]
[card]
primitive=Chainer's Edict
id=294683
rarity=U
[/card]
[card]
primitive=Devil's Play
id=294684
rarity=R
[/card]
[card]
primitive=Enchantress's Presence
id=294685
rarity=R
[/card]
[card]
primitive=Gempalm Incinerator
id=294686
rarity=U
[/card]
[card]
primitive=Gempalm Polluter
id=294687
rarity=C
[/card]
[card]
primitive=Honden of Cleansing Fire
id=294688
rarity=U
[/card]
[card]
primitive=Honden of Infinite Rage
id=294689
rarity=U
[/card]
[card]
primitive=Honden of Life's Web
id=294690
rarity=U
[/card]
[card]
primitive=Honden of Night's Reach
id=294691
rarity=U
[/card]
[card]
primitive=Honden of Seeing Winds
id=294692
rarity=U
[/card]
[card]
primitive=Krosan Tusker
id=294693
rarity=C
[/card]
[card]
primitive=Momentary Blink
id=294694
rarity=C
[/card]
[card]
primitive=Maze's End
id=294695
rarity=M
[/card]
[card]
primitive=Mirari's Wake
id=294696
rarity=R
[/card]
[card]
primitive=Ratchet Bomb
id=294697
rarity=R
[/card]
[card]
primitive=Roar of the Wurm
id=294698
rarity=U
[/card]
[card]
primitive=Silent Departure
id=294699
rarity=C
[/card]
[card]
primitive=Swan Song
id=294700
rarity=R
[/card]
[card]
primitive=Timely Reinforcements
id=294701
rarity=U
[/card]
[card]
primitive=Tectonic Reformation
id=294702
rarity=R
[/card]
[card]
primitive=Tempered Steel
id=294703
rarity=R
[/card]
[card]
primitive=Unburial Rites
id=294704
rarity=U
[/card]
[card]
primitive=Ulamog, the Ceaseless Hunger
id=294705
rarity=M
[/card]
[card]
primitive=Phyrexian Obliterator
id=294706
rarity=M
[/card]

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
author=Wagic Team
name=Journey into Nyx
block=Theros
year=2014
year=2014-05-02
total=165
[/meta]
[card]

View File

@@ -2,7 +2,7 @@
author=Wagic Team
name=Duel Decks: Jace vs. Vraska
block=Duel
year=2014
year=2014-03-14
total=88
[/meta]
[card]

View File

@@ -2,7 +2,7 @@
author=Wagic Team
name=Khans of Tarkir
block=Khans of Tarkir
year=2014
year=2014-09-26
total=269
[/meta]
[card]

View File

@@ -1,7 +1,7 @@
[meta]
author=Wagic Team
name=Magic 2015 Core Set
year=2014
year=2014-07-18
total=284
[/meta]
[card]

View File

@@ -117,7 +117,7 @@ rarity=U
[card]
primitive=Dispatch
id=16672
rarityU
rarity=U
[/card]
[card]
primitive=Steelshaper's Gift

View File

@@ -2,7 +2,7 @@
author=Wagic Team
name=From the Vault: Annihilation
block=Vault
year=2014
year=2014-08-22
total=15
[/meta]
[card]

File diff suppressed because it is too large Load Diff

View File

@@ -6190,7 +6190,8 @@ type=Sorcery
name=Artful Maneuver
target=creature
auto=2/2 ueot
auto=if rebound then moveto(exile) all(this) and!( transforms((,newability[@rebounded:may activate castcard(normal)])) forever )!
auto=if rebound then moveto(exile)
autoexile=@rebounded:may activate castcard(normal)
text=Target creature gets +2/+2 until end of turn. -- Rebound (If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost.)
mana={1}{W}
type=Instant
@@ -18239,7 +18240,8 @@ auto=choice name(red) transforms((,newability[protection from red])) ueot
auto=choice name(blue) transforms((,newability[protection from blue])) ueot
auto=choice name(black) transforms((,newability[protection from black])) ueot
auto=choice name(white) transforms((,newability[protection from white])) ueot
auto=if rebound then moveto(exile) all(this) and!( transforms((,newability[@rebounded:may activate castcard(normal)])) forever )!
auto=if rebound then moveto(exile)
autoexile=@rebounded:may activate castcard(normal)
text=Target creature you control gains protection from the color of your choice until end of turn. -- Rebound (If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost.)
mana={1}{W}
type=Instant
@@ -22224,7 +22226,8 @@ type=Instant
name=Consuming Vapors
target=player
auto=ability$! notatarget(creature|mybattlefield) dynamicability<!mytgt toughnesslifegain abilitycontroller!> sacrifice ) !$ targetedplayer
auto=if rebound then moveto(exile) all(this) and!( transforms((,newability[@rebounded:may activate castcard(normal)])) forever )!
auto=if rebound then moveto(exile)
autoexile=@rebounded:may activate castcard(normal)
text=Target player sacrifices a creature. You gain life equal to that creature's toughness. -- Rebound (If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost.)
mana={3}{B}
type=Sorcery
@@ -30317,7 +30320,8 @@ name=Distortion Strike
target=creature
auto=1/0 ueot
auto=unblockable ueot
auto=if rebound then moveto(exile) all(this) and!( transforms((,newability[@rebounded:may activate castcard(normal)])) forever )!
auto=if rebound then moveto(exile)
autoexile=@rebounded:may activate castcard(normal)
text=Target creature gets +1/+0 until end of turn and is unblockable this turn. -- Rebound (If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost.)
mana={U}
type=Sorcery
@@ -35600,7 +35604,8 @@ auto=choice name(red) transforms((,newability[protection from red])) ueot
auto=choice name(blue) transforms((,newability[protection from blue])) ueot
auto=choice name(black) transforms((,newability[protection from black])) ueot
auto=choice name(white) transforms((,newability[protection from white])) ueot
auto=if rebound then moveto(exile) all(this) and!( transforms((,newability[@rebounded:may activate castcard(normal)])) forever )!
auto=if rebound then moveto(exile)
autoexile=@rebounded:may activate castcard(normal)
text=Target creature you control gains protection from the color of your choice until end of turn. -- Rebound (If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost.)
mana={W}
type=Instant
@@ -50088,7 +50093,8 @@ toughness=3
[card]
name=Great Teacher's Decree
auto=all(creature|mybattlefield) 2/1 ueot
auto=if rebound then moveto(exile) all(this) and!( transforms((,newability[@rebounded:may activate castcard(normal)])) forever )!
auto=if rebound then moveto(exile)
autoexile=@rebounded:may activate castcard(normal)
text=Creatures you control get +2/+1 until end of turn. -- Rebound (If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost.)
mana={3}{W}
type=Sorcery
@@ -80944,7 +80950,8 @@ toughness=2
[card]
name=Nomads' Assembly
auto=token(Kor Soldier,Creature Kor Soldier,1/1,white)*type:creature:mybattlefield
auto=if rebound then moveto(exile) all(this) and!( transforms((,newability[@rebounded:may activate castcard(normal)])) forever )!
auto=if rebound then moveto(exile)
autoexile=@rebounded:may activate castcard(normal)
text=Put a 1/1 white Kor Soldier creature token onto the battlefield for each creature you control. -- Rebound (If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost.)
mana={4}{W}{W}
type=Sorcery
@@ -82327,7 +82334,8 @@ toughness=6
name=Ojutai's Breath
target=creature
auto=freeze
auto=if rebound then moveto(exile) all(this) and!( transforms((,newability[@rebounded:may activate castcard(normal)])) forever )!
auto=if rebound then moveto(exile)
autoexile=@rebounded:may activate castcard(normal)
text=Tap target creature. It doesn't untap during its controller's next untap step. -- Rebound (If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost.)
mana={2}{U}
type=Instant
@@ -82335,7 +82343,8 @@ type=Instant
[card]
name=Ojutai's Summons
auto=create(Djinn Monk:Creature Djinn Monk:2/2:flying:blue)
auto=if rebound then moveto(exile) all(this) and!( transforms((,newability[@rebounded:may activate castcard(normal)])) forever )!
auto=if rebound then moveto(exile)
autoexile=@rebounded:may activate castcard(normal)
text=Put a 2/2 blue Djinn Monk creature token with flying onto the battlefield. -- Rebound (If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost.)
mana={3}{U}{U}
type=Sorcery
@@ -88605,7 +88614,8 @@ type=Sorcery
name=Prey's Vengeance
target=creature
auto=2/2
auto=if rebound then moveto(exile) all(this) and!( transforms((,newability[@rebounded:may activate castcard(normal)])) forever )!
auto=if rebound then moveto(exile)
autoexile=@rebounded:may activate castcard(normal)
text=Target creature gets +2/+2 until end of turn. -- Rebound (If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost.)
mana={G}
type=Instant
@@ -89341,7 +89351,8 @@ type=Sorcery
name=Profound Journey
target=*[-instant;-sorcery]|mygraveyard
auto=moveto(ownerbattlefield)
auto=if rebound then moveto(exile) all(this) and!( transforms((,newability[@rebounded:may activate castcard(normal)])) forever )!
auto=if rebound then moveto(exile)
autoexile=@rebounded:may activate castcard(normal)
text=Return target permanent card from your graveyard to the battlefield. -- Rebound (If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost.)
mana={5}{W}{W}
type=Sorcery
@@ -93549,7 +93560,8 @@ type=Instant
name=Recurring Insight
target=opponent
auto=draw:type:*:targetedpersonshand controller
auto=if rebound then moveto(exile) all(this) and!( transforms((,newability[@rebounded:may activate castcard(normal)])) forever )!
auto=if rebound then moveto(exile)
autoexile=@rebounded:may activate castcard(normal)
text=Draw cards equal to the number of cards in target opponent's hand. -- Rebound (If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost.)
mana={4}{U}{U}
type=Sorcery
@@ -105487,7 +105499,8 @@ name=Sight Beyond Sight
abilities=hiddenface
aicode=activate transforms((,newability[moveto(myhand) all(*[zpos=1]|mylibrary) && bottomoflibrary all(*[zpos=2]|mylibrary)])) ueot
auto=name(look) reveal:2 optionone name(Get a card) target(<1>*|reveal) moveto(myhand) optiononeend optiontwo name(put on bottom) target(<2>*|reveal) bottomoflibrary optiontwoend revealend
auto=if rebound then moveto(exile) all(this) and!( transforms((,newability[@rebounded:may activate castcard(normal)])) forever )!
auto=if rebound then moveto(exile)
autoexile=@rebounded:may activate castcard(normal)
text=Look at the top two cards of your library. Put one of them into your hand and the other on the bottom of your library. -- Rebound (If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost.)
mana={3}{U}
type=Sorcery
@@ -112865,7 +112878,8 @@ toughness=0
name=Staggershock
target=creature,player
auto=damage:2
auto=if rebound then moveto(exile) all(this) and!( transforms((,newability[@rebounded:may activate castcard(normal)])) forever )!
auto=if rebound then moveto(exile)
autoexile=@rebounded:may activate castcard(normal)
text=Staggershock deals 2 damage to target creature or player. -- Rebound (If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost.)
mana={2}{R}
type=Instant
@@ -116556,7 +116570,8 @@ toughness=1
[card]
name=Surreal Memoir
auto=moverandom(instant) from(mygraveyard) to(myhand)
auto=if rebound then moveto(exile) all(this) and!( transforms((,newability[@rebounded:may activate castcard(normal)])) forever )!
auto=if rebound then moveto(exile)
autoexile=@rebounded:may activate castcard(normal)
text=Return an instant card at random from your graveyard to your hand. -- Rebound (If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost.)
mana={3}{R}
type=Sorcery
@@ -116584,7 +116599,8 @@ type=Sorcery
name=Survival Cache
auto=life:2 controller
auto=if compare(lifetotal)~morethan~compare(opponentlifetotal) then draw:1 controller
auto=if rebound then moveto(exile) all(this) and!( transforms((,newability[@rebounded:may activate castcard(normal)])) forever )!
auto=if rebound then moveto(exile)
autoexile=@rebounded:may activate castcard(normal)
text=You gain 2 life. Then if you have more life than an opponent, draw a card. -- Rebound (If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost.)
mana={2}{W}
type=Sorcery
@@ -117610,7 +117626,8 @@ name=Taigam's Strike
target=creature
auto=2/0 ueot
auto=unblockable ueot
auto=if rebound then moveto(exile) all(this) and!( transforms((,newability[@rebounded:may activate castcard(normal)])) forever )!
auto=if rebound then moveto(exile)
autoexile=@rebounded:may activate castcard(normal)
text=Target creature gets +2/+0 until end of turn and can't be blocked this turn. -- Rebound (If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost.)
mana={3}{U}
type=Sorcery
@@ -129911,7 +129928,8 @@ name=Virulent Swipe
target=creature
auto=2/0 ueot
auto=deathtouch ueot
auto=if rebound then moveto(exile) all(this) and!( transforms((,newability[@rebounded:may activate castcard(normal)])) forever )!
auto=if rebound then moveto(exile)
autoexile=@rebounded:may activate castcard(normal)
text=Target creature gets +2/+0 and gains deathtouch until end of turn. -- Rebound (If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost.)
mana={B}
type=Instant
@@ -130493,7 +130511,8 @@ type=Sorcery
name=Void Squall
target=*[-land]
auto=moveto(ownerhand)
auto=if rebound then moveto(exile) all(this) and!( transforms((,newability[@rebounded:may activate castcard(normal)])) forever )!
auto=if rebound then moveto(exile)
autoexile=@rebounded:may activate castcard(normal)
text=Return target nonland permanent to its owner's hand. -- Rebound (If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost.)
mana={4}{U}
type=Sorcery
@@ -136122,7 +136141,8 @@ toughness=2
name=World at War
auto=nextphasealter(add,combatphaseswithmain,controller,after<postbattle>)
auto=untap all(creature[attacking])
auto=if rebound then moveto(exile) all(this) and!( transforms((,newability[@rebounded:may activate castcard(normal)])) forever )!
auto=if rebound then moveto(exile)
autoexile=@rebounded:may activate castcard(normal)
text=After the first postcombat main phase this turn, there's an additional combat phase followed by an additional main phase. At the beginning of that combat, untap all creatures that attacked this turn. -- Rebound (If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost.)
mana={3}{R}{R}
type=Sorcery

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
#build.number.properties (normally this file is maintained by build.xml)
#Sun, 06 May 2012 11:56:35 -0700
#Sun, 20 May 2020 11:56:35 +0200
build.major=0
build.minor=20
build.point=1
build.minor=22
build.point=3

View File

@@ -63,6 +63,7 @@ This file was auto-generated by ant build script on ${TODAY}
To make changes please edit the ant build script, otherwise your changes will be lost
Author: Michael Nguyen
Mod by: Vitty85
*/
@@ -73,7 +74,6 @@ Author: Michael Nguyen
#define WAGIC_VERSION_MAJOR ${build.major}
#define WAGIC_VERSION_MEDIUM ${build.minor}
#define WAGIC_VERSION_MINOR ${build.point}
#define WAGIC_VERSION_REVISION ${env.TRAVIS_BUILD_NUMBER}
#define VERSION_DOT(a, b, c, d) a ##.## b ##.## c ##.## d
#define VERSION_WITHOUT_DOT(a, b, c) a ## b ## c
@@ -82,12 +82,12 @@ Author: Michael Nguyen
#define VERSION_TOSTRING(a) #a
#define VERSION_STRINGIFY(a) VERSION_TOSTRING(a)
#define WAGIC_VERSION VERSION_GAME(WAGIC_VERSION_MAJOR, WAGIC_VERSION_MEDIUM, WAGIC_VERSION_MINOR, WAGIC_VERSION_REVISION)
#define WAGIC_VERSION VERSION_GAME(WAGIC_VERSION_MAJOR, WAGIC_VERSION_MEDIUM, WAGIC_VERSION_MINOR)
#define WAGIC_RESOURCE_VERSION VERSION_FILE(WAGIC_VERSION_MAJOR, WAGIC_VERSION_MEDIUM, WAGIC_VERSION_MINOR)
#define WAGIC_VERSION_STRING VERSION_STRINGIFY(WAGIC_VERSION)
#define WAGIC_CORE_VERSION_STRING "core_" VERSION_STRINGIFY(WAGIC_RESOURCE_VERSION)
#define WAGIC_RESOURCE_NAME "Wagic-core.zip"
#define WAGIC_RELEASE_NAME "${env.RELEASE_NAME}"
#define WAGIC_RESOURCE_NAME "Wagic-core-" VERSION_STRINGIFY(WAGIC_RESOURCE_VERSION) ".zip"
#define WAGIC_RELEASE_NAME "wagic-v" WAGIC_VERSION_STRING
#define WAGIC_RESOURCE_URL "https://github.com/WagicProject/wagic/releases/download/" WAGIC_RELEASE_NAME "/" WAGIC_RESOURCE_NAME
#endif

View File

@@ -178,6 +178,8 @@ private:
intValue = 0;
bool halfup = false;
bool halfdown = false;
bool thirdup = false;
bool thirddown = false;
bool twice = false;
bool thrice = false;
bool other = false;//othertype:[subtype]
@@ -218,6 +220,18 @@ private:
size_t hD = s.find("halfdown");
s.erase(hD,hD + 8);
}
if(s.find("thirdup") != string::npos)
{
thirdup = true;
size_t tU = s.find("thirdup");
s.erase(tU,tU + 7);
}
if(s.find("thirddown") != string::npos)
{
thirddown = true;
size_t tD = s.find("thirddown");
s.erase(tD,tD + 9);
}
if(s.find("twice") != string::npos)
{
twice = true;
@@ -328,6 +342,10 @@ private:
{
intValue = target->equipment;
}
else if (s == "mutations")
{
intValue = target->mutation;
}
else if (s == "colors")
{
intValue = target->countColors();
@@ -560,6 +578,14 @@ private:
{
intValue = card->controller()->opponent()->energyCount;
}
else if (s == "pyidarocount")
{
intValue = card->controller()->yidaroCount;
}
else if (s == "oyidarocount")
{
intValue = card->controller()->opponent()->yidaroCount;
}
else if (s == "praidcount")
{
intValue = card->controller()->raidcount;
@@ -1047,6 +1073,16 @@ private:
}
if (halfdown)
intValue = intValue / 2;
if (thirdup)
{
if (intValue % 3 > 0)
intValue = (intValue / 3) + 1;
else
intValue = intValue / 3;
}
if (thirddown)
intValue = intValue / 3;
}
if (twice)
intValue = intValue * 2;
@@ -1613,6 +1649,29 @@ public:
}
};
class TrCardMutated: public Trigger
{
public:
bool thiscontroller, thisopponent;
TrCardMutated(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc,bool once = false) :
Trigger(observer, id, source,once, tc)
{
}
int triggerOnEventImpl(WEvent * event)
{
WEventCardMutated * e = dynamic_cast<WEventCardMutated *> (event);
if (!e) return 0;
if (!tc->canTarget(e->card)) return 0;
return 1;
}
TrCardMutated * clone() const
{
return NEW TrCardMutated(*this);
}
};
class TrCardSacrificed: public Trigger
{
public:
@@ -3045,6 +3104,8 @@ public:
int addToGame()
{
if(!ability)
return 1; //Fix a possible crash on mutate cards
ability->forceDestroy = -1;
ability->target = target; //Might have changed since initialization
ability->addToGame();
@@ -3762,6 +3823,7 @@ public:
int unequip();
int equip(MTGCardInstance * equipped);
int mutate(MTGCardInstance * mutated);
int resolve();
const string getMenuText();
@@ -4696,6 +4758,19 @@ public:
AAAlterEnergy * clone() const;
~AAAlterEnergy();
};
//Yidaro Counter
class AAAlterYidaroCount: public ActivatedAbilityTP
{
public:
int yidarocount;
AAAlterYidaroCount(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, int yidarocount, ManaCost * _cost = NULL,
int who = TargetChooser::UNSET);
int resolve();
const string getMenuText();
AAAlterYidaroCount * clone() const;
~AAAlterYidaroCount();
};
/* Standard Damager, can choose a NEW target each time the price is paid */
class TADamager: public TargetAbility
{
@@ -4808,7 +4883,8 @@ public:
bool retarget;
bool reequip;
bool newhook;
AANewTarget(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target,bool retarget = false, ManaCost * _cost = NULL, bool reequip = false, bool newhook = false);
int mutation;
AANewTarget(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target,bool retarget = false, ManaCost * _cost = NULL, bool reequip = false, bool newhook = false, int mutation = 0);
int resolve();
const string getMenuText();
AANewTarget * clone() const;
@@ -6959,7 +7035,8 @@ public:
bool noEvent;
bool putinplay;
bool asNormalMadness;
AACastCard(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target,bool restricted,bool copied,bool _asNormal,string nameCard,string abilityName,bool _noEvent, bool putinplay,bool asNormalMadness = false);
bool alternative;
AACastCard(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target,bool restricted,bool copied,bool _asNormal,string nameCard,string abilityName,bool _noEvent, bool putinplay,bool asNormalMadness = false,bool alternative = false);
int testDestroy(){return 0;};
void Update(float dt);

View File

@@ -176,6 +176,7 @@ public:
virtual ostream& toString(ostream& out) const;
virtual int addToGame();
virtual int removeFromGame();
static vector<void *> deletedpointers;
/*Poor man's casting */
/* Todo replace that crap with dynamic casting */

View File

@@ -62,6 +62,7 @@ public:
int frozen;
int sunburst;
int equipment;
int mutation;
int auras;
bool wasDealtDamage;
bool combatdamageToOpponent;

View File

@@ -281,7 +281,9 @@ class Constants
TOTEMARMOR = 155,
DISCARDTOPLAYBYOPPONENT = 156,
MODULAR = 157,
NB_BASIC_ABILITIES = 158,
MUTATE = 158,
ADVENTURE = 159,
NB_BASIC_ABILITIES = 160,
RARITY_S = 'S', //Special Rarity
RARITY_M = 'M', //Mythics

View File

@@ -43,6 +43,7 @@ public:
int extraTurn;
int drawCounter;
int energyCount;
int yidaroCount;
int epic;
int forcefield;
int dealsdamagebycombat;

View File

@@ -77,6 +77,14 @@ class ThisOpponentlife:public ThisDescriptor{
ThisOpponentlife * clone() const;
};
class ThisMutation:public ThisDescriptor{
public:
virtual int match(MTGCardInstance * card);
ThisMutation(int mutation);
ThisMutation * clone() const;
};
class ThisEquip:public ThisDescriptor{
public:
virtual int match(MTGCardInstance * card);

View File

@@ -72,7 +72,7 @@ struct WEventLife : public WEvent {
Player * player;
int amount;
MTGCardInstance * source;
WEventLife(Player * player,int amount, MTGCardInstance * source);
WEventLife(Player * player, int amount, MTGCardInstance * source);
virtual Targetable * getTarget(int target);
};
@@ -351,6 +351,12 @@ struct WEventplayerEnergized : public WEvent {
virtual Targetable * getTarget(Player * player);
};
//mutation event
struct WEventCardMutated : public WEventCardUpdate {
WEventCardMutated(MTGCardInstance * card);
virtual Targetable * getTarget(int target);
};
std::ostream& operator<<(std::ostream&, const WEvent&);
#endif

View File

@@ -4,6 +4,7 @@ This file was auto-generated by ant build script on Sat, 26-Oct-2013 23::59:07
To make changes please edit the ant build script, otherwise your changes will be lost
Author: Michael Nguyen
Mod by: Vitty85
*/
@@ -13,7 +14,7 @@ Author: Michael Nguyen
/* Wagic versions */
#define WAGIC_VERSION_MAJOR 0
#define WAGIC_VERSION_MEDIUM 22
#define WAGIC_VERSION_MINOR 2
#define WAGIC_VERSION_MINOR 3
#define VERSION_DOT(a, b, c) a ##.## b ##.## c
#define VERSION_WITHOUT_DOT(a, b, c) a ## b ## c

View File

@@ -1023,6 +1023,44 @@ AAAlterPoison::~AAAlterPoison()
{
}
//AA Yidaro Count
AAAlterYidaroCount::AAAlterYidaroCount(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, int yidarocount, ManaCost * _cost,
int who) :
ActivatedAbilityTP(observer, _id, _source, _target, _cost, who), yidarocount(yidarocount)
{
}
int AAAlterYidaroCount::resolve()
{
Damageable * _target = (Damageable *) getTarget();
if (_target)
{
Player * pTarget = (Player*)_target;
if(pTarget)
{
pTarget->yidaroCount += yidarocount;
if(pTarget->yidaroCount < 0)
pTarget->yidaroCount = 0;
}
}
return 0;
}
const string AAAlterYidaroCount::getMenuText()
{
WParsedInt parsedNum(yidarocount);
return _(parsedNum.getStringValue() + " Yidaro Cycling Counter ").c_str();
}
AAAlterYidaroCount * AAAlterYidaroCount::clone() const
{
return NEW AAAlterYidaroCount(*this);
}
AAAlterYidaroCount::~AAAlterYidaroCount()
{
}
//AA Energy Counters
AAAlterEnergy::AAAlterEnergy(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, int energy, ManaCost * _cost,
int who) :
@@ -3168,8 +3206,8 @@ AAFrozen * AAFrozen::clone() const
}
// chose a new target for an aura or enchantment and equip it note: VERY basic right now.
AANewTarget::AANewTarget(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target,bool retarget, ManaCost * _cost, bool reequip, bool newhook) :
ActivatedAbility(observer, id, card, _cost, 0),retarget(retarget),reequip(reequip),newhook(newhook)
AANewTarget::AANewTarget(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target,bool retarget, ManaCost * _cost, bool reequip, bool newhook, int mutation) :
ActivatedAbility(observer, id, card, _cost, 0),retarget(retarget),reequip(reequip),newhook(newhook),mutation(mutation)
{
target = _target;
}
@@ -3182,7 +3220,7 @@ int AANewTarget::resolve()
_target = source;
source = (MTGCardInstance *) target;
}
if (_target && !reequip)
if (_target && !reequip && !mutation)
{
while (_target->next)
_target = _target->next;
@@ -3219,7 +3257,7 @@ int AANewTarget::resolve()
}
}
if (_target && _target->currentZone == _target->controller()->game->battlefield && reequip)
if (_target && _target->currentZone == _target->controller()->game->battlefield && reequip && !mutation)
{
if(!newhook)
{
@@ -3254,6 +3292,53 @@ int AANewTarget::resolve()
source = _target;
}
}
if (_target && _target->currentZone == _target->controller()->game->battlefield && mutation > 0)
{
_target = source;
source = (MTGCardInstance *) target;
for (size_t i = 1; i < game->mLayers->actionLayer()->mObjects.size(); i++)
{
MTGAbility * a = ((MTGAbility *) game->mLayers->actionLayer()->mObjects[i]);
AEquip * eq = dynamic_cast<AEquip*> (a);
if (eq && eq->source == _target)
{
uint8_t sourceoldcolors = source->colors; // Read the original colors before mutation
uint8_t _targetoldcolors = _target->colors;
((AEquip*)a)->mutate(source); // hook the cards one each other
source->colors = sourceoldcolors; // Restore the original colors after the mutation
if(mutation == 1){
int deltapower = source->getPower() - source->origpower; // keep counters and power/toughness increasement
int deltatoughness = source->getToughness() - source->origtoughness;
source->origpower = _target->origpower;
source->origtoughness = _target->origtoughness;
source->basepower = _target->basepower;
source->basetoughness = _target->basetoughness;
source->setPower(_target->getPower() + deltapower);
source->setToughness(_target->getToughness() + deltatoughness);
source->colors = _targetoldcolors; // The mutated card gain all colors from the parent
std::string oldname = source->getName(); // The mutated card swap its name with the parent
source->setName(_target->getName());
_target->setName(oldname);
for (int i = ((int)source->types.size())-1; i >= 0; --i) // The mutated card looses all its types
if(source->types[i] != 1)
source->removeType(source->types[i]);
for (int i = 0; i < ((int)_target->types.size()); i++) // The mutated card gains all the types of the source card
if(_target->types[i] != 1)
source->addType(_target->types[i]);
if(source->types[0] == 1 && source->types[1] == 7){ // Fix order for Legendary Creatures
source->types[0] = 7;
source->types[1] = 1;
}
}
_target->colors = 0; // The parent card loose all its colors
for (int i = ((int)_target->types.size())-1; i >= 0; --i) // The parent card looses all types and becomes a dummy Mutated type
_target->removeType(_target->types[i]);
_target->setType("Mutated");
}
}
target = source;
source = _target;
}
return 1;
}
@@ -5389,10 +5474,16 @@ IfThenAbility * IfThenAbility::clone() const
IfThenAbility::~IfThenAbility()
{
SAFE_DELETE(delayedAbility);
SAFE_DELETE(delayedElseAbility);
if(delayedAbility && (std::find(deletedpointers.begin(), deletedpointers.end(), delayedAbility) == deletedpointers.end())) {
deletedpointers.push_back(delayedAbility); // Fix to avoid crash on May abilities nested in IfThenElse Abilities.
SAFE_DELETE(delayedAbility);
}
if(delayedElseAbility && (std::find(deletedpointers.begin(), deletedpointers.end(), delayedElseAbility) == deletedpointers.end())) {
deletedpointers.push_back(delayedElseAbility); // Fix to avoid crash on May abilities nested in IfThenElse Abilities.
SAFE_DELETE(delayedElseAbility);
}
}
//
//May Abilities
MayAbility::MayAbility(GameObserver* observer, int _id, MTGAbility * _ability, MTGCardInstance * _source, bool must,string _cond) :
MTGAbility(observer, _id, _source), NestedAbility(_ability), must(must), Cond(_cond)
@@ -6336,8 +6427,8 @@ int ATransformer::destroy()
{
for (unsigned int i = 0;i < newAbilities[_target].size(); i++)
{
// The primitives Dead Presence probabily causes a double free error and a crash in Wagic, so for now it has been exluded...
if(newAbilities[_target].at(i) && strcmp(_target->name.c_str(),"Dread Presence"))
// The primitives Dead Presence and the mutated cards probably cause a double free error and a crash in Wagic, so for now they have been exluded...
if(newAbilities[_target].at(i) && strcmp(_target->name.c_str(),"Dread Presence") && !_target->mutation)
{
newAbilities[_target].at(i)->forceDestroy = 1;
newAbilities[_target].at(i)->removeFromGame();
@@ -6884,9 +6975,10 @@ int AProduceMana::receiveEvent(WEvent * event)
int AProduceMana::produce()
{
if(ManaDescription == "selectmana")
{//I tried menu ability and vector<MTGAbility*abi> to have a shorter code but it crashes wagic at end of turn...
//The may ability on otherhand works but the ability is cumulative...
//This must be wrapped on menuability so we can use it on successions...
{
//I tried menu ability and vector<MTGAbility*abi> to have a shorter code but it crashes wagic at end of turn...
//The may ability on otherhand works but the ability is cumulative...
//This must be wrapped on menuability so we can use it on successions...
AManaProducer *ap0 = NEW AManaProducer(game, game->mLayers->actionLayer()->getMaxId(), source, source->controller(), ManaCost::parseManaCost(mana[0],NULL,source), NULL, 0,"",false);
MayAbility *mw0 = NEW MayAbility(game, game->mLayers->actionLayer()->getMaxId(), ap0, source,true);
MTGAbility *ga0 = NEW GenericAddToGame(game, game->mLayers->actionLayer()->getMaxId(), source,NULL,mw0);
@@ -8091,11 +8183,47 @@ int AEquip::equip(MTGCardInstance * equipped)
return 1;
}
int AEquip::mutate(MTGCardInstance * mutated)
{
source->target = mutated;
source->target->mutation += 1;
source->mutation += 1;
source->parentCards.push_back(mutated);
source->target->childrenCards.push_back((MTGCardInstance*)source);
AbilityFactory af(game);
af.getAbilities(&currentAbilities, NULL, source);
for (size_t i = 0; i < currentAbilities.size(); ++i)
{
MTGAbility * a = currentAbilities[i];
if (dynamic_cast<AEquip *> (a)) continue;
if (dynamic_cast<ATeach *> (a)) continue;
if (dynamic_cast<AAConnect *> (a)) continue;
if (dynamic_cast<AANewTarget *> (af.getCoreAbility(a))) continue;
if (a->aType == MTGAbility::STANDARD_TOKENCREATOR && a->oneShot)
{
a->forceDestroy = 1;
continue;
}
if (dynamic_cast<AACopier *> (af.getCoreAbility(a)))
{
a->forceDestroy = 1;
continue;
}
//we generally dont want to pass oneShot tokencreators to the cards
//we mutate...
a->addToGame();
}
WEvent * e = NEW WEventCardMutated(mutated);
source->getObserver()->receiveEvent(e); // triggers the @mutated event for any other listener.
return 1;
}
int AEquip::resolve()
{
MTGCardInstance * mTarget = tc->getNextCardTarget();
if (!mTarget) return 0;
if (mTarget == source) return 0;
if (source->mutation) return 0; // No need to unequip mutation cards.
unequip();
equip(mTarget);
return 1;
@@ -8111,6 +8239,9 @@ const string AEquip::getMenuText()
int AEquip::testDestroy()
{
if(source->mutation) // No need to unequip mutation cards.
return 0;
if (source->target && !game->isInPlay(source->target))
//unequip();//testfix for equipment when the card it equip moves to other battlefield
if (!game->connectRule)
@@ -8123,6 +8254,8 @@ int AEquip::testDestroy()
int AEquip::destroy()
{
if(source->mutation) // No need to unequip mutation cards.
return 0;
unequip();
return TargetAbility::destroy();
}
@@ -8133,8 +8266,8 @@ AEquip * AEquip::clone() const
}
// casting a card for free, or casting a copy of a card.
AACastCard::AACastCard(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target,bool _restricted,bool _copied,bool asNormal,string _namedCard,string _name,bool _noEvent,bool putinplay,bool madness) :
MTGAbility(observer, _id, _source),restricted(_restricted),asCopy(_copied),normal(asNormal),cardNamed(_namedCard),nameThis(_name),noEvent(_noEvent),putinplay(putinplay), asNormalMadness(madness)
AACastCard::AACastCard(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target,bool _restricted,bool _copied,bool asNormal,string _namedCard,string _name,bool _noEvent,bool putinplay,bool madness, bool alternative) :
MTGAbility(observer, _id, _source),restricted(_restricted),asCopy(_copied),normal(asNormal),cardNamed(_namedCard),nameThis(_name),noEvent(_noEvent),putinplay(putinplay), asNormalMadness(madness), alternative(alternative)
{
target = _target;
andAbility = NULL;
@@ -8397,7 +8530,7 @@ int AACastCard::resolveSpell()
copy =_target->controller()->game->putInZone(_target, _target->currentZone, source->controller()->game->stack,noEvent);
copy->changeController(source->controller(),true);
if(asNormalMadness)
copy->MadnessPlay = true;
copy->MadnessPlay = true;
}
else
{
@@ -8407,6 +8540,8 @@ int AACastCard::resolveSpell()
copy =_target->controller()->game->putInZone(_target, _target->currentZone, source->controller()->game->stack,noEvent);
copy->changeController(source->controller(),true);
}
if(alternative)
copy->alternateCostPaid[ManaCost::MANA_PAID_WITH_ALTERNATIVE] = 1;
if (game->targetChooser)
{
game->targetChooser->Owner = source->controller();

View File

@@ -851,7 +851,7 @@ void CardGui::AlternateRender(MTGCard * card, const Pos& pos)
}
} else {
for (unsigned int i = 0; i < card->data->types.size() - 1; i++)
{
{
s += _(MTGAllCards::findType(card->data->types[i]));
if(!strcmp(_(MTGAllCards::findType(card->data->types[i])).c_str(),"Creature") || !strcmp(_(MTGAllCards::findType(card->data->types[i])).c_str(),"Land"))
s += _(" - ");
@@ -1152,7 +1152,7 @@ void CardGui::TinyCropRender(MTGCard * card, const Pos& pos, JQuad * quad)
}
} else {
for (unsigned int i = 0; i < card->data->types.size() - 1; i++)
{
{
s += _(MTGAllCards::findType(card->data->types[i]));
if(!strcmp(_(MTGAllCards::findType(card->data->types[i])).c_str(),"Creature") || !strcmp(_(MTGAllCards::findType(card->data->types[i])).c_str(),"Land"))
s += _(" - ");
@@ -1276,7 +1276,7 @@ void CardGui::RenderBig(MTGCard* card, const Pos& pos, bool thumb, bool noborder
string cardsetname = setlist[card->setId].c_str();
/*if(!noborder)
{
if(cardsetname == "2ED"||cardsetname == "RV"||cardsetname == "4ED"||cardsetname == "5ED"||cardsetname == "6ED"||cardsetname == "7ED"||cardsetname == "8ED"||cardsetname == "9ED"||cardsetname == "CHR"||cardsetname == "DM")
if(cardsetname == "2ED"||cardsetname == "RV"||cardsetname == "4ED"||cardsetname == "5ED"||cardsetname == "6ED"||cardsetname == "7ED"||cardsetname == "8ED"||cardsetname == "9ED"||cardsetname == "S00"||cardsetname == "S99"||cardsetname == "PTK"||cardsetname == "BTD"||cardsetname == "ATH"||cardsetname == "BRB"||cardsetname == "CHR"||cardsetname == "DM")
{//Draw white border
renderer->FillRoundRect((pos.actX - (pos.actZ * 84.f))-11.5f,(pos.actY - (pos.actZ * 119.7f))-14.f,pos.actZ * 168.f + 6.5f,pos.actZ * 239.4f + 12.f,8.f,ARGB(255,248,248,255));
renderer->DrawRoundRect((pos.actX - (pos.actZ * 84.f))-11.5f,(pos.actY - (pos.actZ * 119.7f))-14.f,pos.actZ * 168.f + 6.5f,pos.actZ * 239.4f + 12.f,8.f,ARGB(150,20,20,20));
@@ -1299,7 +1299,7 @@ void CardGui::RenderBig(MTGCard* card, const Pos& pos, bool thumb, bool noborder
//universal border
if(options[Options::SHOWBORDER].number)
{
if((cardsetname == "2ED"||cardsetname == "RV"||cardsetname == "4ED"||cardsetname == "5ED"||cardsetname == "6ED"||cardsetname == "7ED"||cardsetname == "8ED"||cardsetname == "9ED"||cardsetname == "CHR"||cardsetname == "DM")
if((cardsetname == "2ED"||cardsetname == "RV"||cardsetname == "4ED"||cardsetname == "5ED"||cardsetname == "6ED"||cardsetname == "7ED"||cardsetname == "8ED"||cardsetname == "9ED"||cardsetname == "S00"||cardsetname == "S99"||cardsetname == "PTK"||cardsetname == "BTD"||cardsetname == "ATH"||cardsetname == "BRB"||cardsetname == "CHR"||cardsetname == "DM")
&& !options[Options::BLKBORDER].number)
{//white border
renderer->FillRoundRect(pos.actX - (scale * quad->mWidth / 2)-6.f,pos.actY - (scale * quad->mHeight / 2)-5.8f, (scale * quad->mWidth)-0.02f, (scale * quad->mHeight)-0.02f, 5.8f,ARGB(255,248,248,255));

View File

@@ -189,7 +189,7 @@ int SnowCost::doPay()
result += source->controller()->snowManaC;
if (result)
{
// Avoided double payments for Snow Mana cost
// Avoided double payments for Snow Mana cost
if (source->controller()->snowManaC && source->controller()->getManaPool()->canAfford(ManaCost::parseManaCost("{1}",NULL,source)))
{
//source->controller()->getManaPool()->pay(ManaCost::parseManaCost("{1}",NULL,source));

View File

@@ -788,7 +788,7 @@ void GameObserver::gameStateBasedEffects()
else if((!card->target->isLand() && card->hasType("fortification")))
((AEquip*)a)->unequip();
}
if(card->controller())
if(card->controller() && !card->mutation)
((AEquip*)a)->getActionTc()->Owner = card->controller();
//fix for equip ability when the equipment changed controller...
}
@@ -1406,9 +1406,9 @@ bool GameObserver::WaitForExtraPayment(MTGCardInstance * card)
mExtraPayment = NULL;
}
result = true;
// Avoid game stucks on current phase till snow mana cost will be paid
if(mExtraPayment && mExtraPayment->costs.size() == 1 && !strcmp(mExtraPayment->costs[0]->mCostRenderString.c_str(), "Snow Mana"))
result = false;
// Avoid game stucks on current phase till snow mana cost will be paid
if(mExtraPayment && mExtraPayment->costs.size() == 1 && !strcmp(mExtraPayment->costs[0]->mCostRenderString.c_str(), "Snow Mana"))
result = false;
}
return result;

View File

@@ -95,13 +95,19 @@ void GameStateAwards::Start()
listview->Add(wgh);
int locked = 0;
for (int i = 0; i < setlist.size(); i++)
vector<pair<string, string> > orderedSet;
for(int i = 0; i < setlist.size(); i++){
sprintf(buf, "%s", setlist[i].c_str());
orderedSet.push_back(pair<string, string> (setlist.getInfo(i)->getName(), buf));
}
sort(orderedSet.begin(),orderedSet.end());
for (unsigned int i = 0; i < orderedSet.size(); i++)
{
MTGSetInfo * si = setlist.getInfo(i);
MTGSetInfo * si = setlist.getInfo(setlist.findSet(orderedSet.at(i).second));
if (!si)
continue;
if (!options[Options::optionSet(i)].number)
{
if (!options[Options::optionSet(setlist.findSet(orderedSet.at(i).second))].number){
locked++;
continue;
}
@@ -119,9 +125,9 @@ void GameStateAwards::Start()
else
sprintf(buf, _("%s: %i cards.").c_str(), si->author.c_str(), si->totalCards());
aw = NEW WGuiAward(Options::optionSet(i), si->getName(), buf, "Card Spoiler");
aw = NEW WGuiAward(Options::optionSet(setlist.findSet(orderedSet.at(i).second)), si->getName(), buf, "Card Spoiler");
aw->mFlags = WGuiItem::NO_TRANSLATE;
btn = NEW WGuiButton(aw, GUI_AWARD_BUTTON, Options::optionSet(i), this);
btn = NEW WGuiButton(aw, GUI_AWARD_BUTTON, Options::optionSet(setlist.findSet(orderedSet.at(i).second)), this);
listview->Add(btn);
}
if (locked)

View File

@@ -364,6 +364,8 @@ void GameStateDuel::End()
#ifdef TESTSUITE
SAFE_DELETE(testSuite);
#endif
MTGAbility::deletedpointers.clear(); // Clear the list of deallocated pointer.
}
//TODO Move This to utils or ResourceManager. Don't we have more generic functions that can do that?

View File

@@ -58,7 +58,7 @@ void GameStateOptions::Start()
optionsList->Add(NEW WGuiHeader("Card Display Options"));
optionsList->Add(NEW OptionInteger(Options::SHOWBORDER, "Show Borders"));
//black border
optionsList->Add(NEW OptionInteger(Options::BLKBORDER, "All Black Border"));
optionsList->Add(NEW OptionInteger(Options::BLKBORDER, "All Black Borders"));
//show tokens in editor
optionsList->Add(NEW OptionInteger(Options::SHOWTOKENS, "Show Tokens in Editor"));
WDecoStyled * wMisc = NEW WDecoStyled(NEW WGuiHeader("Warning!!!"));
@@ -258,9 +258,9 @@ void GameStateOptions::Render()
"",
"Dev Team:",
"Abrasax, Almosthumane, Daddy32, DJardin, Dr.Solomat,",
"J, Jeck, kevlahnota, Leungclj, linshier, Mootpoint,",
"Mnguyen, Ph34rbot, Psyringe, Rolzad73, Salmelo, Superhiro,",
"Vitty85, Wololo, Yeshua, Zethfox",
"J, Jeck, kevlahnota, Leungclj, linshier, Mootpoint,",
"Mnguyen, Ph34rbot, Psyringe, Rolzad73, Salmelo, Superhiro,",
"Vitty85, Wololo, Yeshua, Zethfox",
"",
"Music by Celestial Aeon Project, http://www.jamendo.com",
"",

View File

@@ -1169,6 +1169,10 @@ TriggeredAbility * AbilityFactory::parseTrigger(string s, string, int id, Spell
if (TargetChooser * tc = parseSimpleTC(s, "drawn", card))
return NEW TrcardDrawn(observer, id, card, tc,once);
//Card is mutated
if (TargetChooser * tc = parseSimpleTC(s, "mutated", card))
return NEW TrCardMutated(observer, id, card, tc,once);
//Card is sacrificed
if (TargetChooser * tc = parseSimpleTC(s, "sacrificed", card))
return NEW TrCardSacrificed(observer, id, card, tc,once);
@@ -3128,6 +3132,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
bool asNormalMadness = splitCastCard[1].find("madness") != string::npos;
bool sendNoEvent = splitCastCard[1].find("noevent") != string::npos;
bool putinplay = splitCastCard[1].find("putinplay") != string::npos;
bool alternative = splitCastCard[1].find("alternative") != string::npos;
string nameCard = "";
if(splitCastCard[1].find("named!:") != string::npos)
{
@@ -3137,7 +3142,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
nameCard = splitCastName[1];
}
}
MTGAbility *a = NEW AACastCard(observer, id, card, target,withRestrictions,asCopy,asNormal,nameCard,newName,sendNoEvent,putinplay, asNormalMadness);
MTGAbility *a = NEW AACastCard(observer, id, card, target,withRestrictions,asCopy,asNormal,nameCard,newName,sendNoEvent,putinplay, asNormalMadness, alternative);
a->oneShot = false;
if(splitCastCard[1].find("trigger[to]") != string::npos)
{
@@ -3278,6 +3283,38 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
return a;
}
//alter yidaro counter
vector<string> splitYidaroCounter = parseBetween(s, "alteryidarocount:", " ", false);
if (splitYidaroCounter.size())
{
int yidarocount = atoi(splitYidaroCounter[1].c_str());
Targetable * t = spell ? spell->getNextTarget() : NULL;
MTGAbility * a = NEW AAAlterYidaroCount(observer, id, card, t, yidarocount, NULL, who);
a->oneShot = 1;
return a;
}
//alter mutation counter on target card with trigger activation
vector<string> splitMutated = parseBetween(s, "altermutationcounter:", " ", false);
if (splitMutated.size())
{
card->mutation += atoi(splitMutated[1].c_str());
WEvent * e = NEW WEventCardMutated(card);
card->getObserver()->receiveEvent(e);
}
//set mutation counter on source card with no trigger activation
vector<string> splitMutatedOver = parseBetween(s, "mutationover:", " ", false);
if (splitMutatedOver.size())
{
card->mutation += atoi(splitMutatedOver[1].c_str());
}
vector<string> splitMutatedUnder = parseBetween(s, "mutationunder:", " ", false);
if (splitMutatedUnder.size())
{
card->mutation += atoi(splitMutatedUnder[1].c_str());
}
//prevent next damage
vector<string> splitPrevent = parseBetween(s, "prevent:", " ", false);
if (splitPrevent.size())
@@ -4174,6 +4211,14 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
return a;
}
//get a new target for muatations
if ((s.find("mutateover") != string::npos) || s.find("mutateunder") != string::npos)
{
MTGAbility * a = NEW AANewTarget(observer, id, card,target, false,NULL,false,false,(s.find("mutateover") != string::npos)?1:2);
a->oneShot = 1;
return a;
}
//morph
found = s.find("morph");
if (found != string::npos)
@@ -4687,8 +4732,8 @@ int AbilityFactory::abilityEfficiency(MTGAbility * a, Player * p, int mode, Targ
badAbilities[(int)Constants::NOLIFEGAINOPPONENT] = true;
badAbilities[(int)Constants::MUSTBLOCK] = true;
badAbilities[(int)Constants::FLYERSONLY] = true;
badAbilities[(int)Constants::TREASON] = true;
badAbilities[(int)Constants::SHACKLER] = true;
badAbilities[(int)Constants::TREASON] = true;
badAbilities[(int)Constants::SHACKLER] = true;
if (AInstantBasicAbilityModifierUntilEOT * abi = dynamic_cast<AInstantBasicAbilityModifierUntilEOT *>(a))
{
@@ -5539,6 +5584,8 @@ MTGAbility * AbilityFactory::getManaReduxAbility(string s, int id, Spell *, MTGC
return NEW AAlterCost(observer, id, card, target, amount, color);
}
vector<void*> MTGAbility::deletedpointers;
MTGAbility::MTGAbility(const MTGAbility& a): ActionElement(a)
{
//Todo get rid of menuText, it is only used as a placeholder in getMenuText, for something that could be a string
@@ -6024,7 +6071,7 @@ int TargetAbility::reactToClick(MTGCardInstance * card)
game->mExtraPayment = cost->extraCosts;
return 0;
}
if (!tc) return 0; // Fix crash on mutating cards
waitingForAnswer = 1;
game->mLayers->actionLayer()->setCurrentWaitingAction(this);
tc->initTargets();
@@ -6306,7 +6353,8 @@ void ListMaintainerAbility::updateTargets()
{
MTGCardInstance * card = (*it).first;
cards.erase(card);
removed(card);
if(!card->mutation) // Fix crash on mutating card...
removed(card);
}
temp.clear();
//add New valid ones
@@ -6426,7 +6474,8 @@ int ListMaintainerAbility::destroy()
{
MTGCardInstance * card = (*it).first;
cards.erase(card);
removed(card);
if(!card->mutation) // Fix crash on mutating card...
removed(card);
it = cards.begin();
}
return 1;

View File

@@ -237,6 +237,7 @@ void MTGCardInstance::initMTGCI()
notblocked = 0;
sunburst = 0;
equipment = 0;
mutation = 0;
auras = 0;
combatdamageToOpponent = false;
damageToOpponent = false;

View File

@@ -188,7 +188,9 @@ const char* Constants::MTGBasicAbilities[] = {
"showopponenttoplibrary",
"totemarmor",
"discardtoplaybyopponent",
"modular"
"modular",
"mutate", //it can mutate
"adventure" //it can be adventure
};
map<string,int> Constants::MTGBasicAbilitiesMap;

View File

@@ -782,12 +782,14 @@ int MTGAlternativeCostRule::isReactingToClick(MTGCardInstance * card, ManaCost *
if(!allowedToAltCast(card,player))
return 0;
if(card->has(Constants::ADVENTURE) && game->isInExile(card))
return 0; // Advetures can't be alternate casted from exile.
alternativeName = "Pay Alternative Cost";
if(card->has(Constants::CANPLAYFROMGRAVEYARD) && game->isInGrave(card))
alternativeName = "Alternate Cast From Graveyard";
else if(card->has(Constants::CANPLAYFROMEXILE) && game->isInExile(card))
else if(card->has(Constants::CANPLAYFROMEXILE) && game->isInExile(card) && !card->has(Constants::ADVENTURE))
alternativeName = "Alternate Cast From Exile";
else if(card->canPlayFromLibrary() && game->isInLibrary(card))
alternativeName = "Alternate Cast From Library";

View File

@@ -35,6 +35,7 @@ Player::Player(GameObserver *observer, string file, string fileSmall, MTGDeck *
extraTurn = 0;
drawCounter = 0;
energyCount = 0;
yidaroCount = 0;
epic = 0;
forcefield = 0;
dealsdamagebycombat = 0;

View File

@@ -598,6 +598,7 @@ void Rules::initGame(GameObserver *g, bool currentPlayerSet)
p->damageCount = initState.playerData[i].player->damageCount;
p->preventable = initState.playerData[i].player->preventable;
p->energyCount = initState.playerData[i].player->energyCount;
p->yidaroCount = initState.playerData[i].player->yidaroCount;
if (initState.playerData[i].player->mAvatarName.size())
{
p->mAvatarName = initState.playerData[i].player->mAvatarName;

View File

@@ -145,6 +145,18 @@ ThisDescriptor * ThisDescriptorFactory::createThisDescriptor(GameObserver* obser
return NULL;
}
//mutations
found = s.find("mutations");
if (found != string::npos)
{
ThisMutation * td = NEW ThisMutation(criterion);
if (td)
{
td->comparisonMode = mode;
return td;
}
return NULL;
}
//equips and auras
found = s.find("gear");//still same meaning, better wording to word conflict with MTGAbility equip.
if (found != string::npos)
@@ -513,6 +525,20 @@ ThisPower* ThisPower::clone() const
return NEW ThisPower(*this);
}
ThisMutation::ThisMutation(int mutation)
{
comparisonCriterion = mutation;
}
int ThisMutation::match(MTGCardInstance * card)
{
return matchValue(card->mutation);
}
ThisMutation* ThisMutation::clone() const
{
return NEW ThisMutation(*this);
}
ThisEquip::ThisEquip(int equipment)
{
comparisonCriterion = equipment;

View File

@@ -286,6 +286,11 @@ WEventplayerEnergized::WEventplayerEnergized(Player * player, int nb_count) :
player(player), nb_count(nb_count)
{
}
WEventCardMutated::WEventCardMutated(MTGCardInstance * card) :
WEventCardUpdate(card)
{
}
;
Targetable * WEventDamage::getTarget(int target)
@@ -484,6 +489,12 @@ Targetable * WEventCardCopiedACard::getTarget(int target)
return NULL;
}
Targetable * WEventCardMutated::getTarget(int target)
{
if (target) return card;
return NULL;
}
Targetable * WEventplayerEnergized::getTarget(Player * player)
{
if (player) return player;

View File

@@ -1345,7 +1345,7 @@ void WGuiAward::Underlay()
}
if (!trophy.get()) //Fallback to basic trophy image.
trophy = WResourceManager::Instance()->RetrieveTempQuad("trophy.png");
trophy = WResourceManager::Instance()->RetrieveTempQuad("trophy.png");
#endif
if (trophy.get())
@@ -2215,11 +2215,15 @@ void WGuiFilterItem::updateValue()
else if (filterType == FILTER_SET)
{
char buf[512];
for (int i = 0; i < setlist.size(); i++)
{
vector<pair<string, string> > orderedSet;
for(int i = 0; i < setlist.size(); i++){
if (options[Options::optionSet(i)].number == 0) continue;
sprintf(buf, "s:%s;", setlist[i].c_str());
mParent->addArg((setlist.getInfo(i))->getName(), buf);
orderedSet.push_back(pair<string, string> (setlist.getInfo(i)->getName(), buf));
}
sort(orderedSet.begin(),orderedSet.end());
for (unsigned int i = 0; i < orderedSet.size(); i++){
mParent->addArg(orderedSet.at(i).first, orderedSet.at(i).second);
}
}
else if (filterType == FILTER_ALPHA)