Pretty huge patch here(sorry old habits never die :( )
lots of changes, many bug fixes,
first
added auto=count(targetchooser)
and countedamount wparsed int
they work together for cards where it is difficult to get working without knowing in advance how many we had ie: exile blah creatures, for each creature you exiled do effect.
auto=count(creature|mybattlefield)
auto=moveto(exile)
auto=draw:countedamount
it takes into account token creatures, which our old methods did not.
second, added "freeze" which is a "frozen" that automatically taps your target for you, for use when nesting or whenever needed where it was difficult to nest the ability with tap included.
added devotion for "iroas"
added reveal:x and scry x
reveal contains optionone/optiononeend ; optiontwo/optiontwoend ; repeat; afterrevealed/afterrevealed end.
this ability has heavy use of targetListIsSet(<amount>) and upto:amount, you MUST be certain that all cards being revealed have an action that removes them from reveal either in the first, second, or 3rd ability.
there are over 300 examples in the new card code, the ability is VERY easy to understand.
scry contains automatic put on top, put on bottom, then scrycore/scrycoreend which is an ability to fire.
it also contains keywords, dontshow which is nested in scrycore, scry reveals, puts on top or bottom, then reveal AGAIN, and does an effect, dontshow eliminates the 2nd revealing.
is also contains "delayed" keyword, which delays the ability until AFTER the core fires.
added bestow. update rules mtg.txt!!!!
examples are in primitives, every bestow card was supported.
added a new lord based on varibles and restrictions
while(restriction{morbid})
while(varible:blah)
this simplifies and expands on this(, allowing you to even use while(cantarget together and check if a card is targetable by the variable. examples are in primitives
added token(by card name)
auto=token(Eldrazi Scion)
will search primitives and card dats for this card and give it to you as a token.
valid card dat info is still required.
added variable delirium
added restriction madnessplayed to allow checking if the card was played with madness.
added restriction "geared" for checking if a card has equipment on it.
added abilities words
skulk
menace <--cant be blocked except by 2 or more, if you dont block it with 2 or more we automatically unassign the single blocker and the creature is considered not blocked.
nosolo <--cant attack alone
mustblock <---if you dont assign as a blocker, we assign automatically the first thing it can block legally.
changed iscolorless back to "colorless"
enjoy, cards coming soon, theyre coded but im debating on not alpha sorting, cards being added this patch 965 uniques.
there is a section of the commit which was just VS2016 normalizing line ends, sorry if it makes it a cluster mess.
This commit is contained in:
@@ -35,6 +35,7 @@ auto=lifelinkrule
|
||||
auto=deathtouchrule
|
||||
auto=soulbondrule
|
||||
auto=dredgerule
|
||||
auto=bestowrule
|
||||
|
||||
[PLAYERS]
|
||||
life:20
|
||||
|
||||
@@ -38,6 +38,117 @@ public:
|
||||
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
|
||||
{
|
||||
public:
|
||||
@@ -240,6 +351,10 @@ private:
|
||||
{
|
||||
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)
|
||||
{
|
||||
size_t begins = s.find("type:");
|
||||
@@ -556,6 +671,10 @@ private:
|
||||
{
|
||||
intValue = target->getCurrentToughness();
|
||||
}
|
||||
else if (s == "countedamount")
|
||||
{
|
||||
intValue = target->CountedObjects;
|
||||
}
|
||||
else if (s == "kicked")
|
||||
{
|
||||
intValue = target->kicked;
|
||||
@@ -745,6 +864,21 @@ private:
|
||||
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
|
||||
{
|
||||
intValue = atoi(s.c_str());
|
||||
@@ -2855,7 +2989,6 @@ public:
|
||||
return NEW ARegularLifeModifierAura(*this);
|
||||
}
|
||||
};
|
||||
|
||||
//Generic Kird Ape
|
||||
class AAsLongAs: public ListMaintainerAbility, public NestedAbility
|
||||
{
|
||||
@@ -3334,6 +3467,7 @@ public:
|
||||
list<int> colors;
|
||||
int power, toughness;
|
||||
int tokenId;
|
||||
string _cardName;
|
||||
string name;
|
||||
string sabilities;
|
||||
string starfound;
|
||||
@@ -3345,6 +3479,7 @@ public:
|
||||
MTGCardInstance * myToken;
|
||||
vector<MTGAbility *> currentAbilities;
|
||||
Player * tokenReciever;
|
||||
//by id
|
||||
ATokenCreator(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable *, ManaCost * _cost, int tokenId,string starfound, WParsedInt * multiplier = NULL,
|
||||
int who = 0,bool aLivingWeapon = false) :
|
||||
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();
|
||||
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,
|
||||
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)
|
||||
@@ -3877,10 +4023,12 @@ class AThis: public MTGAbility, public NestedAbility
|
||||
public:
|
||||
MTGAbility * a;
|
||||
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)
|
||||
{
|
||||
td = _td;
|
||||
restrictionCheck = restriction;
|
||||
ability->source = source;
|
||||
ability->target = target;
|
||||
a = NULL;
|
||||
@@ -3904,9 +4052,18 @@ public:
|
||||
|
||||
int resolve()
|
||||
{
|
||||
//TODO check if ability is oneShot ?
|
||||
int match;
|
||||
match = td->match(source);
|
||||
int match = 0;
|
||||
if (td)
|
||||
{
|
||||
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)
|
||||
{
|
||||
addAbilityToGame();
|
||||
@@ -3953,6 +4110,7 @@ public:
|
||||
{
|
||||
AThis * a = NEW AThis(*this);
|
||||
a->ability = ability->clone();
|
||||
if(a->td)
|
||||
a->td = td->clone();
|
||||
return a;
|
||||
}
|
||||
@@ -4166,6 +4324,16 @@ public:
|
||||
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 */
|
||||
class AATapper: public ActivatedAbility
|
||||
@@ -4197,12 +4365,22 @@ public:
|
||||
int resolve();
|
||||
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 */
|
||||
class AAFrozen: public ActivatedAbility
|
||||
{
|
||||
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();
|
||||
const string getMenuText();
|
||||
AAFrozen * clone() const;
|
||||
@@ -6205,7 +6383,8 @@ public:
|
||||
MTGCardInstance * theNamedCard;
|
||||
bool noEvent;
|
||||
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;};
|
||||
void Update(float dt);
|
||||
|
||||
@@ -80,6 +80,7 @@ class GameObserver{
|
||||
ExtraCosts * mExtraPayment;
|
||||
int oldGamePhase;
|
||||
TargetChooser * targetChooser;
|
||||
CardDisplay * OpenedDisplay;
|
||||
DuelLayers * mLayers;
|
||||
ReplacementEffects *replacementEffects;
|
||||
vector<Player *> players; //created outside
|
||||
|
||||
@@ -121,6 +121,7 @@ public:
|
||||
ManaCost* BuyBack;
|
||||
ManaCost* FlashBack;
|
||||
ManaCost* Retrace;
|
||||
ManaCost* Bestow;
|
||||
ManaCost* morph;
|
||||
ManaCost* suspend;
|
||||
|
||||
|
||||
@@ -95,6 +95,7 @@ public:
|
||||
bool exileEffects;
|
||||
bool suspended;
|
||||
bool miracle;
|
||||
bool isBestowed;
|
||||
int chooseacolor;
|
||||
string chooseasubtype;
|
||||
int coinSide;//1 = tails
|
||||
@@ -105,6 +106,7 @@ public:
|
||||
int notblocked;
|
||||
int fresh;
|
||||
int MaxLevelUp;
|
||||
int CountedObjects;
|
||||
int kicked;
|
||||
int dredge;
|
||||
bool isDualWielding;
|
||||
@@ -272,6 +274,8 @@ public:
|
||||
string currentimprintName;
|
||||
vector<string>imprintedNames;
|
||||
|
||||
MTGCardInstance * revealedLast;//last card revealed by a ability this card owns.
|
||||
bool MadnessPlay;
|
||||
void eventattacked();
|
||||
void eventattackedAlone();
|
||||
void eventattackednotblocked();
|
||||
|
||||
@@ -82,6 +82,7 @@ class Constants
|
||||
static const string kRetraceKeyword;
|
||||
static const string kKickerKeyword;
|
||||
static const string kMorphKeyword;
|
||||
static const string kBestowKeyword;
|
||||
|
||||
// used for deck statistics
|
||||
static const int STATS_FOR_TURNS = 8;
|
||||
@@ -246,8 +247,11 @@ class Constants
|
||||
COMBATTOUGHNESS = 125,
|
||||
CANTPAYLIFE = 126,
|
||||
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_M = 'M', //Mythics
|
||||
@@ -308,6 +312,7 @@ class Constants
|
||||
CAST_WITH_RETRACE = 6,
|
||||
CAST_WITH_MORPH = 7,
|
||||
CAST_WITH_SUSPEND = 8,
|
||||
CAST_WITH_BESTOW = 9,
|
||||
|
||||
CAST_ALTERNATE = -1, //matches all alternate costs, including itself
|
||||
CAST_ALL = -2, // matches everything except NOT_CAST
|
||||
|
||||
@@ -72,6 +72,14 @@ class MTGGameZone {
|
||||
OWNER_STACK = 66,
|
||||
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;
|
||||
@@ -194,6 +202,7 @@ public:
|
||||
MTGRemovedFromGame * exile; //alias to removedFromZone
|
||||
MTGGameZone * garbage;
|
||||
MTGGameZone * garbageLastTurn;
|
||||
MTGGameZone * reveal;
|
||||
MTGGameZone * temp;
|
||||
|
||||
MTGPlayerCards();
|
||||
|
||||
@@ -206,6 +206,21 @@ public:
|
||||
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
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -31,6 +31,7 @@ protected:
|
||||
ManaCost * manaUsedToCast;
|
||||
ManaCost * morph;
|
||||
ManaCost * Retrace;
|
||||
ManaCost * Bestow;
|
||||
ManaCost * FlashBack;
|
||||
ManaCost * BuyBack;
|
||||
ManaCost * kicker;
|
||||
@@ -75,6 +76,9 @@ public:
|
||||
ManaCost * getSuspend(){ return suspend; };
|
||||
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; };
|
||||
void setManaUsedToCast(ManaCost * aMana){ SAFE_DELETE(manaUsedToCast); manaUsedToCast = aMana;};
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ class TargetChooser: public TargetsList
|
||||
protected:
|
||||
int forceTargetListReady;
|
||||
public:
|
||||
int forceTargetListReadyByPlayer;
|
||||
const static int UNLITMITED_TARGETS = 1000;
|
||||
enum
|
||||
{
|
||||
|
||||
@@ -1221,7 +1221,7 @@ int AIPlayerBaka::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, Rank
|
||||
for (int i = 0; i < 2; 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()->maxtargets == 1)
|
||||
@@ -1352,7 +1352,7 @@ int AIPlayerBaka::selectHintAbility()
|
||||
|
||||
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;
|
||||
check = dynamic_cast<ExtraManaCost*>(observer->mExtraPayment->costs[0]);
|
||||
@@ -1560,8 +1560,8 @@ int AIPlayerBaka::chooseTarget(TargetChooser * _tc, Player * forceTarget,MTGCard
|
||||
}
|
||||
}
|
||||
MTGPlayerCards * playerZones = target->game;
|
||||
MTGGameZone * zones[] = { playerZones->hand, playerZones->library, playerZones->inPlay, playerZones->graveyard,playerZones->stack,playerZones->exile };
|
||||
for (int j = 0; j < 6; j++)
|
||||
MTGGameZone * zones[] = { playerZones->hand, playerZones->library, playerZones->inPlay, playerZones->graveyard,playerZones->stack,playerZones->exile,playerZones->reveal };
|
||||
for (int j = 0; j < 7; j++)
|
||||
{
|
||||
MTGGameZone * zone = zones[j];
|
||||
for (int k = 0; k < zone->nb_cards; k++)
|
||||
|
||||
@@ -77,7 +77,7 @@ void ActionLayer::cleanGarbage()
|
||||
|
||||
int ActionLayer::reactToClick(ActionElement * ability, MTGCardInstance * card)
|
||||
{
|
||||
int result = ability->reactToClick(card);
|
||||
int result = ability?ability->reactToClick(card):0;
|
||||
if (result)
|
||||
stuffHappened = 1;
|
||||
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
|
||||
fill the maxtargets list.
|
||||
*/
|
||||
if(int(ae->getActionTc()->getNbTargets()) == countTargets-1)
|
||||
ae->getActionTc()->done = true;
|
||||
if (int(ae->getActionTc()->getNbTargets()) == countTargets)//if the amount of targets is equal the all we can target
|
||||
{
|
||||
ae->getActionTc()->done = true;//were done
|
||||
ae->getActionTc()->source->getObserver()->cardClick(ae->getActionTc()->source, 0, false);//click source.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -578,6 +578,10 @@ int ActionStack::addAbility(MTGAbility * ability)
|
||||
if (!observer->players[0]->isAI() && ability->source->controller() == observer->players[0] && 0
|
||||
== options[Options::INTERRUPTMYABILITIES].number)
|
||||
interruptDecision[0] = DONT_INTERRUPT;
|
||||
if (observer->OpenedDisplay && observer->players[0]->game->reveal->cards.size())
|
||||
{
|
||||
interruptDecision[0] = DONT_INTERRUPT;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -756,9 +756,10 @@ int TapTargetCost::isPaymentSet()
|
||||
int TapTargetCost::doPay()
|
||||
{
|
||||
MTGCardInstance * _target = (MTGCardInstance *) target;
|
||||
source->storedCard = target->createSnapShot();
|
||||
|
||||
if (target)
|
||||
{
|
||||
source->storedCard = target->createSnapShot();
|
||||
_target->tap();
|
||||
target = NULL;
|
||||
if (tc)
|
||||
@@ -799,9 +800,10 @@ int UnTapTargetCost::isPaymentSet()
|
||||
int UnTapTargetCost::doPay()
|
||||
{
|
||||
MTGCardInstance * _target = (MTGCardInstance *) target;
|
||||
source->storedCard = target->createSnapShot();
|
||||
|
||||
if (target)
|
||||
{
|
||||
source->storedCard = target->createSnapShot();
|
||||
_target->untap();
|
||||
target = NULL;
|
||||
if (tc)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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::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"));
|
||||
optionsTabs = NEW WGuiTabMenu();
|
||||
optionsTabs->Add(optionsList);
|
||||
|
||||
@@ -149,12 +149,16 @@ ostream& GuiAvatar::toString(ostream& out) const
|
||||
|
||||
void GuiGameZone::toggleDisplay()
|
||||
{
|
||||
if (showCards)
|
||||
showCards = 0;
|
||||
else
|
||||
if (showCards)
|
||||
{
|
||||
showCards = 0;
|
||||
cd->zone->owner->getObserver()->OpenedDisplay = NULL;
|
||||
}
|
||||
else if(!cd->zone->owner->getObserver()->OpenedDisplay)//one display at a time please.
|
||||
{
|
||||
showCards = 1;
|
||||
cd->init(zone);
|
||||
cd->zone->owner->getObserver()->OpenedDisplay = cd;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
const string kLordKeywords[] = { "lord(", "foreach(", "aslongas(", "teach(", "all(" };
|
||||
const size_t kLordKeywordsCount = 5;
|
||||
|
||||
const string kThisKeywords[] = { "this(", "thisforeach(" };
|
||||
const size_t kThisKeywordsCount = 2;
|
||||
const string kThisKeywords[] = { "this(", "thisforeach(","while(", };
|
||||
const size_t kThisKeywordsCount = 3;
|
||||
|
||||
|
||||
// Used for the maxCast/maxPlay ability parsing
|
||||
@@ -353,6 +353,24 @@ int AbilityFactory::parseCastRestrictions(MTGCardInstance * card, Player * playe
|
||||
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");
|
||||
if(check != string::npos)
|
||||
{
|
||||
@@ -362,6 +380,13 @@ int AbilityFactory::parseCastRestrictions(MTGCardInstance * card, Player * playe
|
||||
return 0;
|
||||
}
|
||||
|
||||
check = restriction[i].find("madnessplayed");
|
||||
if (check != string::npos)
|
||||
{
|
||||
if (card->previous && !card->previous->MadnessPlay)
|
||||
return 0;
|
||||
}
|
||||
|
||||
check = restriction[i].find("prowl");
|
||||
if(check != string::npos)
|
||||
{
|
||||
@@ -437,6 +462,13 @@ int AbilityFactory::parseCastRestrictions(MTGCardInstance * card, Player * playe
|
||||
return 0;
|
||||
}
|
||||
|
||||
check = restriction[i].find("geared");
|
||||
if (check != string::npos)
|
||||
{
|
||||
if (card->equipment < 1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
check = restriction[i].find("raid");
|
||||
if(check != string::npos)
|
||||
{
|
||||
@@ -1139,6 +1171,13 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
observer->addObserver(NEW MTGFlashBackRule(observer, -1));
|
||||
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
|
||||
found = s.find("retracerule");
|
||||
if(found != string::npos)
|
||||
@@ -1306,19 +1345,46 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
//actual abilities, this is a limitation.
|
||||
string unchangedS = "";
|
||||
unchangedS.append(s);
|
||||
found = s.find("pay(");
|
||||
if (found != string::npos && storedPayString.empty())
|
||||
{
|
||||
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(")");
|
||||
}
|
||||
}
|
||||
|
||||
//Reveal:x remove the core so we dont build them prematurely
|
||||
vector<string>transPayfound = parseBetween(s, "newability[pay(", " ");
|
||||
vector<string>transfound = parseBetween(s,"newability[reveal:"," ");//if we are using reveal inside a newability, let transforms remove the string instead.
|
||||
vector<string>abilfound = parseBetween(s, "ability$!name(reveal) reveal:", " ");
|
||||
if(!abilfound.size())
|
||||
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.
|
||||
|
||||
found = s.find("pay(");
|
||||
if (found != string::npos && storedPayString.empty() && !transPayfound.size())
|
||||
{
|
||||
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((");
|
||||
if (found != string::npos && storedString.empty())
|
||||
{
|
||||
@@ -1750,15 +1816,25 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
}
|
||||
if (end != string::npos)
|
||||
{
|
||||
ThisDescriptor * td = NULL;
|
||||
string thisDescriptorString = s.substr(found + header, end - found - header);
|
||||
ThisDescriptorFactory tdf;
|
||||
ThisDescriptor * td = tdf.createThisDescriptor(observer, thisDescriptorString);
|
||||
vector<string> splitRest = parseBetween(s, "restriction{", "}");
|
||||
if (splitRest.size())
|
||||
{
|
||||
|
||||
if (!td)
|
||||
{
|
||||
DebugTrace("MTGABILITY: Parsing Error:" << s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
if (!a)
|
||||
@@ -1795,6 +1871,9 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
case 1:
|
||||
result = NEW AThisForEach(observer, id, card, _target, td, a);
|
||||
break;
|
||||
case 2:
|
||||
result = NEW AThis(observer, id, card, _target, NULL, a, thisDescriptorString);
|
||||
break;
|
||||
default:
|
||||
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 NULL;
|
||||
}
|
||||
|
||||
//mana of the listed type doesnt get emptied from the pools.
|
||||
vector<string>colorType = parseBetween(s,"poolsave(",")",false);
|
||||
if (colorType.size())
|
||||
@@ -2269,9 +2347,21 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
tok->oneShot = 1;
|
||||
return tok;
|
||||
}
|
||||
|
||||
|
||||
string tokenDesc = splitToken[1];
|
||||
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)
|
||||
{
|
||||
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 asCopy = splitCastCard[1].find("copied") != 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 putinplay = splitCastCard[1].find("putinplay") != string::npos;
|
||||
string nameCard = "";
|
||||
@@ -2485,7 +2576,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
nameCard = splitCastName[1];
|
||||
}
|
||||
}
|
||||
MTGAbility *a = NEW AACastCard(observer, id, card, target,withRestrictions,asCopy,asNormal,nameCard,newName,sendNoEvent,putinplay);
|
||||
MTGAbility *a = NEW AACastCard(observer, id, card, target,withRestrictions,asCopy,asNormal,nameCard,newName,sendNoEvent,putinplay, asNormalMadness);
|
||||
a->oneShot = false;
|
||||
if(splitCastCard[1].find("trigger[to]") != string::npos)
|
||||
{
|
||||
@@ -2933,6 +3024,16 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
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
|
||||
vector<string> splitCounterShroud = parseBetween(s, "countershroud(", ")");
|
||||
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
|
||||
vector<string> splitFlipStat = parseBetween(s, "flip(", ")", true);
|
||||
if(splitFlipStat.size())
|
||||
@@ -3291,11 +3416,20 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
found = s.find("frozen");
|
||||
if (found != string::npos)
|
||||
{
|
||||
MTGAbility * a = NEW AAFrozen(observer, id, card, target);
|
||||
MTGAbility * a = NEW AAFrozen(observer, id, card, target,false);
|
||||
a->oneShot = 1;
|
||||
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...
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
found = s.find("swap");
|
||||
if (found != string::npos)
|
||||
@@ -4625,6 +4767,7 @@ MTGAbility::MTGAbility(const MTGAbility& a): ActionElement(a)
|
||||
BuyBack = a.BuyBack; //? NEW ManaCost(a.BuyBack) : NULL;
|
||||
FlashBack = a.FlashBack; // ? NEW ManaCost(a.FlashBack) : NULL;
|
||||
Retrace = a.Retrace;// ? NEW ManaCost(a.Retrace) : NULL;
|
||||
Bestow = a.Bestow;
|
||||
morph = a.morph; //? NEW ManaCost(a.morph) : NULL;
|
||||
suspend = a.suspend;// ? NEW ManaCost(a.suspend) : NULL;
|
||||
|
||||
@@ -5101,7 +5244,7 @@ int TargetAbility::reactToClick(MTGCardInstance * card)
|
||||
}
|
||||
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);
|
||||
if (result)
|
||||
@@ -5360,8 +5503,8 @@ void ListMaintainerAbility::updateTargets()
|
||||
for (int i = 0; i < 2; 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 };
|
||||
for (int k = 0; k < 6; k++)
|
||||
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 < 7; k++)
|
||||
{
|
||||
MTGGameZone * zone = zones[k];
|
||||
if (canTarget(zone))
|
||||
@@ -5432,8 +5575,8 @@ void ListMaintainerAbility::checkTargets()
|
||||
for (int i = 0; i < 2; 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 };
|
||||
for (int k = 0; k < 6; k++)
|
||||
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 < 7; k++)
|
||||
{
|
||||
MTGGameZone * zone = zones[k];
|
||||
if (canTarget(zone))
|
||||
@@ -5772,7 +5915,7 @@ int AManaProducer::resolve()
|
||||
Player * player = getPlayerFromTarget(_target);
|
||||
if (!player)
|
||||
return 0;
|
||||
|
||||
|
||||
player->getManaPool()->add(output, source);
|
||||
if(DoesntEmpty)
|
||||
player->doesntEmpty->add(output);
|
||||
|
||||
@@ -69,6 +69,8 @@ MTGCardInstance::MTGCardInstance(MTGCard * card, MTGPlayerCards * arg_belongs_to
|
||||
cardistargetted = 0;
|
||||
cardistargetter = 0;
|
||||
myconvertedcost = getManaCost()->getConvertedCost();
|
||||
revealedLast = NULL;
|
||||
MadnessPlay = false;
|
||||
}
|
||||
|
||||
MTGCardInstance * MTGCardInstance::createSnapShot()
|
||||
@@ -194,6 +196,7 @@ void MTGCardInstance::initMTGCI()
|
||||
wasDealtDamage = false;
|
||||
isDualWielding = false;
|
||||
suspended = false;
|
||||
isBestowed = false;
|
||||
castMethod = Constants::NOT_CAST;
|
||||
mPropertiesChangedSinceLastUpdate = false;
|
||||
stillNeeded = true;
|
||||
@@ -222,6 +225,7 @@ void MTGCardInstance::initMTGCI()
|
||||
imprintW = 0;
|
||||
currentimprintName = "";
|
||||
imprintedNames.clear();
|
||||
CountedObjects = 0;
|
||||
|
||||
for (int i = 0; i < ManaCost::MANA_PAID_WITH_SUSPEND +1; i++)
|
||||
alternateCostPaid[i] = 0;
|
||||
@@ -870,7 +874,7 @@ int MTGCardInstance::canBlock(MTGCardInstance * opponent)
|
||||
return 0;
|
||||
if (opponent->basicAbilities[(int)Constants::ONEBLOCKER] && opponent->blocked)
|
||||
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;
|
||||
if(opponent->basicAbilities[(int)Constants::STRONG] && power < opponent->power)
|
||||
return 0;
|
||||
@@ -1266,7 +1270,7 @@ int MTGCardInstance::setDefenser(MTGCardInstance * opponent)
|
||||
if (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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,8 +105,19 @@ int MTGAllCards::processConfLine(string &s, MTGCard *card, CardPrimitive * primi
|
||||
}
|
||||
break;
|
||||
|
||||
case 'b': //buyback
|
||||
case 'b': //buyback/Bestow
|
||||
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())
|
||||
{
|
||||
string value = val;
|
||||
|
||||
@@ -26,6 +26,7 @@ const string Constants::kFlashBackKeyword = "flashback";
|
||||
const string Constants::kRetraceKeyword = "retrace";
|
||||
const string Constants::kKickerKeyword = "kicker";
|
||||
const string Constants::kMorphKeyword = "facedown";
|
||||
const string Constants::kBestowKeyword = "bestow";
|
||||
|
||||
int Constants::NB_Colors = 0; //Store the Max number of colors.
|
||||
|
||||
@@ -157,7 +158,11 @@ const char* Constants::MTGBasicAbilities[] = {
|
||||
"cantchangelife",
|
||||
"combattoughness",
|
||||
"cantpaylife",
|
||||
"cantbesacrified"
|
||||
"cantbesacrified",
|
||||
"skulk",
|
||||
"menace",
|
||||
"nosolo",
|
||||
"mustblock"
|
||||
};
|
||||
|
||||
map<string,int> Constants::MTGBasicAbilitiesMap;
|
||||
|
||||
@@ -9,6 +9,7 @@ MTGGamePhase::MTGGamePhase(GameObserver* g, int id) :
|
||||
animation = 0;
|
||||
currentState = -1;
|
||||
mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT);
|
||||
if(mFont)
|
||||
mFont->SetBase(0); // using 2nd font
|
||||
}
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ MTGPlayerCards::~MTGPlayerCards()
|
||||
SAFE_DELETE(stack);
|
||||
SAFE_DELETE(removedFromGame);
|
||||
SAFE_DELETE(garbage);
|
||||
SAFE_DELETE(reveal);
|
||||
SAFE_DELETE(temp);
|
||||
SAFE_DELETE(playRestrictions);
|
||||
}
|
||||
@@ -91,6 +92,7 @@ void MTGPlayerCards::beforeBeginPhase()
|
||||
stack->beforeBeginPhase();
|
||||
removedFromGame->beforeBeginPhase();
|
||||
garbage->beforeBeginPhase();
|
||||
reveal->beforeBeginPhase();
|
||||
temp->beforeBeginPhase();
|
||||
}
|
||||
|
||||
@@ -105,6 +107,7 @@ void MTGPlayerCards::setOwner(Player * player)
|
||||
stack->setOwner(player);
|
||||
garbage->setOwner(player);
|
||||
garbageLastTurn->setOwner(player);
|
||||
reveal->setOwner(player);
|
||||
temp->setOwner(player);
|
||||
}
|
||||
|
||||
@@ -272,6 +275,7 @@ void MTGPlayerCards::init()
|
||||
exile = removedFromGame;
|
||||
garbage = NEW MTGGameZone();
|
||||
garbageLastTurn = garbage;
|
||||
reveal = NEW MTGGameZone();
|
||||
temp = NEW MTGGameZone();
|
||||
|
||||
playRestrictions = NEW PlayRestrictions();
|
||||
@@ -360,6 +364,12 @@ MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone
|
||||
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
|
||||
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))
|
||||
@@ -371,6 +381,7 @@ MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone
|
||||
|
||||
if (!(copy = from->removeCard(card, doCopy)))
|
||||
return NULL; //ERROR
|
||||
|
||||
if (card->miracle)
|
||||
{
|
||||
copy->miracle = true;
|
||||
@@ -435,11 +446,12 @@ MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone
|
||||
previous->next = NULL;
|
||||
SAFE_DELETE(previous);
|
||||
}
|
||||
|
||||
}
|
||||
if(!asCopy)
|
||||
{
|
||||
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);
|
||||
g->receiveEvent(e);
|
||||
@@ -995,6 +1007,14 @@ MTGGameZone * MTGGameZone::intToZone(int zoneId, Player * p, Player * p2)
|
||||
return p->opponent()->game->stack;
|
||||
case 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;
|
||||
switch (zoneId)
|
||||
@@ -1017,6 +1037,9 @@ MTGGameZone * MTGGameZone::intToZone(int zoneId, Player * p, Player * p2)
|
||||
case TARGET_CONTROLLER_STACK:
|
||||
return p2->game->stack;
|
||||
|
||||
case TARGET_CONTROLLER_REVEAL:
|
||||
return p2->game->reveal;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
@@ -1114,6 +1137,18 @@ MTGGameZone * MTGGameZone::intToZone(GameObserver *g, int zoneId, MTGCardInstanc
|
||||
if(source->playerTarget)
|
||||
return source->playerTarget->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:
|
||||
return NULL;
|
||||
}
|
||||
@@ -1141,6 +1176,8 @@ int MTGGameZone::zoneStringToId(string zoneName)
|
||||
|
||||
"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,
|
||||
@@ -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_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);
|
||||
|
||||
|
||||
@@ -367,9 +367,7 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card)
|
||||
return 0;
|
||||
Player * player = game->currentlyActing();
|
||||
ManaCost * cost = card->getManaCost();
|
||||
|
||||
//this handles extra cost payments at the moment a card is played.
|
||||
|
||||
if (cost->isExtraPaymentSet())
|
||||
{
|
||||
if (!game->targetListIsSet(card))
|
||||
@@ -383,7 +381,7 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card)
|
||||
game->mExtraPayment = cost->extraCosts;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ManaCost * previousManaPool = NEW ManaCost(player->getManaPool());
|
||||
int payResult = player->getManaPool()->pay(card->getManaCost());
|
||||
if (card->getManaCost()->getKicker() && (OptionKicker::KICKER_ALWAYS == options[Options::KICKERPAYMENT].number || card->controller()->isAI()))
|
||||
@@ -497,6 +495,9 @@ int MTGKickerRule::isReactingToClick(MTGCardInstance * card, ManaCost *)
|
||||
ManaCost * withKickerCost= NEW ManaCost(card->getManaCost());
|
||||
withKickerCost->add(card->getManaCost()->getKicker());
|
||||
//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
|
||||
withKickerCost->Dump();
|
||||
#endif
|
||||
@@ -532,7 +533,7 @@ int MTGKickerRule::reactToClick(MTGCardInstance * card)
|
||||
ManaCost * previousManaPool = NEW ManaCost(player->getManaPool());
|
||||
int payResult = player->getManaPool()->pay(card->getManaCost());
|
||||
if (card->getManaCost()->getKicker())
|
||||
{ //cost reduction/recalculation must be here or outside somehow...
|
||||
{
|
||||
ManaCost * withKickerCost= NEW ManaCost(card->getManaCost());
|
||||
withKickerCost->add(withKickerCost->getKicker());
|
||||
if (card->getManaCost()->getKicker()->isMulti)
|
||||
@@ -1345,7 +1346,68 @@ MTGOverloadRule * MTGOverloadRule::clone() const
|
||||
{
|
||||
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
|
||||
@@ -1425,7 +1487,6 @@ MTGBlockCostRule::MTGBlockCostRule(GameObserver* observer, int _id) :
|
||||
aType = MTGAbility::BLOCK_COST;
|
||||
scost = "Pay to block";
|
||||
}
|
||||
|
||||
int MTGBlockCostRule::isReactingToClick(MTGCardInstance * card, ManaCost *)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
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.
|
||||
reactToClick(card);
|
||||
if (!card->isAttacker() && card->has(Constants::TREASON) && p->isAI())
|
||||
@@ -1848,6 +1917,50 @@ PermanentAbility(observer, _id)
|
||||
|
||||
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))
|
||||
{
|
||||
|
||||
@@ -1866,6 +1979,25 @@ int MTGBlockRule::receiveEvent(WEvent *e)
|
||||
//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;
|
||||
|
||||
}
|
||||
|
||||
@@ -152,7 +152,8 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstan
|
||||
manaCost->addExtraCost(NEW SacrificeCost(tc));
|
||||
}
|
||||
break;
|
||||
case 'e': //Exile
|
||||
case 'e':
|
||||
//Exile
|
||||
manaCost->addExtraCost(NEW ExileTargetCost(tc));
|
||||
break;
|
||||
case 'h': //bounce (move to Hand)
|
||||
@@ -387,6 +388,7 @@ ManaCost::ManaCost(ManaCost * manaCost)
|
||||
FlashBack = NEW ManaCost( manaCost->FlashBack );
|
||||
morph = NEW ManaCost( manaCost->morph );
|
||||
suspend = NEW ManaCost( manaCost->suspend );
|
||||
Bestow = NEW ManaCost(manaCost->Bestow);
|
||||
|
||||
extraCosts = manaCost->extraCosts ? manaCost->extraCosts->clone() : NULL;
|
||||
manaUsedToCast = NULL;
|
||||
@@ -415,7 +417,8 @@ ManaCost::ManaCost(const ManaCost& manaCost)
|
||||
FlashBack = NEW ManaCost( manaCost.FlashBack );
|
||||
morph = NEW ManaCost( manaCost.morph );
|
||||
suspend = NEW ManaCost( manaCost.suspend );
|
||||
|
||||
Bestow = NEW ManaCost(manaCost.Bestow);
|
||||
|
||||
extraCosts = manaCost.extraCosts ? manaCost.extraCosts->clone() : NULL;
|
||||
manaUsedToCast = NULL;
|
||||
xColor = manaCost.xColor;
|
||||
@@ -438,6 +441,7 @@ ManaCost & ManaCost::operator= (const ManaCost & manaCost)
|
||||
FlashBack = manaCost.FlashBack;
|
||||
morph = manaCost.morph;
|
||||
suspend = manaCost.suspend;
|
||||
Bestow = manaCost.Bestow;
|
||||
manaUsedToCast = manaCost.manaUsedToCast;
|
||||
xColor = manaCost.xColor;
|
||||
}
|
||||
@@ -454,6 +458,7 @@ ManaCost::~ManaCost()
|
||||
SAFE_DELETE(Retrace);
|
||||
SAFE_DELETE(morph);
|
||||
SAFE_DELETE(suspend);
|
||||
SAFE_DELETE(Bestow);
|
||||
SAFE_DELETE(manaUsedToCast);
|
||||
|
||||
cost.erase(cost.begin() ,cost.end());
|
||||
@@ -539,6 +544,7 @@ void ManaCost::init()
|
||||
Retrace = NULL;
|
||||
morph = NULL;
|
||||
suspend = NULL;
|
||||
Bestow = NULL;
|
||||
manaUsedToCast = NULL;
|
||||
isMulti = false;
|
||||
xColor = -1;
|
||||
@@ -563,6 +569,7 @@ void ManaCost::resetCosts()
|
||||
SAFE_DELETE(Retrace);
|
||||
SAFE_DELETE(morph);
|
||||
SAFE_DELETE(suspend);
|
||||
SAFE_DELETE(Bestow);
|
||||
}
|
||||
|
||||
void ManaCost::copy(ManaCost * _manaCost)
|
||||
@@ -628,6 +635,12 @@ void ManaCost::copy(ManaCost * _manaCost)
|
||||
suspend = NEW ManaCost();
|
||||
suspend->copy(_manaCost->suspend);
|
||||
}
|
||||
SAFE_DELETE(Bestow);
|
||||
if (_manaCost->Bestow)
|
||||
{
|
||||
Bestow = NEW ManaCost();
|
||||
Bestow->copy(_manaCost->Bestow);
|
||||
}
|
||||
xColor = _manaCost->xColor;
|
||||
}
|
||||
|
||||
@@ -1092,6 +1105,7 @@ void ManaPool::Empty()
|
||||
SAFE_DELETE(Retrace);
|
||||
SAFE_DELETE(morph);
|
||||
SAFE_DELETE(suspend);
|
||||
SAFE_DELETE(Bestow);
|
||||
SAFE_DELETE(manaUsedToCast);
|
||||
init();
|
||||
WEvent * e = NEW WEventEmptyManaPool(this);
|
||||
|
||||
@@ -413,12 +413,13 @@ void Rules::initGame(GameObserver *g, bool currentPlayerSet)
|
||||
{
|
||||
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,
|
||||
initState.playerData[i].player->game->library,
|
||||
initState.playerData[i].player->game->hand,
|
||||
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++)
|
||||
{
|
||||
MTGGameZone * zone = playerZones[j];
|
||||
|
||||
@@ -156,6 +156,11 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
|
||||
{
|
||||
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)
|
||||
{
|
||||
zones[nbzones++] = MTGGameZone::MY_GRAVEYARD;
|
||||
@@ -637,15 +642,15 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
|
||||
}
|
||||
}
|
||||
|
||||
if (attribute.find("iscolorless") != string::npos)
|
||||
{
|
||||
attributefound = 1;
|
||||
for (int cid = 1; cid < Constants::NB_Colors; cid++)
|
||||
{
|
||||
cd->SetExclusionColor(cid);
|
||||
}
|
||||
cd->mode = CardDescriptor::CD_OR;
|
||||
}
|
||||
if (attribute.find("colorless") != string::npos)
|
||||
{
|
||||
attributefound = 1;
|
||||
for (int cid = 1; cid < Constants::NB_Colors; cid++)
|
||||
{
|
||||
cd->SetExclusionColor(cid);
|
||||
}
|
||||
cd->mode = CardDescriptor::CD_OR;
|
||||
}
|
||||
|
||||
if (attribute.find("chosencolor") != string::npos)
|
||||
{
|
||||
@@ -817,6 +822,7 @@ TargetChooser::TargetChooser(GameObserver *observer, MTGCardInstance * card, int
|
||||
TargetsList(), observer(observer)
|
||||
{
|
||||
forceTargetListReady = 0;
|
||||
forceTargetListReadyByPlayer = 0;
|
||||
source = card;
|
||||
targetter = card;
|
||||
maxtargets = _maxtargets;
|
||||
@@ -899,6 +905,10 @@ int TargetChooser::ForceTargetListReady()
|
||||
|
||||
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())
|
||||
{
|
||||
return TARGET_NOK;
|
||||
@@ -931,8 +941,8 @@ bool TargetChooser::validTargetsExist(int maxTargets)
|
||||
int maxAmount = 0;
|
||||
Player *p = observer->players[i];
|
||||
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 };
|
||||
for (int k = 0; k < 6; k++)
|
||||
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 < 7; k++)
|
||||
{
|
||||
MTGGameZone * z = zones[k];
|
||||
if (targetsZone(z))
|
||||
@@ -965,8 +975,8 @@ int TargetChooser::countValidTargets(bool withoutProtections)
|
||||
Player *p = observer->players[i];
|
||||
if(canTarget(p))
|
||||
result++;
|
||||
MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->exile, p->game->stack };
|
||||
for (int k = 0; k < 6; k++)
|
||||
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 < 7; k++)
|
||||
{
|
||||
MTGGameZone * z = zones[k];
|
||||
if (targetsZone(z))
|
||||
|
||||
@@ -123,6 +123,7 @@ WEventTarget::WEventTarget(MTGCardInstance * card,MTGCardInstance * source) :
|
||||
WEventCardUpdate(card),card(card),source(source)
|
||||
{
|
||||
card->cardistargetted = 1;
|
||||
if(source)
|
||||
source->cardistargetter = 1;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user