Erwan
- added maxCast and maxPlay abilities, this deprecates the following abilities: nospells,nocreatures,onlyonespell,land I usually don't like to deprecate abilities, but the existing ones, despite having easy to remember names, were really not flexible enough. If you want to use these old keywords, instead use: -- nospells => maxCast(*)0 -- onlyOneSpell => maxCast(*)1 --nocreatures => maxCast(creature)0 --land:1 => maxplay(land)+1 note maxPlay and maxCast. They follow similar rules, but maxPlay monitors the number of cards that are going on the Battlefield, while maxCast monitors the stack. In most cases, maxCast should be the one to use, but lands are a special case because they go directly to play. I unfortunately cannot guarantee I didn't break anything, especially in the AI, but the test suite passes ,and I added a few additional tests yesterday and today, to feel more confident about the change. next step is removing the creatures keywords that do the same kind of thing (cantcast, etc...) and replace them with maxCast
This commit is contained in:
@@ -1902,7 +1902,7 @@ type=Artifact
|
|||||||
name=Angelic Arbiter
|
name=Angelic Arbiter
|
||||||
abilities=flying
|
abilities=flying
|
||||||
auto=@movedTo(*|opponentstack):all(creature|opponentBattlefield) cantattack
|
auto=@movedTo(*|opponentstack):all(creature|opponentBattlefield) cantattack
|
||||||
auto=@attacking(creature|opponentBattlefield):nospell opponent
|
auto=@attacking(creature|opponentBattlefield):maxCast(*)0 opponent ueot
|
||||||
text=Flying -- Each opponent who cast a spell this turn can't attack with creatures. -- Each opponent who attacked with creatures this turn can't cast spells.
|
text=Flying -- Each opponent who cast a spell this turn can't attack with creatures. -- Each opponent who attacked with creatures this turn can't cast spells.
|
||||||
mana={5}{W}{W}
|
mana={5}{W}{W}
|
||||||
type=Creature
|
type=Creature
|
||||||
@@ -4109,8 +4109,7 @@ toughness=4
|
|||||||
[/card]
|
[/card]
|
||||||
[card]
|
[card]
|
||||||
name=Azusa, Lost but Seeking
|
name=Azusa, Lost but Seeking
|
||||||
auto=land:2
|
auto=maxPlay(land)+2
|
||||||
auto=@each my upkeep:land:2 controller
|
|
||||||
text=You may play two additional lands on each of your turns.
|
text=You may play two additional lands on each of your turns.
|
||||||
mana={2}{G}
|
mana={2}{G}
|
||||||
type=Legendary Creature
|
type=Legendary Creature
|
||||||
@@ -9712,7 +9711,7 @@ type=Sorcery
|
|||||||
[card]
|
[card]
|
||||||
name=Cease-Fire
|
name=Cease-Fire
|
||||||
target=player
|
target=player
|
||||||
auto=nocreatures
|
auto=maxCast(creature)0
|
||||||
auto=draw:1 controller
|
auto=draw:1 controller
|
||||||
text=Target player can't cast creature spells this turn. -- Draw a card.
|
text=Target player can't cast creature spells this turn. -- Draw a card.
|
||||||
mana={2}{W}
|
mana={2}{W}
|
||||||
@@ -20094,15 +20093,14 @@ toughness=1
|
|||||||
[/card]
|
[/card]
|
||||||
[card]
|
[card]
|
||||||
name=Exploration
|
name=Exploration
|
||||||
auto=land:1
|
auto=maxPlay(land)+1
|
||||||
auto=@each my upkeep:land:1 controller
|
|
||||||
text=You may play an additional land on each of your turns.
|
text=You may play an additional land on each of your turns.
|
||||||
mana={G}
|
mana={G}
|
||||||
type=Enchantment
|
type=Enchantment
|
||||||
[/card]
|
[/card]
|
||||||
[card]
|
[card]
|
||||||
name=Explore
|
name=Explore
|
||||||
auto=land:1
|
auto=maxPlay(land)+1
|
||||||
auto=draw:1
|
auto=draw:1
|
||||||
text=You may play an additional land this turn. -- Draw a card.
|
text=You may play an additional land this turn. -- Draw a card.
|
||||||
mana={1}{G}
|
mana={1}{G}
|
||||||
@@ -44353,7 +44351,7 @@ toughness=6
|
|||||||
[card]
|
[card]
|
||||||
name=Orim's Chant
|
name=Orim's Chant
|
||||||
target=player
|
target=player
|
||||||
auto=nospells
|
auto=maxCast(*)0
|
||||||
kicker={W}
|
kicker={W}
|
||||||
auto=kicker cantattack all(creature)
|
auto=kicker cantattack all(creature)
|
||||||
text=Kicker {W} (You may pay an additional {W} as you cast this spell.) -- Target player can't cast spells this turn. -- If Orim's Chant was kicked, creatures can't attack this turn.
|
text=Kicker {W} (You may pay an additional {W} as you cast this spell.) -- Target player can't cast spells this turn. -- If Orim's Chant was kicked, creatures can't attack this turn.
|
||||||
@@ -44400,8 +44398,8 @@ toughness=3
|
|||||||
[card]
|
[card]
|
||||||
name=Oriss Samite Guardian
|
name=Oriss Samite Guardian
|
||||||
auto={T}:prevent:999 target(creature)
|
auto={T}:prevent:999 target(creature)
|
||||||
auto={discard(oriss samite guardian|myhand)}:name(opponent can't cast spells and his creatures cannot attack ueot) && nospell opponent && cantattack all(creature|opponentBattlefield)
|
auto={discard(oriss samite guardian|myhand)}:name(opponent can't cast spells and his creatures cannot attack ueot) && maxCast(*)0 opponent ueot && cantattack all(creature|opponentBattlefield)
|
||||||
auto={discard(oriss samite guardian|myhand)}:name(you can't cast spells and your creatures cannot attack ueot) && nospell control && cantattack all(creature|myBattlefield)
|
auto={discard(oriss samite guardian|myhand)}:name(you can't cast spells and your creatures cannot attack ueot) && maxCast(*)0 control ueot && cantattack all(creature|myBattlefield)
|
||||||
text={T}: Prevent all damage that would be dealt to target creature this turn. -- Grandeur - Discard another card named Oriss, Samite Guardian: Target player can't cast spells this turn, and creatures that player controls can't attack this turn.
|
text={T}: Prevent all damage that would be dealt to target creature this turn. -- Grandeur - Discard another card named Oriss, Samite Guardian: Target player can't cast spells this turn, and creatures that player controls can't attack this turn.
|
||||||
mana={1}{W}{W}
|
mana={1}{W}{W}
|
||||||
type=Legendary Creature
|
type=Legendary Creature
|
||||||
@@ -56424,7 +56422,7 @@ type=Sorcery
|
|||||||
[/card]
|
[/card]
|
||||||
[card]
|
[card]
|
||||||
name=Silence
|
name=Silence
|
||||||
auto=nospells opponent
|
auto=maxCast(*)0 opponent
|
||||||
text=Your opponents can't cast spells this turn. (Spells cast before this resolves are unaffected.)
|
text=Your opponents can't cast spells this turn. (Spells cast before this resolves are unaffected.)
|
||||||
mana={W}
|
mana={W}
|
||||||
type=Instant
|
type=Instant
|
||||||
@@ -62151,7 +62149,7 @@ type=Land
|
|||||||
[/card]
|
[/card]
|
||||||
[card]
|
[card]
|
||||||
name=Summer Bloom
|
name=Summer Bloom
|
||||||
auto=land:3
|
auto=maxPlay(land)+3
|
||||||
text=You may play up to three additional lands this turn.
|
text=You may play up to three additional lands this turn.
|
||||||
mana={1}{G}
|
mana={1}{G}
|
||||||
type=Sorcery
|
type=Sorcery
|
||||||
|
|||||||
@@ -472,6 +472,7 @@ selesnya_guildmage.txt
|
|||||||
setpower_settoughness.txt
|
setpower_settoughness.txt
|
||||||
shard_volley.txt
|
shard_volley.txt
|
||||||
sigil_captain_i467.txt
|
sigil_captain_i467.txt
|
||||||
|
silence.txt
|
||||||
silver_seraph_i300.txt
|
silver_seraph_i300.txt
|
||||||
skullcage0_i239.txt
|
skullcage0_i239.txt
|
||||||
skullcage1_i239.txt
|
skullcage1_i239.txt
|
||||||
|
|||||||
28
projects/mtg/bin/Res/test/silence.txt
Normal file
28
projects/mtg/bin/Res/test/silence.txt
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#Slience: Opponent cannot cast spells this turn
|
||||||
|
[init]
|
||||||
|
firstmain
|
||||||
|
[player1]
|
||||||
|
manapool:{G}{G}
|
||||||
|
inplay:mountain
|
||||||
|
hand:grizzly bears,raging golblin
|
||||||
|
[player2]
|
||||||
|
inplay:plains
|
||||||
|
hand:Silence
|
||||||
|
[do]
|
||||||
|
Grizzly Bears
|
||||||
|
no
|
||||||
|
yes
|
||||||
|
plains
|
||||||
|
Silence
|
||||||
|
endofinterruption
|
||||||
|
mountain
|
||||||
|
Raging goblin
|
||||||
|
[assert]
|
||||||
|
firstmain
|
||||||
|
[player1]
|
||||||
|
inplay:mountain,Grizzly bears
|
||||||
|
manapool:{R}
|
||||||
|
[player2]
|
||||||
|
inplay:plains
|
||||||
|
graveyard:Silence
|
||||||
|
[end]
|
||||||
@@ -1280,22 +1280,41 @@ public:
|
|||||||
int getNumCards();
|
int getNumCards();
|
||||||
};
|
};
|
||||||
|
|
||||||
//lands, allows to play more land during a turn:
|
|
||||||
class AMoreLandPlzUEOT: public InstantAbilityTP
|
|
||||||
|
class ACastRestriction: public AbilityTP
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WParsedInt *additional;
|
WParsedInt *value; //"maxPerTurn" value
|
||||||
MaxPerTurnRestriction * landsRestriction;
|
MaxPerTurnRestriction * existingRestriction; // a pointer to the restriction that is being modified or that has been created (for restriction deletion purpose)
|
||||||
|
TargetChooser * restrictionsScope; //a minimalist TargetChooser object describing the cards impacted by the restriction (for example: lands)
|
||||||
|
bool modifyExisting; //if set to true, means we want to modify an existing restriction, otherwise we create a new one
|
||||||
|
int zoneId; // identifier of the zone id impacted by the restriction
|
||||||
|
Player * targetPlayer; // Reference to the player impacted by the restriction (for restriction deletion purpose)
|
||||||
|
|
||||||
AMoreLandPlzUEOT(int _id, MTGCardInstance * card, Targetable * _target, WParsedInt * _additional, int who = TargetChooser::UNSET);
|
ACastRestriction(int _id, MTGCardInstance * card, Targetable * _target, TargetChooser * _restrictionsScope, WParsedInt * _value, bool _modifyExisting, int _zoneId, int who = TargetChooser::UNSET);
|
||||||
int addToGame();
|
int addToGame();
|
||||||
int destroy();
|
int destroy();
|
||||||
const char * getMenuText();
|
const char * getMenuText();
|
||||||
AMoreLandPlzUEOT * clone() const;
|
ACastRestriction * clone() const;
|
||||||
~AMoreLandPlzUEOT();
|
~ACastRestriction();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class AInstantCastRestrictionUEOT: public InstantAbilityTP
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ACastRestriction * ability;
|
||||||
|
|
||||||
|
|
||||||
|
AInstantCastRestrictionUEOT(int _id, MTGCardInstance * card, Targetable * _target, TargetChooser * _restrictionsScope, WParsedInt * _value, bool _modifyExisting, int _zoneId, int who = TargetChooser::UNSET);
|
||||||
|
int resolve();
|
||||||
|
const char * getMenuText();
|
||||||
|
AInstantCastRestrictionUEOT * clone() const;
|
||||||
|
~AInstantCastRestrictionUEOT();
|
||||||
|
};
|
||||||
|
|
||||||
/*Gives life to target controller*/
|
/*Gives life to target controller*/
|
||||||
class AALifer: public ActivatedAbilityTP
|
class AALifer: public ActivatedAbilityTP
|
||||||
{
|
{
|
||||||
@@ -2052,7 +2071,6 @@ public:
|
|||||||
a->isClone = 1;
|
a->isClone = 1;
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//Circle of Protections
|
//Circle of Protections
|
||||||
@@ -5552,38 +5570,6 @@ public:
|
|||||||
AAShuffle * clone() const;
|
AAShuffle * clone() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
//only 1 spell
|
|
||||||
class AAOnlyOne: public ActivatedAbilityTP
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AAOnlyOne(int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost = NULL, int _tap = 0, int who =
|
|
||||||
TargetChooser::UNSET);
|
|
||||||
int resolve();
|
|
||||||
const char * getMenuText();
|
|
||||||
AAOnlyOne * clone() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
//nospells
|
|
||||||
class AANoSpells: public ActivatedAbilityTP
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AANoSpells(int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost = NULL, int _tap = 0, int who =
|
|
||||||
TargetChooser::UNSET);
|
|
||||||
int resolve();
|
|
||||||
const char * getMenuText();
|
|
||||||
AANoSpells * clone() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
//NoCreature
|
|
||||||
class AANoCreatures: public ActivatedAbilityTP
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AANoCreatures(int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost = NULL, int _tap = 0, int who =
|
|
||||||
TargetChooser::UNSET);
|
|
||||||
int resolve();
|
|
||||||
const char * getMenuText();
|
|
||||||
AANoCreatures * clone() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
//Random Discard
|
//Random Discard
|
||||||
class AARandomDiscarder: public ActivatedAbilityTP
|
class AARandomDiscarder: public ActivatedAbilityTP
|
||||||
|
|||||||
@@ -406,6 +406,14 @@ public:
|
|||||||
Targetable * getTarget();
|
Targetable * getTarget();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class AbilityTP:public MTGAbility{
|
||||||
|
public:
|
||||||
|
int who;
|
||||||
|
AbilityTP(int id, MTGCardInstance * card, Targetable * _target = NULL, int who = TargetChooser::UNSET);
|
||||||
|
Targetable * getTarget();
|
||||||
|
virtual ~AbilityTP(){};
|
||||||
|
};
|
||||||
|
|
||||||
class AManaProducer: public ActivatedAbilityTP{
|
class AManaProducer: public ActivatedAbilityTP{
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ class MTGGameZone {
|
|||||||
static MTGGameZone * stringToZone(string zoneName, MTGCardInstance * source, MTGCardInstance * target);
|
static MTGGameZone * stringToZone(string zoneName, MTGCardInstance * source, MTGCardInstance * target);
|
||||||
static int zoneStringToId(string zoneName);
|
static int zoneStringToId(string zoneName);
|
||||||
static MTGGameZone *intToZone(int zoneId, MTGCardInstance * source = NULL,MTGCardInstance * target = NULL);
|
static MTGGameZone *intToZone(int zoneId, MTGCardInstance * source = NULL,MTGCardInstance * target = NULL);
|
||||||
|
static MTGGameZone *intToZone(int zoneId, Player * source, Player * target);
|
||||||
bool needShuffle;
|
bool needShuffle;
|
||||||
virtual const char * getName(){return "zone";};
|
virtual const char * getName(){return "zone";};
|
||||||
virtual ostream& toString(ostream&) const;
|
virtual ostream& toString(ostream&) const;
|
||||||
|
|||||||
@@ -31,9 +31,6 @@ public:
|
|||||||
int castedspellsthisturn;
|
int castedspellsthisturn;
|
||||||
bool onlyonecast;
|
bool onlyonecast;
|
||||||
int castcount;
|
int castcount;
|
||||||
bool nocreatureinstant;
|
|
||||||
bool nospellinstant;
|
|
||||||
bool onlyoneinstant;
|
|
||||||
bool castrestrictedcreature;
|
bool castrestrictedcreature;
|
||||||
bool castrestrictedspell;
|
bool castrestrictedspell;
|
||||||
bool onlyoneboth;
|
bool onlyoneboth;
|
||||||
|
|||||||
@@ -1330,13 +1330,15 @@ int AIPlayerBaka::computeActions()
|
|||||||
ipotential = true;
|
ipotential = true;
|
||||||
}
|
}
|
||||||
//look for an instant of ability to interupt with
|
//look for an instant of ability to interupt with
|
||||||
if((castrestrictedspell == false && nospellinstant == false)&&
|
if((castrestrictedspell == false)&&
|
||||||
(onlyonecast == false || castcount < 2) && (onlyoneinstant == false || castcount < 2))
|
(onlyonecast == false || castcount < 2))
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!nextCardToPlay)
|
if (!nextCardToPlay)
|
||||||
{
|
{
|
||||||
nextCardToPlay = FindCardToPlay(icurrentMana, "instant");
|
nextCardToPlay = FindCardToPlay(icurrentMana, "instant");
|
||||||
|
if (game->playRestrictions->canPutIntoZone(nextCardToPlay, game->stack) == PlayRestriction::CANT_PLAY)
|
||||||
|
nextCardToPlay = NULL;
|
||||||
}
|
}
|
||||||
if (!nextCardToPlay)
|
if (!nextCardToPlay)
|
||||||
{
|
{
|
||||||
@@ -1379,33 +1381,20 @@ int AIPlayerBaka::computeActions()
|
|||||||
nextCardToPlay = FindCardToPlay(currentMana, "land");
|
nextCardToPlay = FindCardToPlay(currentMana, "land");
|
||||||
selectAbility();
|
selectAbility();
|
||||||
//look for the most expensive creature we can afford
|
//look for the most expensive creature we can afford
|
||||||
if((castrestrictedspell == false && nospellinstant == false)&&
|
if((castrestrictedspell == false)&&
|
||||||
(onlyonecast == false || castcount < 2)&&(onlyoneinstant == false || castcount < 2))
|
(onlyonecast == false || castcount < 2))
|
||||||
{
|
{
|
||||||
if (castrestrictedcreature == false && nocreatureinstant == false)
|
|
||||||
|
const char* types[] = {"creature", "enchantment", "artifact", "sorcery", "instant"};
|
||||||
|
int count = 0;
|
||||||
|
while (!nextCardToPlay && count < 5)
|
||||||
{
|
{
|
||||||
if (!nextCardToPlay)
|
nextCardToPlay = FindCardToPlay(currentMana, types[count]);
|
||||||
{
|
if (game->playRestrictions->canPutIntoZone(nextCardToPlay, game->stack) == PlayRestriction::CANT_PLAY)
|
||||||
nextCardToPlay = FindCardToPlay(currentMana, "creature");
|
nextCardToPlay = NULL;
|
||||||
}
|
count++;
|
||||||
}
|
|
||||||
//Let's Try an enchantment maybe ?
|
|
||||||
if (!nextCardToPlay)
|
|
||||||
{
|
|
||||||
nextCardToPlay = FindCardToPlay(currentMana, "enchantment");
|
|
||||||
}
|
|
||||||
if (!nextCardToPlay)
|
|
||||||
{
|
|
||||||
nextCardToPlay = FindCardToPlay(currentMana, "artifact");
|
|
||||||
}
|
|
||||||
if (!nextCardToPlay)
|
|
||||||
{
|
|
||||||
nextCardToPlay = FindCardToPlay(currentMana, "sorcery");
|
|
||||||
}
|
|
||||||
if (!nextCardToPlay)
|
|
||||||
{
|
|
||||||
nextCardToPlay = FindCardToPlay(currentMana, "instant");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nextCardToPlay)
|
if (!nextCardToPlay)
|
||||||
{
|
{
|
||||||
selectAbility();
|
selectAbility();
|
||||||
|
|||||||
@@ -1455,63 +1455,124 @@ AACloner::~AACloner()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// More Land - allow more lands to be played on a turn
|
|
||||||
AMoreLandPlzUEOT::AMoreLandPlzUEOT(int _id, MTGCardInstance * card, Targetable * _target, WParsedInt * _additional, int who) :
|
|
||||||
InstantAbilityTP(_id, card, _target, who), additional(_additional)
|
// Cast/Play Restriction modifier
|
||||||
|
ACastRestriction::ACastRestriction(int _id, MTGCardInstance * card, Targetable * _target, TargetChooser * _restrictionsScope, WParsedInt * _value, bool _modifyExisting, int _zoneId, int who) :
|
||||||
|
AbilityTP(_id, card, _target, who), restrictionsScope(_restrictionsScope), value(_value), modifyExisting(_modifyExisting),zoneId(_zoneId)
|
||||||
{
|
{
|
||||||
landsRestriction = NULL;
|
existingRestriction = NULL;
|
||||||
|
targetPlayer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AMoreLandPlzUEOT::addToGame()
|
int ACastRestriction::addToGame()
|
||||||
{
|
{
|
||||||
Targetable * _target = getTarget();
|
Targetable * _target = getTarget();
|
||||||
Player * player;
|
|
||||||
if (_target)
|
if (_target)
|
||||||
{
|
{
|
||||||
if (_target->typeAsTarget() == TARGET_CARD)
|
if (_target->typeAsTarget() == TARGET_CARD)
|
||||||
{
|
{
|
||||||
player = ((MTGCardInstance *) _target)->controller();
|
targetPlayer = ((MTGCardInstance *) _target)->controller();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
player = (Player *) _target;
|
targetPlayer = (Player *) _target;
|
||||||
}
|
}
|
||||||
landsRestriction = (MaxPerTurnRestriction *) (player->game->playRestrictions->getRestrictionById(PlayRestriction::LANDS_RULE_ID));
|
if (modifyExisting)
|
||||||
if(landsRestriction && landsRestriction->maxPerTurn != MaxPerTurnRestriction::NO_MAX)
|
{
|
||||||
landsRestriction->maxPerTurn += additional->getValue();
|
//For now the only modifying rule is the one for lands, so this is hardcoded here.
|
||||||
return InstantAbility::addToGame();
|
//This means that a modifying rule for anything lands will actually modify the lands rule.
|
||||||
|
//In the future, we need a way to "identify" rules that modify an existing restriction, probably by doing a comparison of the TargetChoosers
|
||||||
|
existingRestriction = (MaxPerTurnRestriction *) (targetPlayer->game->playRestrictions->getRestrictionById(PlayRestriction::LANDS_RULE_ID));
|
||||||
|
if(existingRestriction && existingRestriction->maxPerTurn != MaxPerTurnRestriction::NO_MAX)
|
||||||
|
existingRestriction->maxPerTurn += value->getValue();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TargetChooser * _tc = restrictionsScope->clone();
|
||||||
|
existingRestriction = NEW MaxPerTurnRestriction(PlayRestriction::UNDEF_ID, _tc, value->getValue(), MTGGameZone::intToZone(zoneId, source->controller(), targetPlayer));
|
||||||
|
targetPlayer->game->playRestrictions->addRestriction(existingRestriction);
|
||||||
|
|
||||||
|
}
|
||||||
|
AbilityTP::addToGame();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AMoreLandPlzUEOT::destroy()
|
int ACastRestriction::destroy()
|
||||||
{
|
{
|
||||||
if (!landsRestriction)
|
if (!existingRestriction)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if(landsRestriction && landsRestriction->maxPerTurn != MaxPerTurnRestriction::NO_MAX)
|
if (modifyExisting)
|
||||||
landsRestriction->maxPerTurn -= additional->getValue();
|
{
|
||||||
|
if(existingRestriction->maxPerTurn != MaxPerTurnRestriction::NO_MAX)
|
||||||
|
existingRestriction->maxPerTurn -= value->getValue();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
targetPlayer->game->playRestrictions->removeRestriction(existingRestriction);
|
||||||
|
SAFE_DELETE(existingRestriction);
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * AMoreLandPlzUEOT::getMenuText()
|
const char * ACastRestriction::getMenuText()
|
||||||
{
|
{
|
||||||
return "Additional Lands";
|
if (modifyExisting)
|
||||||
|
return "Additional Lands"; //hardoced because only the lands rule allows to modify existing rule for now
|
||||||
|
return "Cast Restriction";
|
||||||
}
|
}
|
||||||
|
|
||||||
AMoreLandPlzUEOT * AMoreLandPlzUEOT::clone() const
|
ACastRestriction * ACastRestriction::clone() const
|
||||||
{
|
{
|
||||||
AMoreLandPlzUEOT * a = NEW AMoreLandPlzUEOT(*this);
|
ACastRestriction * a = NEW ACastRestriction(*this);
|
||||||
a->additional = NEW WParsedInt(*(a->additional));
|
a->value = NEW WParsedInt(*(a->value));
|
||||||
|
a->restrictionsScope = restrictionsScope->clone();
|
||||||
a->isClone = 1;
|
a->isClone = 1;
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
AMoreLandPlzUEOT::~AMoreLandPlzUEOT()
|
ACastRestriction::~ACastRestriction()
|
||||||
{
|
{
|
||||||
SAFE_DELETE(additional);
|
SAFE_DELETE(value);
|
||||||
|
SAFE_DELETE(restrictionsScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AInstantCastRestrictionUEOT::AInstantCastRestrictionUEOT(int _id, MTGCardInstance * card, Targetable * _target, TargetChooser * _restrictionsScope, WParsedInt * _value, bool _modifyExisting, int _zoneId, int who) :
|
||||||
|
InstantAbilityTP(_id, card, _target, who)
|
||||||
|
{
|
||||||
|
ability = NEW ACastRestriction(_id, card, _target, _restrictionsScope, _value, _modifyExisting, _zoneId, who);
|
||||||
|
}
|
||||||
|
|
||||||
|
int AInstantCastRestrictionUEOT::resolve()
|
||||||
|
{
|
||||||
|
ACastRestriction * a = ability->clone();
|
||||||
|
GenericInstantAbility * wrapper = NEW GenericInstantAbility(1, source, (Damageable *) (this->target), a);
|
||||||
|
wrapper->addToGame();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
const char * AInstantCastRestrictionUEOT::getMenuText()
|
||||||
|
{
|
||||||
|
return ability->getMenuText();
|
||||||
|
}
|
||||||
|
|
||||||
|
AInstantCastRestrictionUEOT * AInstantCastRestrictionUEOT::clone() const
|
||||||
|
{
|
||||||
|
AInstantCastRestrictionUEOT * a = NEW AInstantCastRestrictionUEOT(*this);
|
||||||
|
a->ability = this->ability->clone();
|
||||||
|
a->isClone = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
AInstantCastRestrictionUEOT::~AInstantCastRestrictionUEOT()
|
||||||
|
{
|
||||||
|
SAFE_DELETE(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//AAMover
|
//AAMover
|
||||||
AAMover::AAMover(int _id, MTGCardInstance * _source, MTGCardInstance * _target, string dest, ManaCost * _cost, int doTap) :
|
AAMover::AAMover(int _id, MTGCardInstance * _source, MTGCardInstance * _target, string dest, ManaCost * _cost, int doTap) :
|
||||||
ActivatedAbility(_id, _source, _cost, 0, doTap), destination(dest)
|
ActivatedAbility(_id, _source, _cost, 0, doTap), destination(dest)
|
||||||
@@ -1570,116 +1631,6 @@ AAMover * AAMover::clone() const
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
// No Creatures
|
|
||||||
AANoCreatures::AANoCreatures(int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost, int _tap, int who) :
|
|
||||||
ActivatedAbilityTP(_id, card, _target, _cost, _tap, who)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int AANoCreatures::resolve()
|
|
||||||
{
|
|
||||||
Targetable * _target = getTarget();
|
|
||||||
Player * player;
|
|
||||||
if (_target)
|
|
||||||
{
|
|
||||||
if (_target->typeAsTarget() == TARGET_CARD)
|
|
||||||
{
|
|
||||||
player = ((MTGCardInstance *) _target)->controller();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
player = (Player *) _target;
|
|
||||||
}
|
|
||||||
player->nocreatureinstant = true;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char * AANoCreatures::getMenuText()
|
|
||||||
{
|
|
||||||
return "No Creatures!";
|
|
||||||
}
|
|
||||||
|
|
||||||
AANoCreatures * AANoCreatures::clone() const
|
|
||||||
{
|
|
||||||
AANoCreatures * a = NEW AANoCreatures(*this);
|
|
||||||
a->isClone = 1;
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
// AA No Spells
|
|
||||||
AANoSpells::AANoSpells(int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost, int _tap, int who) :
|
|
||||||
ActivatedAbilityTP(_id, card, _target, _cost, _tap, who)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
int AANoSpells::resolve()
|
|
||||||
{
|
|
||||||
Targetable * _target = getTarget();
|
|
||||||
Player * player;
|
|
||||||
if (_target)
|
|
||||||
{
|
|
||||||
if (_target->typeAsTarget() == TARGET_CARD)
|
|
||||||
{
|
|
||||||
player = ((MTGCardInstance *) _target)->controller();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
player = (Player *) _target;
|
|
||||||
}
|
|
||||||
player->nospellinstant = true;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char * AANoSpells::getMenuText()
|
|
||||||
{
|
|
||||||
return "No Spells!";
|
|
||||||
}
|
|
||||||
|
|
||||||
AANoSpells * AANoSpells::clone() const
|
|
||||||
{
|
|
||||||
AANoSpells * a = NEW AANoSpells(*this);
|
|
||||||
a->isClone = 1;
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
//OnlyOne
|
|
||||||
AAOnlyOne::AAOnlyOne(int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost, int _tap, int who) :
|
|
||||||
ActivatedAbilityTP(_id, card, _target, _cost, _tap, who)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int AAOnlyOne::resolve()
|
|
||||||
{
|
|
||||||
Targetable * _target = getTarget();
|
|
||||||
Player * player;
|
|
||||||
if (_target)
|
|
||||||
{
|
|
||||||
if (_target->typeAsTarget() == TARGET_CARD)
|
|
||||||
{
|
|
||||||
player = ((MTGCardInstance *) _target)->controller();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
player = (Player *) _target;
|
|
||||||
}
|
|
||||||
player->onlyoneinstant = true;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char * AAOnlyOne::getMenuText()
|
|
||||||
{
|
|
||||||
return "Only One Spell!";
|
|
||||||
}
|
|
||||||
|
|
||||||
AAOnlyOne * AAOnlyOne::clone() const
|
|
||||||
{
|
|
||||||
AAOnlyOne * a = NEW AAOnlyOne(*this);
|
|
||||||
a->isClone = 1;
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Random Discard
|
//Random Discard
|
||||||
AARandomDiscarder::AARandomDiscarder(int _id, MTGCardInstance * card, Targetable * _target,string nbcardsStr, ManaCost * _cost,
|
AARandomDiscarder::AARandomDiscarder(int _id, MTGCardInstance * card, Targetable * _target,string nbcardsStr, ManaCost * _cost,
|
||||||
int _tap, int who) :
|
int _tap, int who) :
|
||||||
|
|||||||
@@ -111,9 +111,6 @@ void GameObserver::nextGamePhase()
|
|||||||
currentPlayer->castedspellsthisturn = 0;
|
currentPlayer->castedspellsthisturn = 0;
|
||||||
currentPlayer->opponent()->castedspellsthisturn = 0;
|
currentPlayer->opponent()->castedspellsthisturn = 0;
|
||||||
currentPlayer->castcount = 0;
|
currentPlayer->castcount = 0;
|
||||||
currentPlayer->nocreatureinstant = false;
|
|
||||||
currentPlayer->nospellinstant = false;
|
|
||||||
currentPlayer->onlyoneinstant = false;
|
|
||||||
currentPlayer->damageCount = 0;
|
currentPlayer->damageCount = 0;
|
||||||
currentPlayer->preventable = 0;
|
currentPlayer->preventable = 0;
|
||||||
currentPlayer->isPoisoned = false;
|
currentPlayer->isPoisoned = false;
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ const size_t kLordKeywordsCount = 5;
|
|||||||
const string kThisKeywords[] = { "this(", "thisforeach(" };
|
const string kThisKeywords[] = { "this(", "thisforeach(" };
|
||||||
const size_t kThisKeywordsCount = 2;
|
const size_t kThisKeywordsCount = 2;
|
||||||
|
|
||||||
|
const string kMaxCastKeywords[] = { "maxplay(", "maxcost("};
|
||||||
|
const int kMaxCastZones[] = { MTGGameZone::BATTLEFIELD, MTGGameZone::STACK};
|
||||||
|
const size_t kMaxCastKeywordsCount = 2;
|
||||||
|
|
||||||
int MTGAbility::allowedToCast(MTGCardInstance * card,Player * player)
|
int MTGAbility::allowedToCast(MTGCardInstance * card,Player * player)
|
||||||
{
|
{
|
||||||
int cPhase = game->getCurrentGamePhase();
|
int cPhase = game->getCurrentGamePhase();
|
||||||
@@ -699,7 +703,8 @@ TriggeredAbility * AbilityFactory::parseTrigger(string s, string magicText, int
|
|||||||
}
|
}
|
||||||
return NEW TrVampired(id, card, tc, fromTc, 0);
|
return NEW TrVampired(id, card, tc, fromTc, 0);
|
||||||
}
|
}
|
||||||
//when card becomes the target of a spell or ability
|
|
||||||
|
//when card becomes the target of a spell or ability
|
||||||
found = s.find("targeted(");
|
found = s.find("targeted(");
|
||||||
if (found != string::npos)
|
if (found != string::npos)
|
||||||
{
|
{
|
||||||
@@ -796,6 +801,7 @@ int AbilityFactory::parseRestriction(string s)
|
|||||||
return ActivatedAbility::NO_RESTRICTION;
|
return ActivatedAbility::NO_RESTRICTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When abilities encapsulate each other, gets the deepest one (it is the one likely to have the most relevant information)
|
||||||
MTGAbility * AbilityFactory::getCoreAbility(MTGAbility * a)
|
MTGAbility * AbilityFactory::getCoreAbility(MTGAbility * a)
|
||||||
{
|
{
|
||||||
GenericTargetAbility * gta = dynamic_cast<GenericTargetAbility*> (a);
|
GenericTargetAbility * gta = dynamic_cast<GenericTargetAbility*> (a);
|
||||||
@@ -2187,27 +2193,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
a->oneShot = 1;
|
a->oneShot = 1;
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
//additional lands per turn
|
|
||||||
found = s.find("land:");
|
|
||||||
if (found != string::npos)
|
|
||||||
{
|
|
||||||
size_t start = s.find(":", found);
|
|
||||||
size_t end = s.find(" ", start);
|
|
||||||
string additionalStr;
|
|
||||||
if (end != string::npos)
|
|
||||||
{
|
|
||||||
additionalStr = s.substr(start + 1, end - start - 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
additionalStr = s.substr(start + 1);
|
|
||||||
}
|
|
||||||
WParsedInt * additional = NEW WParsedInt(additionalStr, spell, card);
|
|
||||||
Targetable * t = NULL;
|
|
||||||
if (spell)
|
|
||||||
t = spell->getNextTarget();
|
|
||||||
return NEW AMoreLandPlzUEOT(id, card, t, additional, who);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Deplete
|
//Deplete
|
||||||
found = s.find("deplete:");
|
found = s.find("deplete:");
|
||||||
@@ -2244,38 +2230,45 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
//cantcastspells
|
//Cast/Play Restrictions
|
||||||
found = s.find("onlyonespell");
|
for (size_t i = 0; i < kMaxCastKeywordsCount; ++i)
|
||||||
if (found != string::npos)
|
|
||||||
{
|
{
|
||||||
Targetable * t = NULL;
|
found = s.find(kMaxCastKeywords[i]);
|
||||||
if (spell)
|
if (found != string::npos)
|
||||||
t = spell->getNextTarget();
|
{
|
||||||
MTGAbility * a = NEW AAOnlyOne(id, card, t, NULL, 0, who);
|
size_t header = kMaxCastKeywords[i].size();
|
||||||
a->oneShot = 1;
|
size_t end = s.find(")");
|
||||||
return a;
|
string targetsString = s.substr(found + header, end - found - header);
|
||||||
}
|
TargetChooserFactory tcf;
|
||||||
//cantcastspells
|
TargetChooser * castTargets = tcf.createTargetChooser(targetsString, card);
|
||||||
found = s.find("nospells");
|
|
||||||
if (found != string::npos)
|
size_t space = s.find(" ", end);
|
||||||
{
|
string valueStr;
|
||||||
Targetable * t = NULL;
|
if (space!= string::npos)
|
||||||
if (spell)
|
{
|
||||||
t = spell->getNextTarget();
|
valueStr = s.substr(end + 1, space - end - 1);
|
||||||
MTGAbility * a = NEW AANoSpells(id, card, t, NULL, 0, who);
|
}
|
||||||
a->oneShot = 1;
|
else
|
||||||
return a;
|
{
|
||||||
}
|
valueStr = s.substr(end + 1);
|
||||||
//cantcastcreature
|
}
|
||||||
found = s.find("nocreatures");
|
|
||||||
if (found != string::npos)
|
bool modifyExisting = (valueStr.find("+") != string::npos || valueStr.find("-") != string::npos);
|
||||||
{
|
|
||||||
Targetable * t = NULL;
|
WParsedInt * value = NEW WParsedInt(valueStr, spell, card);
|
||||||
if (spell)
|
Targetable * t = NULL;
|
||||||
t = spell->getNextTarget();
|
if (spell)
|
||||||
MTGAbility * a = NEW AANoCreatures(id, card, t, NULL, 0, who);
|
t = spell->getNextTarget();
|
||||||
a->oneShot = 1;
|
if (!activated)
|
||||||
return a;
|
{
|
||||||
|
if (card->hasType("instant") || card->hasType("sorcery") || forceUEOT)
|
||||||
|
{
|
||||||
|
return NEW AInstantCastRestrictionUEOT(id, card, t, castTargets, value, modifyExisting, kMaxCastZones[i], who);
|
||||||
|
}
|
||||||
|
return NEW ACastRestriction(id, card, t, castTargets, value, modifyExisting, kMaxCastZones[i], who);
|
||||||
|
}
|
||||||
|
return NULL; //TODO NEW ACastRestrictionUntilEndOfTurn(id, card, t, value, modifyExisting, kMaxCastZones[i], who);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Discard
|
//Discard
|
||||||
@@ -4752,6 +4745,44 @@ AManaProducer * AManaProducer::clone() const
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AbilityTP::AbilityTP(int id, MTGCardInstance * card, Targetable * _target, int who) :
|
||||||
|
MTGAbility(id, card), who(who)
|
||||||
|
{
|
||||||
|
if (_target)
|
||||||
|
target = _target;
|
||||||
|
}
|
||||||
|
|
||||||
|
Targetable * AbilityTP::getTarget()
|
||||||
|
{
|
||||||
|
switch (who)
|
||||||
|
{
|
||||||
|
case TargetChooser::TARGET_CONTROLLER:
|
||||||
|
if (target)
|
||||||
|
{
|
||||||
|
switch (target->typeAsTarget())
|
||||||
|
{
|
||||||
|
case TARGET_CARD:
|
||||||
|
return ((MTGCardInstance *) target)->controller();
|
||||||
|
case TARGET_STACKACTION:
|
||||||
|
return ((Interruptible *) target)->source->controller();
|
||||||
|
default:
|
||||||
|
return (Player *) target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
case TargetChooser::CONTROLLER:
|
||||||
|
return source->controller();
|
||||||
|
case TargetChooser::OPPONENT:
|
||||||
|
return source->controller()->opponent();
|
||||||
|
case TargetChooser::OWNER:
|
||||||
|
return source->owner;
|
||||||
|
default:
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
ActivatedAbilityTP::ActivatedAbilityTP(int id, MTGCardInstance * card, Targetable * _target, ManaCost * cost, int doTap, int who) :
|
ActivatedAbilityTP::ActivatedAbilityTP(int id, MTGCardInstance * card, Targetable * _target, ManaCost * cost, int doTap, int who) :
|
||||||
ActivatedAbility(id, card, cost, 0, doTap), who(who)
|
ActivatedAbility(id, card, cost, 0, doTap), who(who)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -731,6 +731,63 @@ void MTGLibrary::shuffleTopToBottom(int nbcards)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MTGGameZone * MTGGameZone::intToZone(int zoneId, Player * p, Player * p2)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (zoneId)
|
||||||
|
{
|
||||||
|
case MY_GRAVEYARD:
|
||||||
|
return p->game->graveyard;
|
||||||
|
case OPPONENT_GRAVEYARD:
|
||||||
|
return p->opponent()->game->graveyard;
|
||||||
|
case TARGET_CONTROLLER_GRAVEYARD:
|
||||||
|
return p2->game->graveyard;
|
||||||
|
|
||||||
|
case MY_BATTLEFIELD:
|
||||||
|
return p->game->inPlay;
|
||||||
|
case OPPONENT_BATTLEFIELD:
|
||||||
|
return p->opponent()->game->inPlay;
|
||||||
|
case TARGET_CONTROLLER_BATTLEFIELD:
|
||||||
|
return p2->game->inPlay;
|
||||||
|
case BATTLEFIELD:
|
||||||
|
return p->game->inPlay;
|
||||||
|
|
||||||
|
case MY_HAND:
|
||||||
|
return p->game->hand;
|
||||||
|
case OPPONENT_HAND:
|
||||||
|
return p->opponent()->game->hand;
|
||||||
|
case TARGET_CONTROLLER_HAND:
|
||||||
|
return p2->game->hand;
|
||||||
|
|
||||||
|
case MY_EXILE:
|
||||||
|
return p->game->removedFromGame;
|
||||||
|
case OPPONENT_EXILE:
|
||||||
|
return p->opponent()->game->removedFromGame;
|
||||||
|
case TARGET_CONTROLLER_EXILE:
|
||||||
|
return p2->game->removedFromGame;
|
||||||
|
|
||||||
|
case MY_LIBRARY:
|
||||||
|
return p->game->library;
|
||||||
|
case OPPONENT_LIBRARY:
|
||||||
|
return p->opponent()->game->library;
|
||||||
|
case TARGET_CONTROLLER_LIBRARY:
|
||||||
|
return p2->game->library;
|
||||||
|
case LIBRARY:
|
||||||
|
return p->game->library;
|
||||||
|
|
||||||
|
case MY_STACK:
|
||||||
|
return p->game->stack;
|
||||||
|
case OPPONENT_STACK:
|
||||||
|
return p->opponent()->game->stack;
|
||||||
|
case TARGET_CONTROLLER_STACK:
|
||||||
|
return p2->game->stack;
|
||||||
|
case STACK:
|
||||||
|
return p->game->stack;
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MTGGameZone * MTGGameZone::intToZone(int zoneId, MTGCardInstance * source, MTGCardInstance * target)
|
MTGGameZone * MTGGameZone::intToZone(int zoneId, MTGCardInstance * source, MTGCardInstance * target)
|
||||||
{
|
{
|
||||||
Player *p, *p2;
|
Player *p, *p2;
|
||||||
@@ -758,88 +815,51 @@ MTGGameZone * MTGGameZone::intToZone(int zoneId, MTGCardInstance * source, MTGCa
|
|||||||
else
|
else
|
||||||
p2 = target->controller();
|
p2 = target->controller();
|
||||||
|
|
||||||
|
|
||||||
|
MTGGameZone * result = intToZone(zoneId, p, p2);
|
||||||
|
if (result) return result;
|
||||||
|
|
||||||
switch (zoneId)
|
switch (zoneId)
|
||||||
{
|
{
|
||||||
case MY_GRAVEYARD:
|
|
||||||
return p->game->graveyard;
|
|
||||||
case OPPONENT_GRAVEYARD:
|
|
||||||
return p->opponent()->game->graveyard;
|
|
||||||
case TARGET_OWNER_GRAVEYARD:
|
case TARGET_OWNER_GRAVEYARD:
|
||||||
return target->owner->game->graveyard;
|
return target->owner->game->graveyard;
|
||||||
case TARGET_CONTROLLER_GRAVEYARD:
|
|
||||||
return p2->game->graveyard;
|
|
||||||
case GRAVEYARD:
|
case GRAVEYARD:
|
||||||
return target->owner->game->graveyard;
|
return target->owner->game->graveyard;
|
||||||
case OWNER_GRAVEYARD:
|
case OWNER_GRAVEYARD:
|
||||||
return target->owner->game->graveyard;
|
return target->owner->game->graveyard;
|
||||||
|
|
||||||
case MY_BATTLEFIELD:
|
|
||||||
return p->game->inPlay;
|
|
||||||
case OPPONENT_BATTLEFIELD:
|
|
||||||
return p->opponent()->game->inPlay;
|
|
||||||
case TARGET_OWNER_BATTLEFIELD:
|
case TARGET_OWNER_BATTLEFIELD:
|
||||||
return target->owner->game->inPlay;
|
return target->owner->game->inPlay;
|
||||||
case TARGET_CONTROLLER_BATTLEFIELD:
|
|
||||||
return p2->game->inPlay;
|
|
||||||
case BATTLEFIELD:
|
|
||||||
return p->game->inPlay;
|
|
||||||
case OWNER_BATTLEFIELD:
|
case OWNER_BATTLEFIELD:
|
||||||
return target->owner->game->inPlay;
|
return target->owner->game->inPlay;
|
||||||
|
|
||||||
case MY_HAND:
|
|
||||||
return p->game->hand;
|
|
||||||
case OPPONENT_HAND:
|
|
||||||
return p->opponent()->game->hand;
|
|
||||||
case TARGET_OWNER_HAND:
|
case TARGET_OWNER_HAND:
|
||||||
return target->owner->game->hand;
|
return target->owner->game->hand;
|
||||||
case TARGET_CONTROLLER_HAND:
|
|
||||||
return p2->game->hand;
|
|
||||||
case HAND:
|
case HAND:
|
||||||
return target->owner->game->hand;
|
return target->owner->game->hand;
|
||||||
case OWNER_HAND:
|
case OWNER_HAND:
|
||||||
return target->owner->game->hand;
|
return target->owner->game->hand;
|
||||||
|
|
||||||
case MY_EXILE:
|
|
||||||
return p->game->removedFromGame;
|
|
||||||
case OPPONENT_EXILE:
|
|
||||||
return p->opponent()->game->removedFromGame;
|
|
||||||
case TARGET_OWNER_EXILE:
|
case TARGET_OWNER_EXILE:
|
||||||
return target->owner->game->removedFromGame;
|
return target->owner->game->removedFromGame;
|
||||||
case TARGET_CONTROLLER_EXILE:
|
|
||||||
return p2->game->removedFromGame;
|
|
||||||
case EXILE:
|
case EXILE:
|
||||||
return target->owner->game->removedFromGame;
|
return target->owner->game->removedFromGame;
|
||||||
case OWNER_EXILE:
|
case OWNER_EXILE:
|
||||||
return target->owner->game->removedFromGame;
|
return target->owner->game->removedFromGame;
|
||||||
|
|
||||||
case MY_LIBRARY:
|
|
||||||
return p->game->library;
|
|
||||||
case OPPONENT_LIBRARY:
|
|
||||||
return p->opponent()->game->library;
|
|
||||||
case TARGET_OWNER_LIBRARY:
|
case TARGET_OWNER_LIBRARY:
|
||||||
return target->owner->game->library;
|
return target->owner->game->library;
|
||||||
case TARGET_CONTROLLER_LIBRARY:
|
|
||||||
return p2->game->library;
|
|
||||||
case LIBRARY:
|
|
||||||
return p->game->library;
|
|
||||||
case OWNER_LIBRARY:
|
case OWNER_LIBRARY:
|
||||||
return target->owner->game->library;
|
return target->owner->game->library;
|
||||||
|
|
||||||
case MY_STACK:
|
|
||||||
return p->game->stack;
|
|
||||||
case OPPONENT_STACK:
|
|
||||||
return p->opponent()->game->stack;
|
|
||||||
case TARGET_OWNER_STACK:
|
case TARGET_OWNER_STACK:
|
||||||
return target->owner->game->stack;
|
return target->owner->game->stack;
|
||||||
case TARGET_CONTROLLER_STACK:
|
|
||||||
return p2->game->stack;
|
|
||||||
case STACK:
|
|
||||||
return p->game->stack;
|
|
||||||
case OWNER_STACK:
|
case OWNER_STACK:
|
||||||
return target->owner->game->stack;
|
return target->owner->game->stack;
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int MTGGameZone::zoneStringToId(string zoneName)
|
int MTGGameZone::zoneStringToId(string zoneName)
|
||||||
|
|||||||
@@ -55,6 +55,9 @@ int MTGPutInPlayRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
|
|||||||
|| game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN))
|
|| game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN))
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (currentPlayer->game->playRestrictions->canPutIntoZone(card, currentPlayer->game->stack) == PlayRestriction::CANT_PLAY)
|
||||||
|
return 0;
|
||||||
ManaCost * playerMana = player->getManaPool();
|
ManaCost * playerMana = player->getManaPool();
|
||||||
ManaCost * cost = card->getManaCost();
|
ManaCost * cost = card->getManaCost();
|
||||||
|
|
||||||
@@ -69,21 +72,7 @@ int MTGPutInPlayRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (player->nospellinstant)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (player->onlyoneinstant)
|
|
||||||
{
|
|
||||||
if (player->castcount >= 1)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (player->nocreatureinstant && card->hasType("creature"))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (player->castrestrictedcreature && card->hasType("creature"))
|
if (player->castrestrictedcreature && card->hasType("creature"))
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@@ -168,7 +157,7 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card)
|
|||||||
game->targetChooser = NULL;
|
game->targetChooser = NULL;
|
||||||
player->castedspellsthisturn += 1;
|
player->castedspellsthisturn += 1;
|
||||||
player->opponent()->castedspellsthisturn += 1;
|
player->opponent()->castedspellsthisturn += 1;
|
||||||
if (player->onlyonecast || player->onlyoneinstant)
|
if (player->onlyonecast)
|
||||||
{
|
{
|
||||||
player->castcount += 1;
|
player->castcount += 1;
|
||||||
}
|
}
|
||||||
@@ -178,7 +167,7 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card)
|
|||||||
spell = game->mLayers->stackLayer()->addSpell(copy, NULL, spellCost, payResult, 0);
|
spell = game->mLayers->stackLayer()->addSpell(copy, NULL, spellCost, payResult, 0);
|
||||||
player->castedspellsthisturn += 1;
|
player->castedspellsthisturn += 1;
|
||||||
player->opponent()->castedspellsthisturn += 1;
|
player->opponent()->castedspellsthisturn += 1;
|
||||||
if (player->onlyonecast || player->onlyoneinstant)
|
if (player->onlyonecast)
|
||||||
{
|
{
|
||||||
player->castcount += 1;
|
player->castcount += 1;
|
||||||
}
|
}
|
||||||
@@ -275,6 +264,8 @@ int MTGAlternativeCostRule::isReactingToClick(MTGCardInstance * card, ManaCost *
|
|||||||
|| game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN))
|
|| game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN))
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
if (currentPlayer->game->playRestrictions->canPutIntoZone(card, currentPlayer->game->stack) == PlayRestriction::CANT_PLAY)
|
||||||
|
return 0;
|
||||||
ManaCost * playerMana = player->getManaPool();
|
ManaCost * playerMana = player->getManaPool();
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
@@ -289,21 +280,7 @@ int MTGAlternativeCostRule::isReactingToClick(MTGCardInstance * card, ManaCost *
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (player->nospellinstant )
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (player->onlyoneinstant )
|
|
||||||
{
|
|
||||||
if (player->castcount >= 1)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (player->nocreatureinstant && card->hasType("creature"))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (player->castrestrictedcreature && card->hasType("creature"))
|
if (player->castrestrictedcreature && card->hasType("creature"))
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@@ -375,7 +352,7 @@ int MTGAlternativeCostRule::reactToClick(MTGCardInstance * card, ManaCost *alter
|
|||||||
game->targetChooser = NULL;
|
game->targetChooser = NULL;
|
||||||
player->castedspellsthisturn += 1;
|
player->castedspellsthisturn += 1;
|
||||||
player->opponent()->castedspellsthisturn += 1;
|
player->opponent()->castedspellsthisturn += 1;
|
||||||
if (player->onlyonecast || player->onlyoneinstant)
|
if (player->onlyonecast )
|
||||||
player->castcount += 1;
|
player->castcount += 1;
|
||||||
|
|
||||||
if (card->has(Constants::STORM))
|
if (card->has(Constants::STORM))
|
||||||
@@ -610,6 +587,8 @@ int MTGMorphCostRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
|
|||||||
|| game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN))
|
|| game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN))
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
if (currentPlayer->game->playRestrictions->canPutIntoZone(card, currentPlayer->game->stack) == PlayRestriction::CANT_PLAY)
|
||||||
|
return 0;
|
||||||
ManaCost * playerMana = player->getManaPool();
|
ManaCost * playerMana = player->getManaPool();
|
||||||
ManaCost * cost = card->getManaCost();
|
ManaCost * cost = card->getManaCost();
|
||||||
ManaCost * morph = card->getManaCost()->morph;
|
ManaCost * morph = card->getManaCost()->morph;
|
||||||
@@ -624,21 +603,7 @@ int MTGMorphCostRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (player->nospellinstant )
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (player->onlyoneinstant )
|
|
||||||
{
|
|
||||||
if (player->castcount >= 1)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (player->nocreatureinstant && card->hasType("creature"))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (player->castrestrictedcreature && card->hasType("creature"))
|
if (player->castrestrictedcreature && card->hasType("creature"))
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@@ -709,7 +674,7 @@ int MTGMorphCostRule::reactToClick(MTGCardInstance * card)
|
|||||||
copy->toughness = 2;
|
copy->toughness = 2;
|
||||||
player->castedspellsthisturn += 1;
|
player->castedspellsthisturn += 1;
|
||||||
player->opponent()->castedspellsthisturn += 1;
|
player->opponent()->castedspellsthisturn += 1;
|
||||||
if (player->onlyonecast || player->onlyoneinstant)
|
if (player->onlyonecast)
|
||||||
{
|
{
|
||||||
player->castcount += 1;
|
player->castcount += 1;
|
||||||
|
|
||||||
|
|||||||
@@ -21,9 +21,6 @@ Damageable(20)
|
|||||||
onlyoneboth = false;
|
onlyoneboth = false;
|
||||||
onlyonecast = false;
|
onlyonecast = false;
|
||||||
castcount = 0;
|
castcount = 0;
|
||||||
nocreatureinstant = false;
|
|
||||||
nospellinstant = false;
|
|
||||||
onlyoneinstant = false;
|
|
||||||
poisonCount = 0;
|
poisonCount = 0;
|
||||||
damageCount = 0;
|
damageCount = 0;
|
||||||
preventable = 0;
|
preventable = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user