Merge branch 'master' into cmake

This commit is contained in:
xawotihs
2016-06-29 21:36:47 +02:00
40 changed files with 15689 additions and 9603 deletions
+23
View File
@@ -2,6 +2,11 @@
## [latest-master] (https://github.com/WagicProject/wagic/tree/latest-master) ## [latest-master] (https://github.com/WagicProject/wagic/tree/latest-master)
#### 6/29/16
- *Merged pull-request:* Updated Primitives and Hide Highlight Border [#\707] (https://github.com/WagicProject/wagic/pull/707) ([kevlahnota](https://github.com/kevlahnota))
- *Committed:* Pretty huge patch here(sorry old habits never die :( ) [#\6ee00c1] (https://github.com/WagicProject/wagic/commit/6ee00c138ce374d54cb3ee034575ce440288ca0e) ([zethfoxster](https://github.com/zethfoxster))
#### 6/23/16 #### 6/23/16
- *Merged pull-request:* Fix producecolor:color [#\704] (https://github.com/WagicProject/wagic/pull/704) ([kevlahnota](https://github.com/kevlahnota)) - *Merged pull-request:* Fix producecolor:color [#\704] (https://github.com/WagicProject/wagic/pull/704) ([kevlahnota](https://github.com/kevlahnota))
@@ -14,6 +19,24 @@
#### 6/11/16 #### 6/11/16
- *Merged pull-request:* Refactor & Devotion [#\690] (https://github.com/WagicProject/wagic/pull/690) ([kevlahnota](https://github.com/kevlahnota)) - *Merged pull-request:* Refactor & Devotion [#\690] (https://github.com/WagicProject/wagic/pull/690) ([kevlahnota](https://github.com/kevlahnota))
#### 6/9/16
- *Closed issue:* Clone goes to graveyard before being able to copy anything [\#546](https://github.com/WagicProject/wagic/issues/546)
- *Closed issue:* Blinking an aura causes freeze [\#541](https://github.com/WagicProject/wagic/issues/541)
- *Closed issue:* Profile name at upper left side is not being updated correctly [\#469](https://github.com/WagicProject/wagic/issues/469)
- *Closed issue:* Giving card C protection from X does not remove cards attached to C which have quality X [\#464](https://github.com/WagicProject/wagic/issues/464)
- *Closed issue:* (graphical glitch) wood / gold textures [\#461](https://github.com/WagicProject/wagic/issues/461)
- *Closed issue:* Clone does not get all P/T bonuses [\#448](https://github.com/WagicProject/wagic/issues/448)
- *Closed issue:* Card "threaten" messes up the GUI [\#473](https://github.com/WagicProject/wagic/issues/473)
#### 6/7/16
- *Closed issue:* Emrakul isn't killed by creatures with deathtouch [\#597](https://github.com/WagicProject/wagic/issues/597)
#### 6/3/16 #### 6/3/16
- *Merged pull-request:* Cost Increaser & Reducer Fix [#\676] (https://github.com/WagicProject/wagic/pull/676) ([kevlahnota](https://github.com/kevlahnota)) - *Merged pull-request:* Cost Increaser & Reducer Fix [#\676] (https://github.com/WagicProject/wagic/pull/676) ([kevlahnota](https://github.com/kevlahnota))
@@ -17,6 +17,7 @@ public class DeckImporter
String message = ""; String message = "";
String deck = ""; String deck = "";
String deckname = ""; String deckname = "";
String prefix = "#SB:";
if(f.exists() && !f.isDirectory()) if(f.exists() && !f.isDirectory())
{ {
deckname = f.getName(); deckname = f.getName();
@@ -33,15 +34,21 @@ public class DeckImporter
{ {
while (scanner.hasNext()) while (scanner.hasNext())
{ {
boolean foundSideboard = false;
String line = scanner.nextLine(); String line = scanner.nextLine();
if(line.toLowerCase().contains("sideboard"))
foundSideboard = true;
String[] slines = line.split("\\s+"); String[] slines = line.split("\\s+");
String arranged = ""; String arranged = "";
for(int idx = 1; idx < slines.length; idx++) for(int idx = 1; idx < slines.length; idx++)
{ {
arranged += slines[idx] + " "; arranged += slines[idx] + " ";
} }
if (isNumeric(slines[0]) && arranged != null) if ((isNumeric(slines[0])||foundSideboard) && arranged != null)
{ {
if (foundSideboard)
deck += prefix;
if (slines[1] != null && slines[1].startsWith("[")) if (slines[1] != null && slines[1].startsWith("["))
{ {
arranged = arranged.substring(5); arranged = arranged.substring(5);
@@ -221,7 +221,7 @@ public class SDLActivity extends Activity implements OnKeyListener
File[] files = root.listFiles(); File[] files = root.listFiles();
for( File f : files) for( File f : files)
{ {
if( !myresult.contains(f.toString()) && (f.toString().contains(".txt")||f.toString().contains(".dec"))) if( !myresult.contains(f.toString()) && (f.toString().contains(".txt")||f.toString().contains(".dck")||f.toString().contains(".dec")))
myresult.add(f.toString()); myresult.add(f.toString());
} }
+4
View File
@@ -42,6 +42,10 @@
<item name="types" > <item name="types" >
<position x="22" y="49"/> <position x="22" y="49"/>
</item> </item>
<item name="cardid" >
<position x="22" y="237"/>
<formattedtext>mtgid</formattedtext>
</item>
<item name="expansionrarity" > <item name="expansionrarity" >
<position x="22" y="255"/> <position x="22" y="255"/>
<formattedtext>expansion rarity</formattedtext> <formattedtext>expansion rarity</formattedtext>
+1
View File
@@ -35,6 +35,7 @@ auto=lifelinkrule
auto=deathtouchrule auto=deathtouchrule
auto=soulbondrule auto=soulbondrule
auto=dredgerule auto=dredgerule
auto=bestowrule
[PLAYERS] [PLAYERS]
life:20 life:20
+75
View File
@@ -289,6 +289,11 @@ id=401859
rarity=C rarity=C
[/card] [/card]
[card] [card]
primitive=Dragon
id=-401860
rarity=T
[/card]
[card]
primitive=Dragonmaster Outcast primitive=Dragonmaster Outcast
id=401860 id=401860
rarity=M rarity=M
@@ -346,16 +351,76 @@ rarity=C
[card] [card]
primitive=Eldrazi Scion primitive=Eldrazi Scion
rarity=T rarity=T
id=-401803
[/card]
[card]
primitive=Eldrazi Scion
rarity=T
id=-401819 id=-401819
[/card] [/card]
[card] [card]
primitive=Eldrazi Scion primitive=Eldrazi Scion
rarity=T rarity=T
id=-401825
[/card]
[card]
primitive=Eldrazi Scion
rarity=T
id=-401832
[/card]
[card]
primitive=Eldrazi Scion
rarity=T
id=-401833
[/card]
[card]
primitive=Eldrazi Scion
rarity=T
id=-401836
[/card]
[card]
primitive=Eldrazi Scion
rarity=T
id=-401838
[/card]
[card]
primitive=Eldrazi Scion
rarity=T
id=-401839
[/card]
[card]
primitive=Eldrazi Scion
rarity=T
id=-401893
[/card]
[card]
primitive=Eldrazi Scion
rarity=T
id=-402092 id=-402092
[/card] [/card]
[card] [card]
primitive=Eldrazi Scion primitive=Eldrazi Scion
rarity=T rarity=T
id=-401900
[/card]
[card]
primitive=Eldrazi Scion
rarity=T
id=-401863
[/card]
[card]
primitive=Eldrazi Scion
rarity=T
id=-401868
[/card]
[card]
primitive=Eldrazi Scion
rarity=T
id=-401875
[/card]
[card]
primitive=Eldrazi Scion
rarity=T
id=-401915 id=-401915
[/card] [/card]
[card] [card]
@@ -689,11 +754,21 @@ id=401932
rarity=C rarity=C
[/card] [/card]
[card] [card]
primitive=Knight Ally
rarity=T
id=-401897
[/card]
[card]
primitive=Kor Ally primitive=Kor Ally
rarity=T rarity=T
id=-402007 id=-402007
[/card] [/card]
[card] [card]
primitive=Kor Ally
rarity=T
id=-402084
[/card]
[card]
primitive=Kor Bladewhirl primitive=Kor Bladewhirl
id=401933 id=401933
rarity=U rarity=U
+30
View File
@@ -234,6 +234,26 @@ id=-407587
rarity=T rarity=T
[/card] [/card]
[card] [card]
primitive=Eldrazi Scion
id=-407635
rarity=T
[/card]
[card]
primitive=Eldrazi Scion
id=-407550
rarity=T
[/card]
[card]
primitive=Eldrazi Scion
id=-407633
rarity=T
[/card]
[card]
primitive=Eldrazi Scion
id=-407631
rarity=T
[/card]
[card]
primitive=Elemental primitive=Elemental
id=-407614 id=-407614
rarity=T rarity=T
@@ -424,6 +444,11 @@ id=-407540
rarity=T rarity=T
[/card] [/card]
[card] [card]
primitive=Kor Ally
id=-407672
rarity=T
[/card]
[card]
primitive=Kor Scythemaster primitive=Kor Scythemaster
id=407533 id=407533
rarity=C rarity=C
@@ -980,6 +1005,11 @@ rarity=T
[/card] [/card]
[card] [card]
primitive=Zombie primitive=Zombie
id=-407596
rarity=T
[/card]
[card]
primitive=Zombie
id=-407598 id=-407598
rarity=T rarity=T
[/card] [/card]
+223 -3
View File
@@ -44,6 +44,11 @@ id=-409751
rarity=T rarity=T
[/card] [/card]
[card] [card]
primitive=Angel
id=-410011
rarity=T
[/card]
[card]
primitive=Angel of Deliverance primitive=Angel of Deliverance
id=409738 id=409738
rarity=R rarity=R
@@ -216,7 +221,127 @@ rarity=C
[card] [card]
primitive=Clue primitive=Clue
rarity=T rarity=T
id=-410067 id=-409746
[/card]
[card]
primitive=Clue
rarity=T
id=-409750
[/card]
[card]
primitive=Clue
rarity=T
id=-409757
[/card]
[card]
primitive=Clue
rarity=T
id=-409762
[/card]
[card]
primitive=Clue
rarity=T
id=-409781
[/card]
[card]
primitive=Clue
rarity=T
id=-409784
[/card]
[card]
primitive=Clue
rarity=T
id=-409795
[/card]
[card]
primitive=Clue
rarity=T
id=-409797
[/card]
[card]
primitive=Clue
rarity=T
id=-409799
[/card]
[card]
primitive=Clue
rarity=T
id=-409805
[/card]
[card]
primitive=Clue
rarity=T
id=-409810
[/card]
[card]
primitive=Clue
rarity=T
id=-409813
[/card]
[card]
primitive=Clue
rarity=T
id=-409820
[/card]
[card]
primitive=Clue
rarity=T
id=-409823
[/card]
[card]
primitive=Clue
rarity=T
id=-409838
[/card]
[card]
primitive=Clue
rarity=T
id=-409953
[/card]
[card]
primitive=Clue
rarity=T
id=-409954
[/card]
[card]
primitive=Clue
rarity=T
id=-409956
[/card]
[card]
primitive=Clue
rarity=T
id=-409986
[/card]
[card]
primitive=Clue
rarity=T
id=-409997
[/card]
[card]
primitive=Clue
rarity=T
id=-410000
[/card]
[card]
primitive=Clue
rarity=T
id=-410004
[/card]
[card]
primitive=Clue
rarity=T
id=-410007
[/card]
[card]
primitive=Clue
rarity=T
id=-410024
[/card]
[card]
primitive=Clue
rarity=T
id=-410032
[/card] [/card]
[card] [card]
primitive=Compelling Deterrence primitive=Compelling Deterrence
@@ -319,6 +444,16 @@ rarity=T
id=-410068 id=-410068
[/card] [/card]
[card] [card]
primitive=Devil
rarity=T
id=-409902
[/card]
[card]
primitive=Devil
rarity=T
id=-409903
[/card]
[card]
primitive=Devils' Playground primitive=Devils' Playground
id=409903 id=409903
rarity=R rarity=R
@@ -689,8 +824,8 @@ id=409919
rarity=C rarity=C
[/card] [/card]
[card] [card]
primitive=Human Soldier primitive=Human Cleric
id=-409780 id=-409760
rarity=T rarity=T
[/card] [/card]
[card] [card]
@@ -699,6 +834,16 @@ id=-410049
rarity=T rarity=T
[/card] [/card]
[card] [card]
primitive=Human Soldier
id=-409780
rarity=T
[/card]
[card]
primitive=Human Soldier
id=-410015
rarity=T
[/card]
[card]
primitive=Humble the Brute primitive=Humble the Brute
id=409762 id=409762
rarity=U rarity=U
@@ -1350,10 +1495,40 @@ rarity=U
[/card] [/card]
[card] [card]
primitive=Spirit primitive=Spirit
id=-409749
rarity=T
[/card]
[card]
primitive=Spirit
id=-410031 id=-410031
rarity=T rarity=T
[/card] [/card]
[card] [card]
primitive=Spirit
rarity=T
id=-409753
[/card]
[card]
primitive=Spirit
rarity=T
id=-409768
[/card]
[card]
primitive=Spirit
rarity=T
id=-409769
[/card]
[card]
primitive=Spirit
rarity=T
id=-409789
[/card]
[card]
primitive=Spirit
rarity=T
id=-409755
[/card]
[card]
primitive=Spiteful Motives primitive=Spiteful Motives
id=409939 id=409939
rarity=U rarity=U
@@ -1585,6 +1760,11 @@ rarity=C
[/card] [/card]
[card] [card]
primitive=Vampire Knight primitive=Vampire Knight
id=-409850
rarity=T
[/card]
[card]
primitive=Vampire Knight
id=-410016 id=-410016
rarity=T rarity=T
[/card] [/card]
@@ -1690,10 +1870,20 @@ rarity=U
[/card] [/card]
[card] [card]
primitive=Wolf primitive=Wolf
id=-409959
rarity=T
[/card]
[card]
primitive=Wolf
id=-409983 id=-409983
rarity=T rarity=T
[/card] [/card]
[card] [card]
primitive=Wolf
id=-409991
rarity=T
[/card]
[card]
primitive=Wolf of Devil's Breach primitive=Wolf of Devil's Breach
id=409949 id=409949
rarity=M rarity=M
@@ -1705,6 +1895,36 @@ rarity=U
[/card] [/card]
[card] [card]
primitive=Zombie primitive=Zombie
id=-409800
rarity=T
[/card]
[card]
primitive=Zombie
id=-409826
rarity=T
[/card]
[card]
primitive=Zombie
id=-409854
rarity=T
[/card]
[card]
primitive=Zombie
id=-409859
rarity=T
[/card]
[card]
primitive=Zombie
id=-409860
rarity=T
[/card]
[card]
primitive=Zombie
id=-409862
rarity=T
[/card]
[card]
primitive=Zombie
id=-409884 id=-409884
rarity=T rarity=T
[/card] [/card]
@@ -12,18 +12,6 @@ power=4
toughness=4 toughness=4
[/card] [/card]
[card] [card]
name=Aven Warhawk
abilities=flying
auto=foreach(bird|myhand) counter(1/1,1)
auto=foreach(soldier|myhand) counter(1/1,1)
text=Amplify 1 (As this creature enters the battlefield, put a +1/+1 counter on it for each Bird and/or Soldier card you reveal in your hand.) -- Flying
mana={4}{W}
type=Creature
subtype=Bird Soldier
power=2
toughness=2
[/card]
[card]
name=Cemetery Puca name=Cemetery Puca
text=Whenever a creature is put into a graveyard from the battlefield, you may pay {1}. If you do, Cemetery Puca becomes a copy of that creature and gains this ability. text=Whenever a creature is put into a graveyard from the battlefield, you may pay {1}. If you do, Cemetery Puca becomes a copy of that creature and gains this ability.
auto=@movedto(creature|graveyard) from(battlefield):all(trigger[from]) pay[[{1}]] copy auto=@movedto(creature|graveyard) from(battlefield):all(trigger[from]) pay[[{1}]] copy
@@ -109,27 +97,6 @@ auto={3}:counter(1/1)
#Not all player can use ability #Not all player can use ability
[/card] [/card]
[card] [card]
name=Ghastly Remains
auto=foreach(zombie|myhand) counter(1/1,1)
autograveyard={B}{B}{B}:moveTo(myhand) myUpkeepOnly
text=Amplify 1 (As this creature enters the battlefield, put a +1/+1 counter on it for each Zombie card you reveal in your hand.) -- At the beginning of your upkeep, if Ghastly Remains is in your graveyard, you may pay {B}{B}{B}. If you do, return Ghastly Remains to your hand.
mana={B}{B}{B}
type=Creature
subtype=Zombie
power=0
toughness=0
[/card]
[card]
name=Glowering Rogon
auto=foreach(beast|myhand) counter(1/1,1)
text=Amplify 1 (As this creature enters the battlefield, put a +1/+1 counter on it for each Beast card you reveal in your hand.)
mana={5}{G}
type=Creature
subtype=Beast
power=4
toughness=4
[/card]
[card]
name=Govern the Guildless name=Govern the Guildless
target=creature[-multicolor] target=creature[-multicolor]
auto=moveto(mybattlefield) auto=moveto(mybattlefield)
@@ -348,6 +315,13 @@ text={T}: Add {1} to your mana pool. -- {2}, {T}: Thespian's Stage becomes a cop
type=Land type=Land
[/card] [/card]
[card] [card]
name=Trinisphere
auto=this(untapped) lord(*[-land]|hand,library,exile,graveyard) trinisphere forcedalive
text=As long as Trinisphere is untapped, each spell that would cost less than three mana to cast costs three mana to cast. (Additional mana in the cost may be paid with any color of mana or colorless mana. For example, a spell that would cost {1}{B} to cast costs {2}{B} to cast instead.)
mana={3}
type=Artifact
[/card]
[card]
name=Unstable Shapeshifter name=Unstable Shapeshifter
auto=@movedto(other creature|battlefield):all(trigger[from]) copy auto=@movedto(other creature|battlefield):all(trigger[from]) copy
text=Whenever another creature enters the battlefield, Unstable Shapeshifter becomes a copy of that creature and gains this ability. text=Whenever another creature enters the battlefield, Unstable Shapeshifter becomes a copy of that creature and gains this ability.
@@ -367,14 +341,3 @@ mana={B}
type=Instant type=Instant
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.) 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.)
[/card] [/card]
[card]
name=Zombie Brute
abilities=trample
auto=foreach(zombie|myhand) counter(1/1,1)
text=Amplify 1 (As this creature enters the battlefield, put a +1/+1 counter on it for each Zombie card you reveal in your hand.) -- Trample
mana={6}{B}
type=Creature
subtype=Zombie
power=5
toughness=4
[/card]
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+187 -8
View File
@@ -38,6 +38,117 @@ public:
virtual MTGEventText * clone() const; virtual MTGEventText * clone() const;
}; };
class MTGRevealingCards : public MTGAbility, public CardDisplay
{
public:
vector<CardView*> cards;
Player * playerForZone;
MTGGameZone * RevealZone;
MTGGameZone * RevealFromZone;
string revealCertainTypes;
string revealUntil;
CardDisplay * revealDisplay;
vector<CardDisplay*>trashDisplays;//used for repeat
int nbCard;
string abilityString;
string number;
string abilityOne;
string abilityTwo;
string afterReveal;
bool afterEffectActivated;
MTGAbility * abilityToCast;
MTGAbility * abilityFirst;
MTGAbility * abilitySecond;
MTGAbility * abilityAfter;
vector<MTGAbility*>abilities;
bool repeat;//only the first ability can be repeated, and it must be targeted.
bool initCD;
void Update(float dt);
int testDestroy();
int toResolve();
void CardViewBackup(MTGCardInstance * backup);
void Render();
bool CheckUserInput(JButton key);
MTGAbility * contructAbility(string abilityToMake = "");
MTGRevealingCards(GameObserver* observer, int _id, MTGCardInstance * card, string text);
virtual MTGRevealingCards * clone() const;
~MTGRevealingCards();
int receiveEvent(WEvent*);
};
class RevealDisplay : public CardDisplay
{
public:
RevealDisplay(int id, GameObserver* game, int x, int y, JGuiListener * listener = NULL, TargetChooser * tc = NULL,
int nb_displayed_items = 7);
void AddCard(MTGCardInstance * _card);
bool CheckUserInput(JButton key);
};
class GenericRevealAbility : public ActivatedAbility
{
public:
string howMany;
MTGRevealingCards * ability;
GenericRevealAbility(GameObserver* observer, int id, MTGCardInstance * source, Targetable * target, string _howMany);
int resolve();
const string getMenuText();
GenericRevealAbility * clone() const;
~GenericRevealAbility();
};
class MTGScryCards : public MTGAbility, public CardDisplay
{
public:
vector<CardView*> cards;
MTGGameZone * RevealZone;
MTGGameZone * RevealFromZone;
CardDisplay * revealDisplay;
vector<CardDisplay*>trashDisplays;//used for repeat
int nbCard;
bool delayed;
bool dontRevealAfter;
int revealTopAmount;
string delayedAbilityString;
string abilityString;
string number;
string abilityOne;
string abilityTwo;
MTGAbility * abilityToCast;
MTGAbility * abilityFirst;
MTGAbility * abilitySecond;
vector<MTGAbility*>abilities;
bool initCD;
void Update(float dt);
int testDestroy();
void initDisplay(int value = 0);
int toResolve();
void Render();
bool CheckUserInput(JButton key);
MTGAbility * contructAbility(string abilityToMake = "");
MTGScryCards(GameObserver* observer, int _id, MTGCardInstance * card, string text);
virtual MTGScryCards * clone() const;
~MTGScryCards();
int receiveEvent(WEvent*);
};
class GenericScryAbility : public ActivatedAbility
{
public:
string howMany;
MTGScryCards * ability;
GenericScryAbility(GameObserver* observer, int id, MTGCardInstance * source, Targetable * target, string _howMany);
int resolve();
const string getMenuText();
GenericScryAbility * clone() const;
~GenericScryAbility();
};
class WParsedInt class WParsedInt
{ {
public: public:
@@ -240,6 +351,10 @@ private:
{ {
intValue = countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLUE,Constants::MTG_COLOR_GREEN); intValue = countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLUE,Constants::MTG_COLOR_GREEN);
} }
else if (s == "Iroas")//devotion to red white
{
intValue = countDevotionTo(card, card->controller()->inPlay(), Constants::MTG_COLOR_RED, Constants::MTG_COLOR_WHITE);
}
else if (s.find("type:") != string::npos) else if (s.find("type:") != string::npos)
{ {
size_t begins = s.find("type:"); size_t begins = s.find("type:");
@@ -556,6 +671,10 @@ private:
{ {
intValue = target->getCurrentToughness(); intValue = target->getCurrentToughness();
} }
else if (s == "countedamount")
{
intValue = target->CountedObjects;
}
else if (s == "kicked") else if (s == "kicked")
{ {
intValue = target->kicked; intValue = target->kicked;
@@ -745,6 +864,21 @@ private:
intValue += card->controller()->game->inPlay->cards[j]->power; intValue += card->controller()->game->inPlay->cards[j]->power;
} }
} }
else if (s == "revealedp")
{
if (card->revealedLast)
intValue = card->revealedLast->power;
}
else if (s == "revealedt")
{
if (card->revealedLast)
intValue = card->revealedLast->toughness;
}
else if (s == "revealedmana")
{
if (card->revealedLast)
intValue = card->revealedLast->getManaCost()->getConvertedCost();
}
else else
{ {
intValue = atoi(s.c_str()); intValue = atoi(s.c_str());
@@ -2855,7 +2989,6 @@ public:
return NEW ARegularLifeModifierAura(*this); return NEW ARegularLifeModifierAura(*this);
} }
}; };
//Generic Kird Ape //Generic Kird Ape
class AAsLongAs: public ListMaintainerAbility, public NestedAbility class AAsLongAs: public ListMaintainerAbility, public NestedAbility
{ {
@@ -3334,6 +3467,7 @@ public:
list<int> colors; list<int> colors;
int power, toughness; int power, toughness;
int tokenId; int tokenId;
string _cardName;
string name; string name;
string sabilities; string sabilities;
string starfound; string starfound;
@@ -3345,6 +3479,7 @@ public:
MTGCardInstance * myToken; MTGCardInstance * myToken;
vector<MTGAbility *> currentAbilities; vector<MTGAbility *> currentAbilities;
Player * tokenReciever; Player * tokenReciever;
//by id
ATokenCreator(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable *, ManaCost * _cost, int tokenId,string starfound, WParsedInt * multiplier = NULL, ATokenCreator(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable *, ManaCost * _cost, int tokenId,string starfound, WParsedInt * multiplier = NULL,
int who = 0,bool aLivingWeapon = false) : int who = 0,bool aLivingWeapon = false) :
ActivatedAbility(observer, _id, _source, _cost, 0), tokenId(tokenId), starfound(starfound),multiplier(multiplier), who(who),aLivingWeapon(aLivingWeapon) ActivatedAbility(observer, _id, _source, _cost, 0), tokenId(tokenId), starfound(starfound),multiplier(multiplier), who(who),aLivingWeapon(aLivingWeapon)
@@ -3354,7 +3489,18 @@ public:
if (card) name = card->data->getName(); if (card) name = card->data->getName();
battleReady = false; battleReady = false;
} }
//by name, card still require valid card.dat info, this just makes the primitive code far more readable. token(Eldrazi scion) instead of token(-1234234)...
ATokenCreator(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable *, ManaCost * _cost, string cardName, string starfound, WParsedInt * multiplier = NULL,
int who = 0, bool aLivingWeapon = false) :
ActivatedAbility(observer, _id, _source, _cost, 0), _cardName(cardName), starfound(starfound), multiplier(multiplier), who(who), aLivingWeapon(aLivingWeapon)
{
if (!multiplier) this->multiplier = NEW WParsedInt(1);
MTGCard * card = MTGCollection()->getCardByName(_cardName);
tokenId = card->getId();
if (card) name = card->data->getName();
battleReady = false;
}
//by construction
ATokenCreator(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable *, ManaCost * _cost, string sname, string stypes, int _power, int _toughness, ATokenCreator(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable *, ManaCost * _cost, string sname, string stypes, int _power, int _toughness,
string sabilities, string starfound,WParsedInt * multiplier = NULL, int _who = 0,bool aLivingWeapon = false,string spt = "") : string sabilities, string starfound,WParsedInt * multiplier = NULL, int _who = 0,bool aLivingWeapon = false,string spt = "") :
ActivatedAbility(observer, _id, _source, _cost, 0),sabilities(sabilities),starfound(starfound), multiplier(multiplier), who(_who),aLivingWeapon(aLivingWeapon),spt(spt) ActivatedAbility(observer, _id, _source, _cost, 0),sabilities(sabilities),starfound(starfound), multiplier(multiplier), who(_who),aLivingWeapon(aLivingWeapon),spt(spt)
@@ -3877,10 +4023,12 @@ class AThis: public MTGAbility, public NestedAbility
public: public:
MTGAbility * a; MTGAbility * a;
ThisDescriptor * td; ThisDescriptor * td;
AThis(GameObserver* observer, int _id, MTGCardInstance * _source, Damageable * _target, ThisDescriptor * _td, MTGAbility * ability) : string restrictionCheck;
AThis(GameObserver* observer, int _id, MTGCardInstance * _source, Damageable * _target, ThisDescriptor * _td, MTGAbility * ability, string restriction = "") :
MTGAbility(observer, _id, _source, _target), NestedAbility(ability) MTGAbility(observer, _id, _source, _target), NestedAbility(ability)
{ {
td = _td; td = _td;
restrictionCheck = restriction;
ability->source = source; ability->source = source;
ability->target = target; ability->target = target;
a = NULL; a = NULL;
@@ -3904,9 +4052,18 @@ public:
int resolve() int resolve()
{ {
//TODO check if ability is oneShot ? int match = 0;
int match; if (td)
match = td->match(source); {
match = td->match(source);
}
else
{//restriction check instead of Targetchooser
AbilityFactory abf(target->getObserver());
int checkCond = abf.parseCastRestrictions(source, source->controller(), restrictionCheck);
if (checkCond)
match = 1;
}
if (match > 0) if (match > 0)
{ {
addAbilityToGame(); addAbilityToGame();
@@ -3953,6 +4110,7 @@ public:
{ {
AThis * a = NEW AThis(*this); AThis * a = NEW AThis(*this);
a->ability = ability->clone(); a->ability = ability->clone();
if(a->td)
a->td = td->clone(); a->td = td->clone();
return a; return a;
} }
@@ -4166,6 +4324,16 @@ public:
return NEW TADamager(*this); return NEW TADamager(*this);
} }
}; };
//bestow
class ABestow : public ActivatedAbility
{
public:
MTGCardInstance * _card;
ABestow(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target, ManaCost * _cost = NULL);
int resolve();
const string getMenuText();
ABestow * clone() const;
};
/* Can tap a target for a cost */ /* Can tap a target for a cost */
class AATapper: public ActivatedAbility class AATapper: public ActivatedAbility
@@ -4197,12 +4365,22 @@ public:
int resolve(); int resolve();
AAWhatsMax * clone() const; AAWhatsMax * clone() const;
}; };
//counts a targetchooser for use later by other effects
class AACountObject : public ActivatedAbility
{
public:
string value;
AACountObject(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * source, ManaCost * _cost = NULL, string value ="");
int resolve();
AACountObject * clone() const;
};
/* Can prevent a card from untapping next untap */ /* Can prevent a card from untapping next untap */
class AAFrozen: public ActivatedAbility class AAFrozen: public ActivatedAbility
{ {
public: public:
AAFrozen(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target, ManaCost * _cost = NULL); bool freeze;
AAFrozen(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target, bool tap, ManaCost * _cost = NULL);
int resolve(); int resolve();
const string getMenuText(); const string getMenuText();
AAFrozen * clone() const; AAFrozen * clone() const;
@@ -6205,7 +6383,8 @@ public:
MTGCardInstance * theNamedCard; MTGCardInstance * theNamedCard;
bool noEvent; bool noEvent;
bool putinplay; bool putinplay;
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;
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);
int testDestroy(){return 0;}; int testDestroy(){return 0;};
void Update(float dt); void Update(float dt);
+1
View File
@@ -80,6 +80,7 @@ class GameObserver{
ExtraCosts * mExtraPayment; ExtraCosts * mExtraPayment;
int oldGamePhase; int oldGamePhase;
TargetChooser * targetChooser; TargetChooser * targetChooser;
CardDisplay * OpenedDisplay;
DuelLayers * mLayers; DuelLayers * mLayers;
ReplacementEffects *replacementEffects; ReplacementEffects *replacementEffects;
vector<Player *> players; //created outside vector<Player *> players; //created outside
+1
View File
@@ -121,6 +121,7 @@ public:
ManaCost* BuyBack; ManaCost* BuyBack;
ManaCost* FlashBack; ManaCost* FlashBack;
ManaCost* Retrace; ManaCost* Retrace;
ManaCost* Bestow;
ManaCost* morph; ManaCost* morph;
ManaCost* suspend; ManaCost* suspend;
+4
View File
@@ -95,6 +95,7 @@ public:
bool exileEffects; bool exileEffects;
bool suspended; bool suspended;
bool miracle; bool miracle;
bool isBestowed;
int chooseacolor; int chooseacolor;
string chooseasubtype; string chooseasubtype;
int coinSide;//1 = tails int coinSide;//1 = tails
@@ -105,6 +106,7 @@ public:
int notblocked; int notblocked;
int fresh; int fresh;
int MaxLevelUp; int MaxLevelUp;
int CountedObjects;
int kicked; int kicked;
int dredge; int dredge;
bool isDualWielding; bool isDualWielding;
@@ -272,6 +274,8 @@ public:
string currentimprintName; string currentimprintName;
vector<string>imprintedNames; vector<string>imprintedNames;
MTGCardInstance * revealedLast;//last card revealed by a ability this card owns.
bool MadnessPlay;
void eventattacked(); void eventattacked();
void eventattackedAlone(); void eventattackedAlone();
void eventattackednotblocked(); void eventattackednotblocked();
+7 -2
View File
@@ -82,6 +82,7 @@ class Constants
static const string kRetraceKeyword; static const string kRetraceKeyword;
static const string kKickerKeyword; static const string kKickerKeyword;
static const string kMorphKeyword; static const string kMorphKeyword;
static const string kBestowKeyword;
// used for deck statistics // used for deck statistics
static const int STATS_FOR_TURNS = 8; static const int STATS_FOR_TURNS = 8;
@@ -246,8 +247,11 @@ class Constants
COMBATTOUGHNESS = 125, COMBATTOUGHNESS = 125,
CANTPAYLIFE = 126, CANTPAYLIFE = 126,
CANTBESACRIFIED = 127, CANTBESACRIFIED = 127,
NB_BASIC_ABILITIES = 128, SKULK = 128,
MENACE = 129,
NOSOLO = 130,//cant attack alone
MUSTBLOCK = 131,//blocks each turn
NB_BASIC_ABILITIES = 132,
RARITY_S = 'S', //Special Rarity RARITY_S = 'S', //Special Rarity
RARITY_M = 'M', //Mythics RARITY_M = 'M', //Mythics
@@ -308,6 +312,7 @@ class Constants
CAST_WITH_RETRACE = 6, CAST_WITH_RETRACE = 6,
CAST_WITH_MORPH = 7, CAST_WITH_MORPH = 7,
CAST_WITH_SUSPEND = 8, CAST_WITH_SUSPEND = 8,
CAST_WITH_BESTOW = 9,
CAST_ALTERNATE = -1, //matches all alternate costs, including itself CAST_ALTERNATE = -1, //matches all alternate costs, including itself
CAST_ALL = -2, // matches everything except NOT_CAST CAST_ALL = -2, // matches everything except NOT_CAST
+9
View File
@@ -72,6 +72,14 @@ class MTGGameZone {
OWNER_STACK = 66, OWNER_STACK = 66,
TARGETED_PLAYER_STACK = 67, TARGETED_PLAYER_STACK = 67,
MY_REVEAL = 71,
OPPONENT_REVEAL = 72,
TARGET_OWNER_REVEAL = 73,
TARGET_CONTROLLER_REVEAL = 74,
REVEAL = 75,
OWNER_REVEAL = 76,
TARGETED_PLAYER_REVEAL = 77,
}; };
Player * owner; Player * owner;
@@ -194,6 +202,7 @@ public:
MTGRemovedFromGame * exile; //alias to removedFromZone MTGRemovedFromGame * exile; //alias to removedFromZone
MTGGameZone * garbage; MTGGameZone * garbage;
MTGGameZone * garbageLastTurn; MTGGameZone * garbageLastTurn;
MTGGameZone * reveal;
MTGGameZone * temp; MTGGameZone * temp;
MTGPlayerCards(); MTGPlayerCards();
+15
View File
@@ -206,6 +206,21 @@ public:
virtual MTGOverloadRule * clone() const; virtual MTGOverloadRule * clone() const;
}; };
class MTGBestowRule : public MTGAlternativeCostRule
{
public:
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL);
int reactToClick(MTGCardInstance * card);
virtual ostream& toString(ostream& out) const;
MTGBestowRule(GameObserver* observer, int _id);
const string getMenuText()
{
return "Bestow";
}
virtual MTGBestowRule * clone() const;
};
class MTGSuspendRule: public MTGAlternativeCostRule class MTGSuspendRule: public MTGAlternativeCostRule
{ {
public: public:
+4
View File
@@ -31,6 +31,7 @@ protected:
ManaCost * manaUsedToCast; ManaCost * manaUsedToCast;
ManaCost * morph; ManaCost * morph;
ManaCost * Retrace; ManaCost * Retrace;
ManaCost * Bestow;
ManaCost * FlashBack; ManaCost * FlashBack;
ManaCost * BuyBack; ManaCost * BuyBack;
ManaCost * kicker; ManaCost * kicker;
@@ -75,6 +76,9 @@ public:
ManaCost * getSuspend(){ return suspend; }; ManaCost * getSuspend(){ return suspend; };
void setSuspend(ManaCost * aMana){ SAFE_DELETE(suspend); suspend = aMana;}; void setSuspend(ManaCost * aMana){ SAFE_DELETE(suspend); suspend = aMana;};
ManaCost * getBestow() { return Bestow; };
void setBestow(ManaCost * aMana) { SAFE_DELETE(Bestow); Bestow = aMana; };
ManaCost * getManaUsedToCast(){ return manaUsedToCast; }; ManaCost * getManaUsedToCast(){ return manaUsedToCast; };
void setManaUsedToCast(ManaCost * aMana){ SAFE_DELETE(manaUsedToCast); manaUsedToCast = aMana;}; void setManaUsedToCast(ManaCost * aMana){ SAFE_DELETE(manaUsedToCast); manaUsedToCast = aMana;};
+1
View File
@@ -25,6 +25,7 @@ class TargetChooser: public TargetsList
protected: protected:
int forceTargetListReady; int forceTargetListReady;
public: public:
int forceTargetListReadyByPlayer;
const static int UNLITMITED_TARGETS = 1000; const static int UNLITMITED_TARGETS = 1000;
enum enum
{ {
+4 -4
View File
@@ -1221,7 +1221,7 @@ int AIPlayerBaka::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, Rank
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
Player * p = observer->players[i]; Player * p = observer->players[i];
MTGGameZone * playerZones[] = { p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay,p->game->stack,p->game->exile }; MTGGameZone * playerZones[] = { p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay,p->game->stack,p->game->exile, p->game->reveal };
if(a->getActionTc()->canTarget((Targetable*)p)) if(a->getActionTc()->canTarget((Targetable*)p))
{ {
if(a->getActionTc()->maxtargets == 1) if(a->getActionTc()->maxtargets == 1)
@@ -1352,7 +1352,7 @@ int AIPlayerBaka::selectHintAbility()
int AIPlayerBaka::selectAbility() int AIPlayerBaka::selectAbility()
{ {
if(observer->mExtraPayment && observer->mExtraPayment->source->controller() == this) if(observer->mExtraPayment && observer->mExtraPayment->source && observer->mExtraPayment->source->controller() == this)
{ {
ExtraManaCost * check = NULL; ExtraManaCost * check = NULL;
check = dynamic_cast<ExtraManaCost*>(observer->mExtraPayment->costs[0]); check = dynamic_cast<ExtraManaCost*>(observer->mExtraPayment->costs[0]);
@@ -1560,8 +1560,8 @@ int AIPlayerBaka::chooseTarget(TargetChooser * _tc, Player * forceTarget,MTGCard
} }
} }
MTGPlayerCards * playerZones = target->game; MTGPlayerCards * playerZones = target->game;
MTGGameZone * zones[] = { playerZones->hand, playerZones->library, playerZones->inPlay, playerZones->graveyard,playerZones->stack,playerZones->exile }; MTGGameZone * zones[] = { playerZones->hand, playerZones->library, playerZones->inPlay, playerZones->graveyard,playerZones->stack,playerZones->exile,playerZones->reveal };
for (int j = 0; j < 6; j++) for (int j = 0; j < 7; j++)
{ {
MTGGameZone * zone = zones[j]; MTGGameZone * zone = zones[j];
for (int k = 0; k < zone->nb_cards; k++) for (int k = 0; k < zone->nb_cards; k++)
+6 -3
View File
@@ -77,7 +77,7 @@ void ActionLayer::cleanGarbage()
int ActionLayer::reactToClick(ActionElement * ability, MTGCardInstance * card) int ActionLayer::reactToClick(ActionElement * ability, MTGCardInstance * card)
{ {
int result = ability->reactToClick(card); int result = ability?ability->reactToClick(card):0;
if (result) if (result)
stuffHappened = 1; stuffHappened = 1;
return result; return result;
@@ -186,8 +186,11 @@ void ActionLayer::Update(float dt)
without this, the game locks into a freeze state while you try to select the targets and dont have enough to without this, the game locks into a freeze state while you try to select the targets and dont have enough to
fill the maxtargets list. fill the maxtargets list.
*/ */
if(int(ae->getActionTc()->getNbTargets()) == countTargets-1) if (int(ae->getActionTc()->getNbTargets()) == countTargets)//if the amount of targets is equal the all we can target
ae->getActionTc()->done = true; {
ae->getActionTc()->done = true;//were done
ae->getActionTc()->source->getObserver()->cardClick(ae->getActionTc()->source, 0, false);//click source.
}
} }
} }
} }
+4
View File
@@ -578,6 +578,10 @@ int ActionStack::addAbility(MTGAbility * ability)
if (!observer->players[0]->isAI() && ability->source->controller() == observer->players[0] && 0 if (!observer->players[0]->isAI() && ability->source->controller() == observer->players[0] && 0
== options[Options::INTERRUPTMYABILITIES].number) == options[Options::INTERRUPTMYABILITIES].number)
interruptDecision[0] = DONT_INTERRUPT; interruptDecision[0] = DONT_INTERRUPT;
if (observer->OpenedDisplay && observer->players[0]->game->reveal->cards.size())
{
interruptDecision[0] = DONT_INTERRUPT;
}
return result; return result;
} }
File diff suppressed because it is too large Load Diff
+8
View File
@@ -659,6 +659,14 @@ void CardGui::AlternateRender(MTGCard * card, const Pos& pos)
} }
found = Carditem->mName.find("cardid"); // Write the cardid
if (found != string::npos)
{
stringstream st;
st << card->getMTGId();
formattedfield = FormattedData(formattedfield, "mtgid", st.str());
}
found = Carditem->mName.find("power"); // Write the strength found = Carditem->mName.find("power"); // Write the strength
if (found != string::npos) if (found != string::npos)
{ {
+4 -2
View File
@@ -759,9 +759,10 @@ int TapTargetCost::isPaymentSet()
int TapTargetCost::doPay() int TapTargetCost::doPay()
{ {
MTGCardInstance * _target = (MTGCardInstance *) target; MTGCardInstance * _target = (MTGCardInstance *) target;
source->storedCard = target->createSnapShot();
if (target) if (target)
{ {
source->storedCard = target->createSnapShot();
_target->tap(); _target->tap();
target = NULL; target = NULL;
if (tc) if (tc)
@@ -802,9 +803,10 @@ int UnTapTargetCost::isPaymentSet()
int UnTapTargetCost::doPay() int UnTapTargetCost::doPay()
{ {
MTGCardInstance * _target = (MTGCardInstance *) target; MTGCardInstance * _target = (MTGCardInstance *) target;
source->storedCard = target->createSnapShot();
if (target) if (target)
{ {
source->storedCard = target->createSnapShot();
_target->untap(); _target->untap();
target = NULL; target = NULL;
if (tc) if (tc)
+58 -6
View File
@@ -32,7 +32,8 @@ void GameObserver::cleanup()
SAFE_DELETE(replacementEffects); SAFE_DELETE(replacementEffects);
for (size_t i = 0; i < players.size(); ++i) for (size_t i = 0; i < players.size(); ++i)
{ {
SAFE_DELETE(players[i]); if(players[i])
SAFE_DELETE(players[i]);
} }
players.clear(); players.clear();
@@ -51,6 +52,7 @@ void GameObserver::cleanup()
connectRule = false; connectRule = false;
actionsList.clear(); actionsList.clear();
gameTurn.clear(); gameTurn.clear();
OpenedDisplay = NULL;
} }
GameObserver::~GameObserver() GameObserver::~GameObserver()
@@ -59,7 +61,8 @@ GameObserver::~GameObserver()
for (size_t i = 0; i < players.size(); ++i) for (size_t i = 0; i < players.size(); ++i)
{ {
players[i]->End(); if(players[i])
players[i]->End();
} }
SAFE_DELETE(targetChooser); SAFE_DELETE(targetChooser);
SAFE_DELETE(mLayers); SAFE_DELETE(mLayers);
@@ -67,7 +70,8 @@ GameObserver::~GameObserver()
SAFE_DELETE(replacementEffects); SAFE_DELETE(replacementEffects);
for (size_t i = 0; i < players.size(); ++i) for (size_t i = 0; i < players.size(); ++i)
{ {
SAFE_DELETE(players[i]); if(players[i])
SAFE_DELETE(players[i]);
} }
players.clear(); players.clear();
delete[] ExtraRules; delete[] ExtraRules;
@@ -93,6 +97,7 @@ GameObserver::GameObserver(WResourceManager *output, JGE* input)
targetChooser = NULL; targetChooser = NULL;
cardWaitingForTargets = NULL; cardWaitingForTargets = NULL;
mExtraPayment = NULL; mExtraPayment = NULL;
OpenedDisplay = NULL;
gameOver = NULL; gameOver = NULL;
phaseRing = NULL; phaseRing = NULL;
replacementEffects = NEW ReplacementEffects(); replacementEffects = NEW ReplacementEffects();
@@ -322,7 +327,11 @@ void GameObserver::userRequestNextGamePhase(bool allowInterrupt, bool log)
// Here's what I find weird - if the extra cost is something like a sacrifice, doesn't that imply a TargetChooser? // Here's what I find weird - if the extra cost is something like a sacrifice, doesn't that imply a TargetChooser?
if (WaitForExtraPayment(NULL)) if (WaitForExtraPayment(NULL))
return; return;
/*if (OpenedDisplay)//dont let us fly through all the phases with grave and library box still open.
{
return;//I want this here, but it locks up on opponents turn, we need to come up with a clever way to close opened
//displays, it makes no sense that you travel through 4 or 5 phases with library or grave still open.
}*/
Phase * cPhaseOld = phaseRing->getCurrentPhase(); Phase * cPhaseOld = phaseRing->getCurrentPhase();
if (allowInterrupt && ((cPhaseOld->id == MTG_PHASE_COMBATBLOCKERS && combatStep == ORDER) if (allowInterrupt && ((cPhaseOld->id == MTG_PHASE_COMBATBLOCKERS && combatStep == ORDER)
|| (cPhaseOld->id == MTG_PHASE_COMBATBLOCKERS && combatStep == TRIGGERS) || (cPhaseOld->id == MTG_PHASE_COMBATBLOCKERS && combatStep == TRIGGERS)
@@ -727,12 +736,20 @@ void GameObserver::gameStateBasedEffects()
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
//Remove auras that don't have a valid target anymore// //Remove auras that don't have a valid target anymore//
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
if (card->target && !isInPlay(card->target) && card->isBestowed && card->hasType("aura"))
{
card->removeType("aura");
card->addType("creature");
card->target = NULL;
card->isBestowed = false;
}
if ((card->target||card->playerTarget) && !card->hasType(Subtypes::TYPE_EQUIPMENT)) if ((card->target||card->playerTarget) && !card->hasType(Subtypes::TYPE_EQUIPMENT))
{ {
if(card->target && !isInPlay(card->target)) if(card->target && !isInPlay(card->target))
players[i]->game->putInGraveyard(card); players[i]->game->putInGraveyard(card);
if(card->target && isInPlay(card->target)) if(card->target && isInPlay(card->target))
{ {//what exactly does this section do?
if(card->spellTargetType.find("creature") != string::npos && !card->target->hasType("creature")) if(card->spellTargetType.find("creature") != string::npos && !card->target->hasType("creature"))
players[i]->game->putInGraveyard(card); players[i]->game->putInGraveyard(card);
if(card->spellTargetType.find("artifact") != string::npos && !card->target->hasType("artifact")) if(card->spellTargetType.find("artifact") != string::npos && !card->target->hasType("artifact"))
@@ -1029,9 +1046,41 @@ void GameObserver::Affinity()
if (!card) if (!card)
continue; continue;
bool NewAffinityFound = false;
for (unsigned int na = 0; na < card->cardsAbilities.size(); na++)
{
if (!card->cardsAbilities[na])
break;
ANewAffinity * newAff = dynamic_cast<ANewAffinity*>(card->cardsAbilities[na]);
if (newAff)
{
NewAffinityFound = true;
}
}
bool DoReduceIncrease = false;
if (card->has(Constants::AFFINITYARTIFACTS) ||
card->has(Constants::AFFINITYFOREST) ||
card->has(Constants::AFFINITYGREENCREATURES) ||
card->has(Constants::AFFINITYISLAND) ||
card->has(Constants::AFFINITYMOUNTAIN) ||
card->has(Constants::AFFINITYPLAINS) ||
card->has(Constants::AFFINITYSWAMP) ||
card->has(Constants::TRINISPHERE) ||
card->getIncreasedManaCost()->getConvertedCost() ||
card->getReducedManaCost()->getConvertedCost() ||
NewAffinityFound)
DoReduceIncrease = true;
if (!DoReduceIncrease)
continue;
//above we check if there are even any cards that effect cards manacost
//if there are none, leave this function. manacost->copy( is a very expensive funtion
//1mb a sec to run at all time even when no known reducers or increasers are in play.
//memory snapshot shots pointed to this as such a heavy load that games with many cards inplay
//would slow to a crawl.
//only do any of the following if a card with the stated ability is in your hand.
int color = 0; int color = 0;
string type = ""; string type = "";
//only do any of the following if a card with the stated ability is in your hand.
ManaCost * original = NEW ManaCost(); ManaCost * original = NEW ManaCost();
original->copy(card->model->data->getManaCost()); original->copy(card->model->data->getManaCost());
if(card->getIncreasedManaCost()->getConvertedCost()||card->getReducedManaCost()->getConvertedCost()) if(card->getIncreasedManaCost()->getConvertedCost()||card->getReducedManaCost()->getConvertedCost())
@@ -1054,6 +1103,8 @@ void GameObserver::Affinity()
bool resetCost = false; bool resetCost = false;
for(unsigned int na = 0; na < card->cardsAbilities.size();na++) for(unsigned int na = 0; na < card->cardsAbilities.size();na++)
{//start2 {//start2
if (!card->cardsAbilities[na])
break;
ANewAffinity * newAff = dynamic_cast<ANewAffinity*>(card->cardsAbilities[na]); ANewAffinity * newAff = dynamic_cast<ANewAffinity*>(card->cardsAbilities[na]);
if(newAff) if(newAff)
{ {
@@ -1372,6 +1423,7 @@ int GameObserver::cardClick(MTGCardInstance * card, Targetable * object, bool lo
int _result = targetChooser->ForceTargetListReady(); int _result = targetChooser->ForceTargetListReady();
if(targetChooser->targetMin && int(targetChooser->getNbTargets()) < targetChooser->maxtargets) if(targetChooser->targetMin && int(targetChooser->getNbTargets()) < targetChooser->maxtargets)
_result = 0; _result = 0;
if (_result) if (_result)
{ {
result = TARGET_OK_FULL; result = TARGET_OK_FULL;
+2 -1
View File
@@ -48,7 +48,8 @@ void GameStateOptions::Start()
} }
optionsList->Add(NEW OptionInteger(Options::INTERRUPT_SECONDS, "Seconds to pause for an Interrupt", 20, 1)); optionsList->Add(NEW OptionInteger(Options::INTERRUPT_SECONDS, "Seconds to pause for an Interrupt", 20, 1));
optionsList->Add(NEW OptionInteger(Options::INTERRUPTMYSPELLS, "Interrupt my spells")); optionsList->Add(NEW OptionInteger(Options::INTERRUPTMYSPELLS, "Interrupt my spells"));
optionsList->Add(NEW OptionInteger(Options::INTERRUPTMYABILITIES, "Interrupt my abilities")); // optionsList->Add(NEW OptionInteger(Options::INTERRUPTMYABILITIES, "Interrupt my abilities"));
//this is a dev option, not meant for standard play. uncomment if you need to see abilities you own hitting the stack.
optionsList->Add(NEW OptionInteger(Options::INTERRUPT_SECONDMAIN, "Interrupt opponent's end of turn")); optionsList->Add(NEW OptionInteger(Options::INTERRUPT_SECONDMAIN, "Interrupt opponent's end of turn"));
optionsTabs = NEW WGuiTabMenu(); optionsTabs = NEW WGuiTabMenu();
optionsTabs->Add(optionsList); optionsTabs->Add(optionsList);
+7 -3
View File
@@ -149,12 +149,16 @@ ostream& GuiAvatar::toString(ostream& out) const
void GuiGameZone::toggleDisplay() void GuiGameZone::toggleDisplay()
{ {
if (showCards) if (showCards)
showCards = 0; {
else showCards = 0;
cd->zone->owner->getObserver()->OpenedDisplay = NULL;
}
else if(!cd->zone->owner->getObserver()->OpenedDisplay)//one display at a time please.
{ {
showCards = 1; showCards = 1;
cd->init(zone); cd->init(zone);
cd->zone->owner->getObserver()->OpenedDisplay = cd;
} }
} }
+173 -30
View File
@@ -19,8 +19,8 @@
const string kLordKeywords[] = { "lord(", "foreach(", "aslongas(", "teach(", "all(" }; const string kLordKeywords[] = { "lord(", "foreach(", "aslongas(", "teach(", "all(" };
const size_t kLordKeywordsCount = 5; const size_t kLordKeywordsCount = 5;
const string kThisKeywords[] = { "this(", "thisforeach(" }; const string kThisKeywords[] = { "this(", "thisforeach(","while(", };
const size_t kThisKeywordsCount = 2; const size_t kThisKeywordsCount = 3;
// Used for the maxCast/maxPlay ability parsing // Used for the maxCast/maxPlay ability parsing
@@ -353,6 +353,24 @@ int AbilityFactory::parseCastRestrictions(MTGCardInstance * card, Player * playe
return 0; return 0;
} }
check = restriction[i].find("delirium");
if (check != string::npos)
{
Player * checkCurrent = card->controller();
MTGGameZone * grave = checkCurrent->game->graveyard;
int checkTypesAmount = 0;
if(grave->hasType("creature")) checkTypesAmount++;
if (grave->hasType("enchantment")) checkTypesAmount++;
if (grave->hasType("sorcery")) checkTypesAmount++;
if (grave->hasType("instant")) checkTypesAmount++;
if (grave->hasType("land")) checkTypesAmount++;
if (grave->hasType("artifact")) checkTypesAmount++;
if (grave->hasType("planeswalker")) checkTypesAmount++;
if (checkTypesAmount < 4)
return 0;
}
check = restriction[i].find("miracle"); check = restriction[i].find("miracle");
if(check != string::npos) if(check != string::npos)
{ {
@@ -362,6 +380,13 @@ int AbilityFactory::parseCastRestrictions(MTGCardInstance * card, Player * playe
return 0; return 0;
} }
check = restriction[i].find("madnessplayed");
if (check != string::npos)
{
if (card->previous && !card->previous->MadnessPlay)
return 0;
}
check = restriction[i].find("prowl"); check = restriction[i].find("prowl");
if(check != string::npos) if(check != string::npos)
{ {
@@ -437,6 +462,13 @@ int AbilityFactory::parseCastRestrictions(MTGCardInstance * card, Player * playe
return 0; return 0;
} }
check = restriction[i].find("geared");
if (check != string::npos)
{
if (card->equipment < 1)
return 0;
}
check = restriction[i].find("raid"); check = restriction[i].find("raid");
if(check != string::npos) if(check != string::npos)
{ {
@@ -1139,6 +1171,13 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
observer->addObserver(NEW MTGFlashBackRule(observer, -1)); observer->addObserver(NEW MTGFlashBackRule(observer, -1));
return NULL; return NULL;
} }
//alternative cost type flashback
found = s.find("bestowrule");
if (found != string::npos)
{
observer->addObserver(NEW MTGBestowRule(observer, -1));
return NULL;
}
//alternative cost type retrace //alternative cost type retrace
found = s.find("retracerule"); found = s.find("retracerule");
if(found != string::npos) if(found != string::npos)
@@ -1306,19 +1345,46 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
//actual abilities, this is a limitation. //actual abilities, this is a limitation.
string unchangedS = ""; string unchangedS = "";
unchangedS.append(s); unchangedS.append(s);
found = s.find("pay(");
if (found != string::npos && storedPayString.empty()) //Reveal:x remove the core so we dont build them prematurely
{ vector<string>transPayfound = parseBetween(s, "newability[pay(", " ");
vector<string> splitMayPaystr = parseBetween(s, "pay(", ")", true); vector<string>transfound = parseBetween(s,"newability[reveal:"," ");//if we are using reveal inside a newability, let transforms remove the string instead.
if(splitMayPaystr.size()) vector<string>abilfound = parseBetween(s, "ability$!name(reveal) reveal:", " ");
{ if(!abilfound.size())
storedPayString.append(splitMayPaystr[2]); abilfound = parseBetween(s, "ability$!reveal:", " ");//see above. this allows us to nest reveals inside these 2 other master classes. while also allowing us to nest them inside reveals.
s = splitMayPaystr[0];
s.append("pay("); found = s.find("pay(");
s.append(splitMayPaystr[1]); if (found != string::npos && storedPayString.empty() && !transPayfound.size())
s.append(")"); {
} vector<string> splitMayPaystr = parseBetween(s, "pay(", ")", true);
} if (splitMayPaystr.size())
{
storedPayString.append(splitMayPaystr[2]);
s = splitMayPaystr[0];
s.append("pay(");
s.append(splitMayPaystr[1]);
s.append(")");
}
}
vector<string> splitRevealx = parseBetween(s, "reveal:", " revealend", false);
if (!abilfound.size() && !transfound.size() && splitRevealx.size() && storedAbilityString.empty())
{
storedAbilityString = splitRevealx[1];
s = splitRevealx[0];
s.append("reveal: ");
s.append(splitRevealx[2]);
}
vector<string> splitScryx = parseBetween(s, "scry:", " scryend", false);
if (splitScryx.size() && storedAbilityString.empty())
{
storedAbilityString = splitScryx[1];
s = splitScryx[0];
s.append("scry: ");
s.append(splitScryx[2]);
}
found = s.find("transforms(("); found = s.find("transforms((");
if (found != string::npos && storedString.empty()) if (found != string::npos && storedString.empty())
{ {
@@ -1750,15 +1816,25 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
} }
if (end != string::npos) if (end != string::npos)
{ {
ThisDescriptor * td = NULL;
string thisDescriptorString = s.substr(found + header, end - found - header); string thisDescriptorString = s.substr(found + header, end - found - header);
ThisDescriptorFactory tdf; vector<string> splitRest = parseBetween(s, "restriction{", "}");
ThisDescriptor * td = tdf.createThisDescriptor(observer, thisDescriptorString); if (splitRest.size())
{
if (!td)
{ }
DebugTrace("MTGABILITY: Parsing Error:" << s); else
return NULL; {
} ThisDescriptorFactory tdf;
td = tdf.createThisDescriptor(observer, thisDescriptorString);
if (!td)
{
DebugTrace("MTGABILITY: Parsing Error:" << s);
return NULL;
}
}
MTGAbility * a = parseMagicLine(s1, id, spell, card, 0, activated); MTGAbility * a = parseMagicLine(s1, id, spell, card, 0, activated);
if (!a) if (!a)
@@ -1795,6 +1871,9 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
case 1: case 1:
result = NEW AThisForEach(observer, id, card, _target, td, a); result = NEW AThisForEach(observer, id, card, _target, td, a);
break; break;
case 2:
result = NEW AThis(observer, id, card, _target, NULL, a, thisDescriptorString);
break;
default: default:
result = NULL; result = NULL;
} }
@@ -1986,7 +2065,6 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
return NEW APaired(observer,id, card,card->myPair,a); return NEW APaired(observer,id, card,card->myPair,a);
return NULL; return NULL;
} }
//mana of the listed type doesnt get emptied from the pools. //mana of the listed type doesnt get emptied from the pools.
vector<string>colorType = parseBetween(s,"poolsave(",")",false); vector<string>colorType = parseBetween(s,"poolsave(",")",false);
if (colorType.size()) if (colorType.size())
@@ -2272,6 +2350,18 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
string tokenDesc = splitToken[1]; string tokenDesc = splitToken[1];
vector<string> tokenParameters = split(tokenDesc, ','); vector<string> tokenParameters = split(tokenDesc, ',');
//lets try finding a token by card name.
if (splitToken[1].size() && tokenParameters.size() ==1)
{
string cardName = splitToken[1];
MTGCard * safetycard = MTGCollection()->getCardByName(cardName);
if (safetycard) //lets try constructing it then,we didnt find it by name
{
ATokenCreator * tok = NEW ATokenCreator(observer, id, card, target, NULL, cardName, starfound, multiplier, who);
tok->oneShot = 1;
return tok;
}
}
if (tokenParameters.size() < 3) if (tokenParameters.size() < 3)
{ {
DebugTrace("incorrect Parameters for Token" << tokenDesc); DebugTrace("incorrect Parameters for Token" << tokenDesc);
@@ -2474,6 +2564,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
bool withRestrictions = splitCastCard[1].find("restricted") != string::npos; bool withRestrictions = splitCastCard[1].find("restricted") != string::npos;
bool asCopy = splitCastCard[1].find("copied") != string::npos; bool asCopy = splitCastCard[1].find("copied") != string::npos;
bool asNormal = splitCastCard[1].find("normal") != string::npos; bool asNormal = splitCastCard[1].find("normal") != string::npos;
bool asNormalMadness = splitCastCard[1].find("madness") != string::npos;
bool sendNoEvent = splitCastCard[1].find("noevent") != string::npos; bool sendNoEvent = splitCastCard[1].find("noevent") != string::npos;
bool putinplay = splitCastCard[1].find("putinplay") != string::npos; bool putinplay = splitCastCard[1].find("putinplay") != string::npos;
string nameCard = ""; string nameCard = "";
@@ -2485,7 +2576,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
nameCard = splitCastName[1]; nameCard = splitCastName[1];
} }
} }
MTGAbility *a = NEW AACastCard(observer, id, card, target,withRestrictions,asCopy,asNormal,nameCard,newName,sendNoEvent,putinplay); MTGAbility *a = NEW AACastCard(observer, id, card, target,withRestrictions,asCopy,asNormal,nameCard,newName,sendNoEvent,putinplay, asNormalMadness);
a->oneShot = false; a->oneShot = false;
if(splitCastCard[1].find("trigger[to]") != string::npos) if(splitCastCard[1].find("trigger[to]") != string::npos)
{ {
@@ -2933,6 +3024,16 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
return a; return a;
} }
//bestow
found = s.find("bstw");
if (found != string::npos)
{
MTGAbility * a = NEW ABestow(observer, id, card, target);
a->oneShot = 1;
return a;
}
//no counters on target of optional type //no counters on target of optional type
vector<string> splitCounterShroud = parseBetween(s, "countershroud(", ")"); vector<string> splitCounterShroud = parseBetween(s, "countershroud(", ")");
if (splitCounterShroud.size()) if (splitCounterShroud.size())
@@ -3122,6 +3223,30 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
} }
//Reveal:x (activate aility)
vector<string> splitReveal = parseBetween(s, "reveal:", "revealend", false);
if (splitReveal.size())
{
string backup = storedAbilityString;
storedAbilityString = "";//we clear the string here for cards that contain more than 1 reveal.
GenericRevealAbility * a = NEW GenericRevealAbility(observer, id, card, target, backup);
a->oneShot = 1;
a->canBeInterrupted = false;
return a;
}
//scry:x (activate aility)
vector<string> splitScry = parseBetween(s, "scry:", "scryend", false);
if (splitScry.size())
{
string backup = storedAbilityString;
storedAbilityString = "";//we clear the string here for cards that contain more than 1 reveal.
GenericScryAbility * a = NEW GenericScryAbility(observer, id, card, target, backup);
a->oneShot = 1;
a->canBeInterrupted = false;
return a;
}
//flip //flip
vector<string> splitFlipStat = parseBetween(s, "flip(", ")", true); vector<string> splitFlipStat = parseBetween(s, "flip(", ")", true);
if(splitFlipStat.size()) if(splitFlipStat.size())
@@ -3291,11 +3416,20 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
found = s.find("frozen"); found = s.find("frozen");
if (found != string::npos) if (found != string::npos)
{ {
MTGAbility * a = NEW AAFrozen(observer, id, card, target); MTGAbility * a = NEW AAFrozen(observer, id, card, target,false);
a->oneShot = 1; a->oneShot = 1;
return a; return a;
} }
//frozen, next untap this does not untap.
found = s.find("freeze");
if (found != string::npos)
{
MTGAbility * a = NEW AAFrozen(observer, id, card, target,true);
a->oneShot = 1;
return a;
}
//get a new target - retarget and newtarget makes the card refreshed - from exile to play... //get a new target - retarget and newtarget makes the card refreshed - from exile to play...
if ((s.find("retarget") != string::npos) || s.find("newtarget") != string::npos) if ((s.find("retarget") != string::npos) || s.find("newtarget") != string::npos)
{ {
@@ -3330,6 +3464,14 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
return a; return a;
} }
vector<string> splitCountObject = parseBetween(s, "count(", ")", false);
if (splitCountObject.size())
{
MTGAbility * a = NEW AACountObject(observer, id, card, card, NULL, splitCountObject[1]);
a->oneShot = 1;
return a;
}
//switch targest power with toughness //switch targest power with toughness
found = s.find("swap"); found = s.find("swap");
if (found != string::npos) if (found != string::npos)
@@ -4625,6 +4767,7 @@ MTGAbility::MTGAbility(const MTGAbility& a): ActionElement(a)
BuyBack = a.BuyBack; //? NEW ManaCost(a.BuyBack) : NULL; BuyBack = a.BuyBack; //? NEW ManaCost(a.BuyBack) : NULL;
FlashBack = a.FlashBack; // ? NEW ManaCost(a.FlashBack) : NULL; FlashBack = a.FlashBack; // ? NEW ManaCost(a.FlashBack) : NULL;
Retrace = a.Retrace;// ? NEW ManaCost(a.Retrace) : NULL; Retrace = a.Retrace;// ? NEW ManaCost(a.Retrace) : NULL;
Bestow = a.Bestow;
morph = a.morph; //? NEW ManaCost(a.morph) : NULL; morph = a.morph; //? NEW ManaCost(a.morph) : NULL;
suspend = a.suspend;// ? NEW ManaCost(a.suspend) : NULL; suspend = a.suspend;// ? NEW ManaCost(a.suspend) : NULL;
@@ -5101,7 +5244,7 @@ int TargetAbility::reactToClick(MTGCardInstance * card)
} }
else else
{ {
if (tc->toggleTarget(card) == TARGET_OK_FULL) if (tc->toggleTarget(card) == TARGET_OK_FULL && tc->targetsReadyCheck() == TARGET_OK_FULL)
{ {
int result = ActivatedAbility::reactToClick(source); int result = ActivatedAbility::reactToClick(source);
if (result) if (result)
@@ -5360,8 +5503,8 @@ void ListMaintainerAbility::updateTargets()
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
Player * p = game->players[i]; Player * p = game->players[i];
MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->stack, p->game->exile }; MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->stack, p->game->exile ,p->game->reveal };
for (int k = 0; k < 6; k++) for (int k = 0; k < 7; k++)
{ {
MTGGameZone * zone = zones[k]; MTGGameZone * zone = zones[k];
if (canTarget(zone)) if (canTarget(zone))
@@ -5432,8 +5575,8 @@ void ListMaintainerAbility::checkTargets()
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
Player * p = game->players[i]; Player * p = game->players[i];
MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->stack, p->game->exile }; MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->stack, p->game->exile, p->game->reveal };
for (int k = 0; k < 6; k++) for (int k = 0; k < 7; k++)
{ {
MTGGameZone * zone = zones[k]; MTGGameZone * zone = zones[k];
if (canTarget(zone)) if (canTarget(zone))
+14 -3
View File
@@ -69,6 +69,8 @@ MTGCardInstance::MTGCardInstance(MTGCard * card, MTGPlayerCards * arg_belongs_to
cardistargetted = 0; cardistargetted = 0;
cardistargetter = 0; cardistargetter = 0;
myconvertedcost = getManaCost()->getConvertedCost(); myconvertedcost = getManaCost()->getConvertedCost();
revealedLast = NULL;
MadnessPlay = false;
} }
MTGCardInstance * MTGCardInstance::createSnapShot() MTGCardInstance * MTGCardInstance::createSnapShot()
@@ -194,6 +196,7 @@ void MTGCardInstance::initMTGCI()
wasDealtDamage = false; wasDealtDamage = false;
isDualWielding = false; isDualWielding = false;
suspended = false; suspended = false;
isBestowed = false;
castMethod = Constants::NOT_CAST; castMethod = Constants::NOT_CAST;
mPropertiesChangedSinceLastUpdate = false; mPropertiesChangedSinceLastUpdate = false;
stillNeeded = true; stillNeeded = true;
@@ -222,6 +225,7 @@ void MTGCardInstance::initMTGCI()
imprintW = 0; imprintW = 0;
currentimprintName = ""; currentimprintName = "";
imprintedNames.clear(); imprintedNames.clear();
CountedObjects = 0;
for (int i = 0; i < ManaCost::MANA_PAID_WITH_SUSPEND +1; i++) for (int i = 0; i < ManaCost::MANA_PAID_WITH_SUSPEND +1; i++)
alternateCostPaid[i] = 0; alternateCostPaid[i] = 0;
@@ -789,6 +793,9 @@ bool MTGCardInstance::StackIsEmptyandSorcerySpeed()
//check targetted? //check targetted?
bool MTGCardInstance::isTargetted() bool MTGCardInstance::isTargetted()
{ {
if(controller()->game->reveal->cards.size() || controller()->opponent()->game->reveal->cards.size())
return false;
if(getObserver()->mLayers->stackLayer()->count(0, NOT_RESOLVED) != 0) if(getObserver()->mLayers->stackLayer()->count(0, NOT_RESOLVED) != 0)
{ {
ActionStack * stack = observer->mLayers->stackLayer(); ActionStack * stack = observer->mLayers->stackLayer();
@@ -814,6 +821,9 @@ bool MTGCardInstance::isTargetted()
//check targetter? //check targetter?
bool MTGCardInstance::isTargetter() bool MTGCardInstance::isTargetter()
{ {
if(controller()->game->reveal->cards.size() || controller()->opponent()->game->reveal->cards.size())
return false;
if(getObserver()->mLayers->stackLayer()->count(0, NOT_RESOLVED) != 0) if(getObserver()->mLayers->stackLayer()->count(0, NOT_RESOLVED) != 0)
{ {
ActionStack * stack = observer->mLayers->stackLayer(); ActionStack * stack = observer->mLayers->stackLayer();
@@ -870,7 +880,7 @@ int MTGCardInstance::canBlock(MTGCardInstance * opponent)
return 0; return 0;
if (opponent->basicAbilities[(int)Constants::ONEBLOCKER] && opponent->blocked) if (opponent->basicAbilities[(int)Constants::ONEBLOCKER] && opponent->blocked)
return 0; return 0;
if(opponent->basicAbilities[(int)Constants::EVADEBIGGER] && power > opponent->power) if((opponent->basicAbilities[(int)Constants::EVADEBIGGER]|| opponent->basicAbilities[(int)Constants::SKULK]) && power > opponent->power)
return 0; return 0;
if(opponent->basicAbilities[(int)Constants::STRONG] && power < opponent->power) if(opponent->basicAbilities[(int)Constants::STRONG] && power < opponent->power)
return 0; return 0;
@@ -1035,7 +1045,6 @@ ManaCost * MTGCardInstance::computeNewCost(MTGCardInstance * card,ManaCost * new
if(newCost->getCost(color) > 0) if(newCost->getCost(color) > 0)
newCost->remove(color,1); newCost->remove(color,1);
}//end3 }//end3
SAFE_DELETE(original);
if(!noTrinisphere) if(!noTrinisphere)
{ {
@@ -1058,6 +1067,8 @@ ManaCost * MTGCardInstance::computeNewCost(MTGCardInstance * card,ManaCost * new
} }
} }
SAFE_DELETE(original);
return newCost; return newCost;
} }
@@ -1266,7 +1277,7 @@ int MTGCardInstance::setDefenser(MTGCardInstance * opponent)
if (defenser) if (defenser)
{ {
if (observer->players[0]->game->battlefield->hasCard(defenser) || observer->players[1]->game->battlefield->hasCard(defenser)) if (observer->players[0]->game->battlefield->hasCard(defenser) || observer->players[1]->game->battlefield->hasCard(defenser))
{ {//remove blocker "this" from the attackers list of blockers.
defenser->removeBlocker(this); defenser->removeBlocker(this);
} }
} }
+12 -1
View File
@@ -105,8 +105,19 @@ int MTGAllCards::processConfLine(string &s, MTGCard *card, CardPrimitive * primi
} }
break; break;
case 'b': //buyback case 'b': //buyback/Bestow
if (!primitive) primitive = NEW CardPrimitive(); if (!primitive) primitive = NEW CardPrimitive();
if (key[1] == 'e' && key[2] == 's')
{ //bestow
if (!primitive) primitive = NEW CardPrimitive();
if (ManaCost * cost = primitive->getManaCost())
{
string value = val;
std::transform(value.begin(), value.end(), value.begin(), ::tolower);
cost->setBestow(ManaCost::parseManaCost(value));
}
}
else//buyback
if (ManaCost * cost = primitive->getManaCost()) if (ManaCost * cost = primitive->getManaCost())
{ {
string value = val; string value = val;
+6 -1
View File
@@ -26,6 +26,7 @@ const string Constants::kFlashBackKeyword = "flashback";
const string Constants::kRetraceKeyword = "retrace"; const string Constants::kRetraceKeyword = "retrace";
const string Constants::kKickerKeyword = "kicker"; const string Constants::kKickerKeyword = "kicker";
const string Constants::kMorphKeyword = "facedown"; const string Constants::kMorphKeyword = "facedown";
const string Constants::kBestowKeyword = "bestow";
int Constants::NB_Colors = 0; //Store the Max number of colors. int Constants::NB_Colors = 0; //Store the Max number of colors.
@@ -157,7 +158,11 @@ const char* Constants::MTGBasicAbilities[] = {
"cantchangelife", "cantchangelife",
"combattoughness", "combattoughness",
"cantpaylife", "cantpaylife",
"cantbesacrified" "cantbesacrified",
"skulk",
"menace",
"nosolo",
"mustblock"
}; };
map<string,int> Constants::MTGBasicAbilitiesMap; map<string,int> Constants::MTGBasicAbilitiesMap;
+1
View File
@@ -9,6 +9,7 @@ MTGGamePhase::MTGGamePhase(GameObserver* g, int id) :
animation = 0; animation = 0;
currentState = -1; currentState = -1;
mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT); mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT);
if(mFont)
mFont->SetBase(0); // using 2nd font mFont->SetBase(0); // using 2nd font
} }
+41 -2
View File
@@ -74,6 +74,7 @@ MTGPlayerCards::~MTGPlayerCards()
SAFE_DELETE(stack); SAFE_DELETE(stack);
SAFE_DELETE(removedFromGame); SAFE_DELETE(removedFromGame);
SAFE_DELETE(garbage); SAFE_DELETE(garbage);
SAFE_DELETE(reveal);
SAFE_DELETE(temp); SAFE_DELETE(temp);
SAFE_DELETE(playRestrictions); SAFE_DELETE(playRestrictions);
} }
@@ -91,6 +92,7 @@ void MTGPlayerCards::beforeBeginPhase()
stack->beforeBeginPhase(); stack->beforeBeginPhase();
removedFromGame->beforeBeginPhase(); removedFromGame->beforeBeginPhase();
garbage->beforeBeginPhase(); garbage->beforeBeginPhase();
reveal->beforeBeginPhase();
temp->beforeBeginPhase(); temp->beforeBeginPhase();
} }
@@ -105,6 +107,7 @@ void MTGPlayerCards::setOwner(Player * player)
stack->setOwner(player); stack->setOwner(player);
garbage->setOwner(player); garbage->setOwner(player);
garbageLastTurn->setOwner(player); garbageLastTurn->setOwner(player);
reveal->setOwner(player);
temp->setOwner(player); temp->setOwner(player);
} }
@@ -272,6 +275,7 @@ void MTGPlayerCards::init()
exile = removedFromGame; exile = removedFromGame;
garbage = NEW MTGGameZone(); garbage = NEW MTGGameZone();
garbageLastTurn = garbage; garbageLastTurn = garbage;
reveal = NEW MTGGameZone();
temp = NEW MTGGameZone(); temp = NEW MTGGameZone();
playRestrictions = NEW PlayRestrictions(); playRestrictions = NEW PlayRestrictions();
@@ -360,6 +364,12 @@ MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone
to = g->players[i]->game->exile; to = g->players[i]->game->exile;
} }
} }
//all cards that go from the hand to the graveyard is ALWAYS a discard.
if ((to == g->players[0]->game->graveyard || to == g->players[1]->game->graveyard) && (from == g->players[0]->game->hand || from
== g->players[1]->game->hand))
{
card->discarded = true;
}
//When a card is moved from inPlay to inPlay (controller change, for example), it is still the same object //When a card is moved from inPlay to inPlay (controller change, for example), it is still the same object
if ((to == g->players[0]->game->inPlay || to == g->players[1]->game->inPlay) && (from == g->players[0]->game->inPlay || from if ((to == g->players[0]->game->inPlay || to == g->players[1]->game->inPlay) && (from == g->players[0]->game->inPlay || from
== g->players[1]->game->inPlay)) == g->players[1]->game->inPlay))
@@ -371,6 +381,7 @@ MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone
if (!(copy = from->removeCard(card, doCopy))) if (!(copy = from->removeCard(card, doCopy)))
return NULL; //ERROR return NULL; //ERROR
if (card->miracle) if (card->miracle)
{ {
copy->miracle = true; copy->miracle = true;
@@ -435,11 +446,12 @@ MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone
previous->next = NULL; previous->next = NULL;
SAFE_DELETE(previous); SAFE_DELETE(previous);
} }
} }
if(!asCopy) if(!asCopy)
{ {
if(shufflelibrary) if(shufflelibrary)
copy->owner->game->library->shuffle(); copy->owner->game->library->shuffle();//shouldnt we only ever do this if you clicked close on your library gui??????
WEvent * e = NEW WEventZoneChange(copy, from, to); WEvent * e = NEW WEventZoneChange(copy, from, to);
g->receiveEvent(e); g->receiveEvent(e);
@@ -995,6 +1007,14 @@ MTGGameZone * MTGGameZone::intToZone(int zoneId, Player * p, Player * p2)
return p->opponent()->game->stack; return p->opponent()->game->stack;
case STACK: case STACK:
return p->game->stack; return p->game->stack;
case MY_REVEAL:
return p->game->reveal;
case OPPONENT_REVEAL:
return p->opponent()->game->reveal;
case REVEAL:
return p->game->reveal;
} }
if (!p2) return NULL; if (!p2) return NULL;
switch (zoneId) switch (zoneId)
@@ -1017,6 +1037,9 @@ MTGGameZone * MTGGameZone::intToZone(int zoneId, Player * p, Player * p2)
case TARGET_CONTROLLER_STACK: case TARGET_CONTROLLER_STACK:
return p2->game->stack; return p2->game->stack;
case TARGET_CONTROLLER_REVEAL:
return p2->game->reveal;
default: default:
return NULL; return NULL;
} }
@@ -1114,6 +1137,18 @@ MTGGameZone * MTGGameZone::intToZone(GameObserver *g, int zoneId, MTGCardInstanc
if(source->playerTarget) if(source->playerTarget)
return source->playerTarget->game->stack; return source->playerTarget->game->stack;
else return source->controller()->game->stack; else return source->controller()->game->stack;
case TARGET_OWNER_REVEAL:
return target->owner->game->reveal;
case REVEAL:
return target->owner->game->reveal;
case OWNER_REVEAL:
return target->owner->game->reveal;
case TARGETED_PLAYER_REVEAL:
if (source->playerTarget)
return source->playerTarget->game->reveal;
else return source->controller()->game->reveal;
default: default:
return NULL; return NULL;
} }
@@ -1141,6 +1176,8 @@ int MTGGameZone::zoneStringToId(string zoneName)
"mystack", "opponentstack", "targetownerstack", "targetcontrollerstack", "ownerstack", "stack","targetedpersonsstack", "mystack", "opponentstack", "targetownerstack", "targetcontrollerstack", "ownerstack", "stack","targetedpersonsstack",
"myreveal", "opponentreveal", "targetownerreveal", "targetcontrollerreveal", "ownerreveal", "reveal","targetedpersonsreveal",
}; };
int values[] = { MY_GRAVEYARD, OPPONENT_GRAVEYARD, TARGET_OWNER_GRAVEYARD, TARGET_CONTROLLER_GRAVEYARD, OWNER_GRAVEYARD, int values[] = { MY_GRAVEYARD, OPPONENT_GRAVEYARD, TARGET_OWNER_GRAVEYARD, TARGET_CONTROLLER_GRAVEYARD, OWNER_GRAVEYARD,
@@ -1160,7 +1197,9 @@ int MTGGameZone::zoneStringToId(string zoneName)
MY_EXILE, OPPONENT_EXILE, TARGET_OWNER_EXILE, TARGET_CONTROLLER_EXILE, OWNER_EXILE, EXILE,TARGETED_PLAYER_EXILE, MY_EXILE, OPPONENT_EXILE, TARGET_OWNER_EXILE, TARGET_CONTROLLER_EXILE, OWNER_EXILE, EXILE,TARGETED_PLAYER_EXILE,
MY_STACK, OPPONENT_STACK, TARGET_OWNER_STACK, TARGET_CONTROLLER_STACK, OWNER_STACK, STACK,TARGETED_PLAYER_STACK }; MY_STACK, OPPONENT_STACK, TARGET_OWNER_STACK, TARGET_CONTROLLER_STACK, OWNER_STACK, STACK,TARGETED_PLAYER_STACK,
MY_REVEAL, OPPONENT_REVEAL, TARGET_OWNER_REVEAL, TARGET_CONTROLLER_REVEAL, OWNER_REVEAL, REVEAL,TARGETED_PLAYER_REVEAL };
int max = sizeof(values) / sizeof *(values); int max = sizeof(values) / sizeof *(values);
+136 -4
View File
@@ -367,9 +367,7 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card)
return 0; return 0;
Player * player = game->currentlyActing(); Player * player = game->currentlyActing();
ManaCost * cost = card->getManaCost(); ManaCost * cost = card->getManaCost();
//this handles extra cost payments at the moment a card is played. //this handles extra cost payments at the moment a card is played.
if (cost->isExtraPaymentSet()) if (cost->isExtraPaymentSet())
{ {
if (!game->targetListIsSet(card)) if (!game->targetListIsSet(card))
@@ -497,6 +495,9 @@ int MTGKickerRule::isReactingToClick(MTGCardInstance * card, ManaCost *)
ManaCost * withKickerCost= NEW ManaCost(card->getManaCost()); ManaCost * withKickerCost= NEW ManaCost(card->getManaCost());
withKickerCost->add(card->getManaCost()->getKicker()); withKickerCost->add(card->getManaCost()->getKicker());
//cost reduction/recalculation must be here or outside somehow... //cost reduction/recalculation must be here or outside somehow...
//no recalculations beyound this point, reactToClick is the function that
//happens only with the assumption that you could actually pay for it, any calculations after will
//have negitive effects. this function is basically "can i play this card?"
#ifdef WIN32 #ifdef WIN32
withKickerCost->Dump(); withKickerCost->Dump();
#endif #endif
@@ -532,7 +533,7 @@ int MTGKickerRule::reactToClick(MTGCardInstance * card)
ManaCost * previousManaPool = NEW ManaCost(player->getManaPool()); ManaCost * previousManaPool = NEW ManaCost(player->getManaPool());
int payResult = player->getManaPool()->pay(card->getManaCost()); int payResult = player->getManaPool()->pay(card->getManaCost());
if (card->getManaCost()->getKicker()) if (card->getManaCost()->getKicker())
{ //cost reduction/recalculation must be here or outside somehow... {
ManaCost * withKickerCost= NEW ManaCost(card->getManaCost()); ManaCost * withKickerCost= NEW ManaCost(card->getManaCost());
withKickerCost->add(withKickerCost->getKicker()); withKickerCost->add(withKickerCost->getKicker());
if (card->getManaCost()->getKicker()->isMulti) if (card->getManaCost()->getKicker()->isMulti)
@@ -1345,7 +1346,68 @@ MTGOverloadRule * MTGOverloadRule::clone() const
{ {
return NEW MTGOverloadRule(*this); return NEW MTGOverloadRule(*this);
} }
///////////////////////////////////////////////////////////////////////////////////////////////////
//bestow
MTGBestowRule::MTGBestowRule(GameObserver* observer, int _id) :
MTGAlternativeCostRule(observer, _id)
{
aType = MTGAbility::BESTOW_COST;
}
int MTGBestowRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
{
if (!card->model)
return 0;
//Player * player = game->currentlyActing();
if (!card->model->data->getManaCost()->getBestow())
return 0;
if (card->isInPlay(game))
return 0;
ManaCost * cost = NEW ManaCost(card->model->data->getManaCost()->getBestow());
ManaCost * newCost = card->computeNewCost(card, cost, cost);
if (newCost->extraCosts)
for (unsigned int i = 0; i < newCost->extraCosts->costs.size(); i++)
{
newCost->extraCosts->costs[i]->setSource(card);
}
SAFE_DELETE(cost);
if (card->isLand())
return 0;
if (!card->controller()->inPlay()->hasType("creature") && !card->controller()->opponent()->inPlay()->hasType("creature"))
return 0;
return MTGAlternativeCostRule::isReactingToClick(card, mana, newCost);
}
int MTGBestowRule::reactToClick(MTGCardInstance * card)
{
if (!isReactingToClick(card))
return 0;
//this new method below in all alternative cost type causes a memleak, however, you cant safedelete the cost here as it cause a crash
//TODO::::we need to get to the source of this leak and fix it.
ManaCost * cost = NEW ManaCost(card->model->data->getManaCost()->getBestow());
ManaCost * newCost = card->computeNewCost(card, cost, cost);
if (newCost->extraCosts)
for (unsigned int i = 0; i < newCost->extraCosts->costs.size(); i++)
{
newCost->extraCosts->costs[i]->setSource(card);
}
card->paymenttype = MTGAbility::BESTOW_COST;
card->spellTargetType = "creature|battlefield";
return MTGAlternativeCostRule::reactToClick(card, newCost, ManaCost::MANA_PAID_WITH_BESTOW, false);
}
ostream& MTGBestowRule::toString(ostream& out) const
{
out << "MTGBestowRule ::: (";
return MTGAbility::toString(out) << ")";
}
MTGBestowRule * MTGBestowRule::clone() const
{
return NEW MTGBestowRule(*this);
}
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
//ATTACK COST //ATTACK COST
@@ -1425,7 +1487,6 @@ MTGBlockCostRule::MTGBlockCostRule(GameObserver* observer, int _id) :
aType = MTGAbility::BLOCK_COST; aType = MTGAbility::BLOCK_COST;
scost = "Pay to block"; scost = "Pay to block";
} }
int MTGBlockCostRule::isReactingToClick(MTGCardInstance * card, ManaCost *) int MTGBlockCostRule::isReactingToClick(MTGCardInstance * card, ManaCost *)
{ {
if (currentPhase == MTG_PHASE_COMBATBLOCKERS && !game->isInterrupting if (currentPhase == MTG_PHASE_COMBATBLOCKERS && !game->isInterrupting
@@ -1536,6 +1597,14 @@ int MTGAttackRule::receiveEvent(WEvent *e)
for (int i = 0; i < z->nb_cards; i++) for (int i = 0; i < z->nb_cards; i++)
{ {
MTGCardInstance * card = z->cards[i]; MTGCardInstance * card = z->cards[i];
if (card->isAttacker() && card->has(Constants::NOSOLO))
{
TargetChooserFactory tf(game);
TargetChooser * tc = tf.createTargetChooser("creature[attacking]", NULL);
int Check = card->controller()->game->battlefield->countByCanTarget(tc);
if (Check <2)
card->initAttackersDefensers();
}
if (!card->isAttacker() && !event->from->isExtra && card->has(Constants::MUSTATTACK))//cards are only required to attack in the real attack phase of a turn. if (!card->isAttacker() && !event->from->isExtra && card->has(Constants::MUSTATTACK))//cards are only required to attack in the real attack phase of a turn.
reactToClick(card); reactToClick(card);
if (!card->isAttacker() && card->has(Constants::TREASON) && p->isAI()) if (!card->isAttacker() && card->has(Constants::TREASON) && p->isAI())
@@ -1848,6 +1917,50 @@ PermanentAbility(observer, _id)
int MTGBlockRule::receiveEvent(WEvent *e) int MTGBlockRule::receiveEvent(WEvent *e)
{ {
if (dynamic_cast<WEventBlockersChosen*>(e))
{//do not refactor, these are keep seperate for readability.
Player * p = game->currentPlayer;
vector<MTGCardInstance *> Attacker;
MTGGameZone * k = p->game->inPlay;
for (int i = 0; i < k->nb_cards; i++)
{
MTGCardInstance * card = k->cards[i];
if (card->isAttacker())
{
Attacker.push_back(card);
}
}
//force cards that must block, to block whatever is first found. players have a chance to set thier own
//but if ignored we do it for them.
if (Attacker.size())
{
MTGGameZone * tf = p->opponent()->game->inPlay;
for (size_t i = 0; i < tf->cards.size(); i++)
{
MTGCardInstance * card = tf->cards[i];
if (card->has(Constants::MUSTBLOCK) && !card->defenser && card->canBlock())
{//force mustblockers to block the first thing theyre allowed to block if player leaves blockers with them
//unassigned as a block.
for (size_t i = 0; i < Attacker.size(); i++)
{
if (card->canBlock(Attacker[i]) && !card->defenser)
{
blocker = NEW AABlock(card->getObserver(), -1, card, NULL);
blocker->oneShot = true;
blocker->forceDestroy = 1;
blocker->canBeInterrupted = false;
blocker->target = Attacker[i];
blocker->resolve();
SAFE_DELETE(blocker);
}
}
}
}
}
if (dynamic_cast<WEventBlockersChosen*>(e)) if (dynamic_cast<WEventBlockersChosen*>(e))
{ {
@@ -1866,6 +1979,25 @@ int MTGBlockRule::receiveEvent(WEvent *e)
//but this action can not be ignored. //but this action can not be ignored.
} }
} }
//if a card with menace is not blocked by 2 or more, remove any known blockers and attacking as normal.
MTGGameZone * z = p->game->inPlay;
for (int i = 0; i < z->nb_cards; i++)
{
MTGCardInstance * card = z->cards[i];
if (card->has(Constants::MENACE) && card->blockers.size() < 2)
{
while (card->blockers.size())
{
MTGCardInstance * blockingCard = card->blockers.front();
blockingCard->toggleDefenser(NULL);
}
}
}
}
return 1; return 1;
} }
+15 -1
View File
@@ -152,7 +152,8 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstan
manaCost->addExtraCost(NEW SacrificeCost(tc)); manaCost->addExtraCost(NEW SacrificeCost(tc));
} }
break; break;
case 'e': //Exile case 'e':
//Exile
manaCost->addExtraCost(NEW ExileTargetCost(tc)); manaCost->addExtraCost(NEW ExileTargetCost(tc));
break; break;
case 'h': //bounce (move to Hand) case 'h': //bounce (move to Hand)
@@ -387,6 +388,7 @@ ManaCost::ManaCost(ManaCost * manaCost)
FlashBack = NEW ManaCost( manaCost->FlashBack ); FlashBack = NEW ManaCost( manaCost->FlashBack );
morph = NEW ManaCost( manaCost->morph ); morph = NEW ManaCost( manaCost->morph );
suspend = NEW ManaCost( manaCost->suspend ); suspend = NEW ManaCost( manaCost->suspend );
Bestow = NEW ManaCost(manaCost->Bestow);
extraCosts = manaCost->extraCosts ? manaCost->extraCosts->clone() : NULL; extraCosts = manaCost->extraCosts ? manaCost->extraCosts->clone() : NULL;
manaUsedToCast = NULL; manaUsedToCast = NULL;
@@ -415,6 +417,7 @@ ManaCost::ManaCost(const ManaCost& manaCost)
FlashBack = NEW ManaCost( manaCost.FlashBack ); FlashBack = NEW ManaCost( manaCost.FlashBack );
morph = NEW ManaCost( manaCost.morph ); morph = NEW ManaCost( manaCost.morph );
suspend = NEW ManaCost( manaCost.suspend ); suspend = NEW ManaCost( manaCost.suspend );
Bestow = NEW ManaCost(manaCost.Bestow);
extraCosts = manaCost.extraCosts ? manaCost.extraCosts->clone() : NULL; extraCosts = manaCost.extraCosts ? manaCost.extraCosts->clone() : NULL;
manaUsedToCast = NULL; manaUsedToCast = NULL;
@@ -438,6 +441,7 @@ ManaCost & ManaCost::operator= (const ManaCost & manaCost)
FlashBack = manaCost.FlashBack; FlashBack = manaCost.FlashBack;
morph = manaCost.morph; morph = manaCost.morph;
suspend = manaCost.suspend; suspend = manaCost.suspend;
Bestow = manaCost.Bestow;
manaUsedToCast = manaCost.manaUsedToCast; manaUsedToCast = manaCost.manaUsedToCast;
xColor = manaCost.xColor; xColor = manaCost.xColor;
} }
@@ -454,6 +458,7 @@ ManaCost::~ManaCost()
SAFE_DELETE(Retrace); SAFE_DELETE(Retrace);
SAFE_DELETE(morph); SAFE_DELETE(morph);
SAFE_DELETE(suspend); SAFE_DELETE(suspend);
SAFE_DELETE(Bestow);
SAFE_DELETE(manaUsedToCast); SAFE_DELETE(manaUsedToCast);
cost.erase(cost.begin() ,cost.end()); cost.erase(cost.begin() ,cost.end());
@@ -539,6 +544,7 @@ void ManaCost::init()
Retrace = NULL; Retrace = NULL;
morph = NULL; morph = NULL;
suspend = NULL; suspend = NULL;
Bestow = NULL;
manaUsedToCast = NULL; manaUsedToCast = NULL;
isMulti = false; isMulti = false;
xColor = -1; xColor = -1;
@@ -563,6 +569,7 @@ void ManaCost::resetCosts()
SAFE_DELETE(Retrace); SAFE_DELETE(Retrace);
SAFE_DELETE(morph); SAFE_DELETE(morph);
SAFE_DELETE(suspend); SAFE_DELETE(suspend);
SAFE_DELETE(Bestow);
} }
void ManaCost::copy(ManaCost * _manaCost) void ManaCost::copy(ManaCost * _manaCost)
@@ -628,6 +635,12 @@ void ManaCost::copy(ManaCost * _manaCost)
suspend = NEW ManaCost(); suspend = NEW ManaCost();
suspend->copy(_manaCost->suspend); suspend->copy(_manaCost->suspend);
} }
SAFE_DELETE(Bestow);
if (_manaCost->Bestow)
{
Bestow = NEW ManaCost();
Bestow->copy(_manaCost->Bestow);
}
xColor = _manaCost->xColor; xColor = _manaCost->xColor;
} }
@@ -1092,6 +1105,7 @@ void ManaPool::Empty()
SAFE_DELETE(Retrace); SAFE_DELETE(Retrace);
SAFE_DELETE(morph); SAFE_DELETE(morph);
SAFE_DELETE(suspend); SAFE_DELETE(suspend);
SAFE_DELETE(Bestow);
SAFE_DELETE(manaUsedToCast); SAFE_DELETE(manaUsedToCast);
init(); init();
WEvent * e = NEW WEventEmptyManaPool(this); WEvent * e = NEW WEventEmptyManaPool(this);
+3 -2
View File
@@ -413,12 +413,13 @@ void Rules::initGame(GameObserver *g, bool currentPlayerSet)
{ {
p->mAvatarName = initState.playerData[i].player->mAvatarName; p->mAvatarName = initState.playerData[i].player->mAvatarName;
} }
MTGGameZone * playerZones[] = { p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay, p->game->exile }; MTGGameZone * playerZones[] = { p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay, p->game->exile , p->game->reveal };
MTGGameZone * loadedPlayerZones[] = { initState.playerData[i].player->game->graveyard, MTGGameZone * loadedPlayerZones[] = { initState.playerData[i].player->game->graveyard,
initState.playerData[i].player->game->library, initState.playerData[i].player->game->library,
initState.playerData[i].player->game->hand, initState.playerData[i].player->game->hand,
initState.playerData[i].player->game->inPlay, initState.playerData[i].player->game->inPlay,
initState.playerData[i].player->game->exile }; initState.playerData[i].player->game->exile,
initState.playerData[i].player->game->reveal };
for (int j = 0; j < 5; j++) for (int j = 0; j < 5; j++)
{ {
MTGGameZone * zone = playerZones[j]; MTGGameZone * zone = playerZones[j];
+23 -13
View File
@@ -156,6 +156,11 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
{ {
zones[nbzones++] = MTGGameZone::ALL_ZONES; zones[nbzones++] = MTGGameZone::ALL_ZONES;
} }
else if (zoneName.compare("reveal") == 0)
{
zones[nbzones++] = MTGGameZone::MY_REVEAL;
zones[nbzones++] = MTGGameZone::OPPONENT_REVEAL;
}
else if (zoneName.compare("graveyard") == 0) else if (zoneName.compare("graveyard") == 0)
{ {
zones[nbzones++] = MTGGameZone::MY_GRAVEYARD; zones[nbzones++] = MTGGameZone::MY_GRAVEYARD;
@@ -637,15 +642,15 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
} }
} }
if (attribute.find("iscolorless") != string::npos) if (attribute.find("colorless") != string::npos)
{ {
attributefound = 1; attributefound = 1;
for (int cid = 1; cid < Constants::NB_Colors; cid++) for (int cid = 1; cid < Constants::NB_Colors; cid++)
{ {
cd->SetExclusionColor(cid); cd->SetExclusionColor(cid);
} }
cd->mode = CardDescriptor::CD_OR; cd->mode = CardDescriptor::CD_OR;
} }
if (attribute.find("chosencolor") != string::npos) if (attribute.find("chosencolor") != string::npos)
{ {
@@ -817,6 +822,7 @@ TargetChooser::TargetChooser(GameObserver *observer, MTGCardInstance * card, int
TargetsList(), observer(observer) TargetsList(), observer(observer)
{ {
forceTargetListReady = 0; forceTargetListReady = 0;
forceTargetListReadyByPlayer = 0;
source = card; source = card;
targetter = card; targetter = card;
maxtargets = _maxtargets; maxtargets = _maxtargets;
@@ -899,6 +905,10 @@ int TargetChooser::ForceTargetListReady()
int TargetChooser::targetsReadyCheck() int TargetChooser::targetsReadyCheck()
{ {
if (targetMin == false && !targets.size() && forceTargetListReadyByPlayer)
{
return TARGET_OK_FULL;//we have no min amount for targets and 0 targets is a valid amount player called for a forced finish.
}
if (!targets.size()) if (!targets.size())
{ {
return TARGET_NOK; return TARGET_NOK;
@@ -931,8 +941,8 @@ bool TargetChooser::validTargetsExist(int maxTargets)
int maxAmount = 0; int maxAmount = 0;
Player *p = observer->players[i]; Player *p = observer->players[i];
if (canTarget(p)) return true; if (canTarget(p)) return true;
MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->exile, p->game->stack }; MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->exile, p->game->stack, p->game->reveal };
for (int k = 0; k < 6; k++) for (int k = 0; k < 7; k++)
{ {
MTGGameZone * z = zones[k]; MTGGameZone * z = zones[k];
if (targetsZone(z)) if (targetsZone(z))
@@ -965,8 +975,8 @@ int TargetChooser::countValidTargets(bool withoutProtections)
Player *p = observer->players[i]; Player *p = observer->players[i];
if(canTarget(p)) if(canTarget(p))
result++; result++;
MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->exile, p->game->stack }; MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->exile, p->game->stack, p->game->reveal };
for (int k = 0; k < 6; k++) for (int k = 0; k < 7; k++)
{ {
MTGGameZone * z = zones[k]; MTGGameZone * z = zones[k];
if (targetsZone(z)) if (targetsZone(z))
+1
View File
@@ -123,6 +123,7 @@ WEventTarget::WEventTarget(MTGCardInstance * card,MTGCardInstance * source) :
WEventCardUpdate(card),card(card),source(source) WEventCardUpdate(card),card(card),source(source)
{ {
card->cardistargetted = 1; card->cardistargetted = 1;
if(source)
source->cardistargetter = 1; source->cardistargetter = 1;
} }