Merge remote-tracking branch 'refs/remotes/WagicProject/master'
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