Merge remote-tracking branch 'refs/remotes/WagicProject/master'

This commit is contained in:
Anthony Calosa
2016-06-29 08:26:31 +08:00
29 changed files with 3854 additions and 2289 deletions
+1
View File
@@ -35,6 +35,7 @@ auto=lifelinkrule
auto=deathtouchrule auto=deathtouchrule
auto=soulbondrule auto=soulbondrule
auto=dredgerule auto=dredgerule
auto=bestowrule
[PLAYERS] [PLAYERS]
life:20 life:20
+186 -7
View File
@@ -38,6 +38,117 @@ public:
virtual MTGEventText * clone() const; virtual MTGEventText * clone() const;
}; };
class MTGRevealingCards : public MTGAbility, public CardDisplay
{
public:
vector<CardView*> cards;
Player * playerForZone;
MTGGameZone * RevealZone;
MTGGameZone * RevealFromZone;
string revealCertainTypes;
string revealUntil;
CardDisplay * revealDisplay;
vector<CardDisplay*>trashDisplays;//used for repeat
int nbCard;
string abilityString;
string number;
string abilityOne;
string abilityTwo;
string afterReveal;
bool afterEffectActivated;
MTGAbility * abilityToCast;
MTGAbility * abilityFirst;
MTGAbility * abilitySecond;
MTGAbility * abilityAfter;
vector<MTGAbility*>abilities;
bool repeat;//only the first ability can be repeated, and it must be targeted.
bool initCD;
void Update(float dt);
int testDestroy();
int toResolve();
void CardViewBackup(MTGCardInstance * backup);
void Render();
bool CheckUserInput(JButton key);
MTGAbility * contructAbility(string abilityToMake = "");
MTGRevealingCards(GameObserver* observer, int _id, MTGCardInstance * card, string text);
virtual MTGRevealingCards * clone() const;
~MTGRevealingCards();
int receiveEvent(WEvent*);
};
class RevealDisplay : public CardDisplay
{
public:
RevealDisplay(int id, GameObserver* game, int x, int y, JGuiListener * listener = NULL, TargetChooser * tc = NULL,
int nb_displayed_items = 7);
void AddCard(MTGCardInstance * _card);
bool CheckUserInput(JButton key);
};
class GenericRevealAbility : public ActivatedAbility
{
public:
string howMany;
MTGRevealingCards * ability;
GenericRevealAbility(GameObserver* observer, int id, MTGCardInstance * source, Targetable * target, string _howMany);
int resolve();
const string getMenuText();
GenericRevealAbility * clone() const;
~GenericRevealAbility();
};
class MTGScryCards : public MTGAbility, public CardDisplay
{
public:
vector<CardView*> cards;
MTGGameZone * RevealZone;
MTGGameZone * RevealFromZone;
CardDisplay * revealDisplay;
vector<CardDisplay*>trashDisplays;//used for repeat
int nbCard;
bool delayed;
bool dontRevealAfter;
int revealTopAmount;
string delayedAbilityString;
string abilityString;
string number;
string abilityOne;
string abilityTwo;
MTGAbility * abilityToCast;
MTGAbility * abilityFirst;
MTGAbility * abilitySecond;
vector<MTGAbility*>abilities;
bool initCD;
void Update(float dt);
int testDestroy();
void initDisplay(int value = 0);
int toResolve();
void Render();
bool CheckUserInput(JButton key);
MTGAbility * contructAbility(string abilityToMake = "");
MTGScryCards(GameObserver* observer, int _id, MTGCardInstance * card, string text);
virtual MTGScryCards * clone() const;
~MTGScryCards();
int receiveEvent(WEvent*);
};
class GenericScryAbility : public ActivatedAbility
{
public:
string howMany;
MTGScryCards * ability;
GenericScryAbility(GameObserver* observer, int id, MTGCardInstance * source, Targetable * target, string _howMany);
int resolve();
const string getMenuText();
GenericScryAbility * clone() const;
~GenericScryAbility();
};
class WParsedInt class WParsedInt
{ {
public: public:
@@ -240,6 +351,10 @@ private:
{ {
intValue = countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLUE,Constants::MTG_COLOR_GREEN); intValue = countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLUE,Constants::MTG_COLOR_GREEN);
} }
else if (s == "Iroas")//devotion to red white
{
intValue = countDevotionTo(card, card->controller()->inPlay(), Constants::MTG_COLOR_RED, Constants::MTG_COLOR_WHITE);
}
else if (s.find("type:") != string::npos) else if (s.find("type:") != string::npos)
{ {
size_t begins = s.find("type:"); size_t begins = s.find("type:");
@@ -556,6 +671,10 @@ private:
{ {
intValue = target->getCurrentToughness(); intValue = target->getCurrentToughness();
} }
else if (s == "countedamount")
{
intValue = target->CountedObjects;
}
else if (s == "kicked") else if (s == "kicked")
{ {
intValue = target->kicked; intValue = target->kicked;
@@ -745,6 +864,21 @@ private:
intValue += card->controller()->game->inPlay->cards[j]->power; intValue += card->controller()->game->inPlay->cards[j]->power;
} }
} }
else if (s == "revealedp")
{
if (card->revealedLast)
intValue = card->revealedLast->power;
}
else if (s == "revealedt")
{
if (card->revealedLast)
intValue = card->revealedLast->toughness;
}
else if (s == "revealedmana")
{
if (card->revealedLast)
intValue = card->revealedLast->getManaCost()->getConvertedCost();
}
else else
{ {
intValue = atoi(s.c_str()); intValue = atoi(s.c_str());
@@ -2855,7 +2989,6 @@ public:
return NEW ARegularLifeModifierAura(*this); return NEW ARegularLifeModifierAura(*this);
} }
}; };
//Generic Kird Ape //Generic Kird Ape
class AAsLongAs: public ListMaintainerAbility, public NestedAbility class AAsLongAs: public ListMaintainerAbility, public NestedAbility
{ {
@@ -3334,6 +3467,7 @@ public:
list<int> colors; list<int> colors;
int power, toughness; int power, toughness;
int tokenId; int tokenId;
string _cardName;
string name; string name;
string sabilities; string sabilities;
string starfound; string starfound;
@@ -3345,6 +3479,7 @@ public:
MTGCardInstance * myToken; MTGCardInstance * myToken;
vector<MTGAbility *> currentAbilities; vector<MTGAbility *> currentAbilities;
Player * tokenReciever; Player * tokenReciever;
//by id
ATokenCreator(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable *, ManaCost * _cost, int tokenId,string starfound, WParsedInt * multiplier = NULL, ATokenCreator(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable *, ManaCost * _cost, int tokenId,string starfound, WParsedInt * multiplier = NULL,
int who = 0,bool aLivingWeapon = false) : int who = 0,bool aLivingWeapon = false) :
ActivatedAbility(observer, _id, _source, _cost, 0), tokenId(tokenId), starfound(starfound),multiplier(multiplier), who(who),aLivingWeapon(aLivingWeapon) ActivatedAbility(observer, _id, _source, _cost, 0), tokenId(tokenId), starfound(starfound),multiplier(multiplier), who(who),aLivingWeapon(aLivingWeapon)
@@ -3354,7 +3489,18 @@ public:
if (card) name = card->data->getName(); if (card) name = card->data->getName();
battleReady = false; battleReady = false;
} }
//by name, card still require valid card.dat info, this just makes the primitive code far more readable. token(Eldrazi scion) instead of token(-1234234)...
ATokenCreator(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable *, ManaCost * _cost, string cardName, string starfound, WParsedInt * multiplier = NULL,
int who = 0, bool aLivingWeapon = false) :
ActivatedAbility(observer, _id, _source, _cost, 0), _cardName(cardName), starfound(starfound), multiplier(multiplier), who(who), aLivingWeapon(aLivingWeapon)
{
if (!multiplier) this->multiplier = NEW WParsedInt(1);
MTGCard * card = MTGCollection()->getCardByName(_cardName);
tokenId = card->getId();
if (card) name = card->data->getName();
battleReady = false;
}
//by construction
ATokenCreator(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable *, ManaCost * _cost, string sname, string stypes, int _power, int _toughness, ATokenCreator(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable *, ManaCost * _cost, string sname, string stypes, int _power, int _toughness,
string sabilities, string starfound,WParsedInt * multiplier = NULL, int _who = 0,bool aLivingWeapon = false,string spt = "") : string sabilities, string starfound,WParsedInt * multiplier = NULL, int _who = 0,bool aLivingWeapon = false,string spt = "") :
ActivatedAbility(observer, _id, _source, _cost, 0),sabilities(sabilities),starfound(starfound), multiplier(multiplier), who(_who),aLivingWeapon(aLivingWeapon),spt(spt) ActivatedAbility(observer, _id, _source, _cost, 0),sabilities(sabilities),starfound(starfound), multiplier(multiplier), who(_who),aLivingWeapon(aLivingWeapon),spt(spt)
@@ -3877,10 +4023,12 @@ class AThis: public MTGAbility, public NestedAbility
public: public:
MTGAbility * a; MTGAbility * a;
ThisDescriptor * td; ThisDescriptor * td;
AThis(GameObserver* observer, int _id, MTGCardInstance * _source, Damageable * _target, ThisDescriptor * _td, MTGAbility * ability) : string restrictionCheck;
AThis(GameObserver* observer, int _id, MTGCardInstance * _source, Damageable * _target, ThisDescriptor * _td, MTGAbility * ability, string restriction = "") :
MTGAbility(observer, _id, _source, _target), NestedAbility(ability) MTGAbility(observer, _id, _source, _target), NestedAbility(ability)
{ {
td = _td; td = _td;
restrictionCheck = restriction;
ability->source = source; ability->source = source;
ability->target = target; ability->target = target;
a = NULL; a = NULL;
@@ -3904,9 +4052,18 @@ public:
int resolve() int resolve()
{ {
//TODO check if ability is oneShot ? int match = 0;
int match; if (td)
{
match = td->match(source); match = td->match(source);
}
else
{//restriction check instead of Targetchooser
AbilityFactory abf(target->getObserver());
int checkCond = abf.parseCastRestrictions(source, source->controller(), restrictionCheck);
if (checkCond)
match = 1;
}
if (match > 0) if (match > 0)
{ {
addAbilityToGame(); addAbilityToGame();
@@ -3953,6 +4110,7 @@ public:
{ {
AThis * a = NEW AThis(*this); AThis * a = NEW AThis(*this);
a->ability = ability->clone(); a->ability = ability->clone();
if(a->td)
a->td = td->clone(); a->td = td->clone();
return a; return a;
} }
@@ -4166,6 +4324,16 @@ public:
return NEW TADamager(*this); return NEW TADamager(*this);
} }
}; };
//bestow
class ABestow : public ActivatedAbility
{
public:
MTGCardInstance * _card;
ABestow(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target, ManaCost * _cost = NULL);
int resolve();
const string getMenuText();
ABestow * clone() const;
};
/* Can tap a target for a cost */ /* Can tap a target for a cost */
class AATapper: public ActivatedAbility class AATapper: public ActivatedAbility
@@ -4197,12 +4365,22 @@ public:
int resolve(); int resolve();
AAWhatsMax * clone() const; AAWhatsMax * clone() const;
}; };
//counts a targetchooser for use later by other effects
class AACountObject : public ActivatedAbility
{
public:
string value;
AACountObject(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * source, ManaCost * _cost = NULL, string value ="");
int resolve();
AACountObject * clone() const;
};
/* Can prevent a card from untapping next untap */ /* Can prevent a card from untapping next untap */
class AAFrozen: public ActivatedAbility class AAFrozen: public ActivatedAbility
{ {
public: public:
AAFrozen(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target, ManaCost * _cost = NULL); bool freeze;
AAFrozen(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target, bool tap, ManaCost * _cost = NULL);
int resolve(); int resolve();
const string getMenuText(); const string getMenuText();
AAFrozen * clone() const; AAFrozen * clone() const;
@@ -6205,7 +6383,8 @@ public:
MTGCardInstance * theNamedCard; MTGCardInstance * theNamedCard;
bool noEvent; bool noEvent;
bool putinplay; bool putinplay;
AACastCard(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target,bool restricted,bool copied,bool _asNormal,string nameCard,string abilityName,bool _noEvent, bool putinplay); bool asNormalMadness;
AACastCard(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target,bool restricted,bool copied,bool _asNormal,string nameCard,string abilityName,bool _noEvent, bool putinplay,bool asNormalMadness = false);
int testDestroy(){return 0;}; int testDestroy(){return 0;};
void Update(float dt); void Update(float dt);
+1
View File
@@ -80,6 +80,7 @@ class GameObserver{
ExtraCosts * mExtraPayment; ExtraCosts * mExtraPayment;
int oldGamePhase; int oldGamePhase;
TargetChooser * targetChooser; TargetChooser * targetChooser;
CardDisplay * OpenedDisplay;
DuelLayers * mLayers; DuelLayers * mLayers;
ReplacementEffects *replacementEffects; ReplacementEffects *replacementEffects;
vector<Player *> players; //created outside vector<Player *> players; //created outside
+1
View File
@@ -121,6 +121,7 @@ public:
ManaCost* BuyBack; ManaCost* BuyBack;
ManaCost* FlashBack; ManaCost* FlashBack;
ManaCost* Retrace; ManaCost* Retrace;
ManaCost* Bestow;
ManaCost* morph; ManaCost* morph;
ManaCost* suspend; ManaCost* suspend;
+4
View File
@@ -95,6 +95,7 @@ public:
bool exileEffects; bool exileEffects;
bool suspended; bool suspended;
bool miracle; bool miracle;
bool isBestowed;
int chooseacolor; int chooseacolor;
string chooseasubtype; string chooseasubtype;
int coinSide;//1 = tails int coinSide;//1 = tails
@@ -105,6 +106,7 @@ public:
int notblocked; int notblocked;
int fresh; int fresh;
int MaxLevelUp; int MaxLevelUp;
int CountedObjects;
int kicked; int kicked;
int dredge; int dredge;
bool isDualWielding; bool isDualWielding;
@@ -272,6 +274,8 @@ public:
string currentimprintName; string currentimprintName;
vector<string>imprintedNames; vector<string>imprintedNames;
MTGCardInstance * revealedLast;//last card revealed by a ability this card owns.
bool MadnessPlay;
void eventattacked(); void eventattacked();
void eventattackedAlone(); void eventattackedAlone();
void eventattackednotblocked(); void eventattackednotblocked();
+7 -2
View File
@@ -82,6 +82,7 @@ class Constants
static const string kRetraceKeyword; static const string kRetraceKeyword;
static const string kKickerKeyword; static const string kKickerKeyword;
static const string kMorphKeyword; static const string kMorphKeyword;
static const string kBestowKeyword;
// used for deck statistics // used for deck statistics
static const int STATS_FOR_TURNS = 8; static const int STATS_FOR_TURNS = 8;
@@ -246,8 +247,11 @@ class Constants
COMBATTOUGHNESS = 125, COMBATTOUGHNESS = 125,
CANTPAYLIFE = 126, CANTPAYLIFE = 126,
CANTBESACRIFIED = 127, CANTBESACRIFIED = 127,
NB_BASIC_ABILITIES = 128, SKULK = 128,
MENACE = 129,
NOSOLO = 130,//cant attack alone
MUSTBLOCK = 131,//blocks each turn
NB_BASIC_ABILITIES = 132,
RARITY_S = 'S', //Special Rarity RARITY_S = 'S', //Special Rarity
RARITY_M = 'M', //Mythics RARITY_M = 'M', //Mythics
@@ -308,6 +312,7 @@ class Constants
CAST_WITH_RETRACE = 6, CAST_WITH_RETRACE = 6,
CAST_WITH_MORPH = 7, CAST_WITH_MORPH = 7,
CAST_WITH_SUSPEND = 8, CAST_WITH_SUSPEND = 8,
CAST_WITH_BESTOW = 9,
CAST_ALTERNATE = -1, //matches all alternate costs, including itself CAST_ALTERNATE = -1, //matches all alternate costs, including itself
CAST_ALL = -2, // matches everything except NOT_CAST CAST_ALL = -2, // matches everything except NOT_CAST
+9
View File
@@ -72,6 +72,14 @@ class MTGGameZone {
OWNER_STACK = 66, OWNER_STACK = 66,
TARGETED_PLAYER_STACK = 67, TARGETED_PLAYER_STACK = 67,
MY_REVEAL = 71,
OPPONENT_REVEAL = 72,
TARGET_OWNER_REVEAL = 73,
TARGET_CONTROLLER_REVEAL = 74,
REVEAL = 75,
OWNER_REVEAL = 76,
TARGETED_PLAYER_REVEAL = 77,
}; };
Player * owner; Player * owner;
@@ -194,6 +202,7 @@ public:
MTGRemovedFromGame * exile; //alias to removedFromZone MTGRemovedFromGame * exile; //alias to removedFromZone
MTGGameZone * garbage; MTGGameZone * garbage;
MTGGameZone * garbageLastTurn; MTGGameZone * garbageLastTurn;
MTGGameZone * reveal;
MTGGameZone * temp; MTGGameZone * temp;
MTGPlayerCards(); MTGPlayerCards();
+15
View File
@@ -206,6 +206,21 @@ public:
virtual MTGOverloadRule * clone() const; virtual MTGOverloadRule * clone() const;
}; };
class MTGBestowRule : public MTGAlternativeCostRule
{
public:
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL);
int reactToClick(MTGCardInstance * card);
virtual ostream& toString(ostream& out) const;
MTGBestowRule(GameObserver* observer, int _id);
const string getMenuText()
{
return "Bestow";
}
virtual MTGBestowRule * clone() const;
};
class MTGSuspendRule: public MTGAlternativeCostRule class MTGSuspendRule: public MTGAlternativeCostRule
{ {
public: public:
+4
View File
@@ -31,6 +31,7 @@ protected:
ManaCost * manaUsedToCast; ManaCost * manaUsedToCast;
ManaCost * morph; ManaCost * morph;
ManaCost * Retrace; ManaCost * Retrace;
ManaCost * Bestow;
ManaCost * FlashBack; ManaCost * FlashBack;
ManaCost * BuyBack; ManaCost * BuyBack;
ManaCost * kicker; ManaCost * kicker;
@@ -75,6 +76,9 @@ public:
ManaCost * getSuspend(){ return suspend; }; ManaCost * getSuspend(){ return suspend; };
void setSuspend(ManaCost * aMana){ SAFE_DELETE(suspend); suspend = aMana;}; void setSuspend(ManaCost * aMana){ SAFE_DELETE(suspend); suspend = aMana;};
ManaCost * getBestow() { return Bestow; };
void setBestow(ManaCost * aMana) { SAFE_DELETE(Bestow); Bestow = aMana; };
ManaCost * getManaUsedToCast(){ return manaUsedToCast; }; ManaCost * getManaUsedToCast(){ return manaUsedToCast; };
void setManaUsedToCast(ManaCost * aMana){ SAFE_DELETE(manaUsedToCast); manaUsedToCast = aMana;}; void setManaUsedToCast(ManaCost * aMana){ SAFE_DELETE(manaUsedToCast); manaUsedToCast = aMana;};
+1
View File
@@ -25,6 +25,7 @@ class TargetChooser: public TargetsList
protected: protected:
int forceTargetListReady; int forceTargetListReady;
public: public:
int forceTargetListReadyByPlayer;
const static int UNLITMITED_TARGETS = 1000; const static int UNLITMITED_TARGETS = 1000;
enum enum
{ {
+4 -4
View File
@@ -1221,7 +1221,7 @@ int AIPlayerBaka::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, Rank
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
Player * p = observer->players[i]; Player * p = observer->players[i];
MTGGameZone * playerZones[] = { p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay,p->game->stack,p->game->exile }; MTGGameZone * playerZones[] = { p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay,p->game->stack,p->game->exile, p->game->reveal };
if(a->getActionTc()->canTarget((Targetable*)p)) if(a->getActionTc()->canTarget((Targetable*)p))
{ {
if(a->getActionTc()->maxtargets == 1) if(a->getActionTc()->maxtargets == 1)
@@ -1352,7 +1352,7 @@ int AIPlayerBaka::selectHintAbility()
int AIPlayerBaka::selectAbility() int AIPlayerBaka::selectAbility()
{ {
if(observer->mExtraPayment && observer->mExtraPayment->source->controller() == this) if(observer->mExtraPayment && observer->mExtraPayment->source && observer->mExtraPayment->source->controller() == this)
{ {
ExtraManaCost * check = NULL; ExtraManaCost * check = NULL;
check = dynamic_cast<ExtraManaCost*>(observer->mExtraPayment->costs[0]); check = dynamic_cast<ExtraManaCost*>(observer->mExtraPayment->costs[0]);
@@ -1560,8 +1560,8 @@ int AIPlayerBaka::chooseTarget(TargetChooser * _tc, Player * forceTarget,MTGCard
} }
} }
MTGPlayerCards * playerZones = target->game; MTGPlayerCards * playerZones = target->game;
MTGGameZone * zones[] = { playerZones->hand, playerZones->library, playerZones->inPlay, playerZones->graveyard,playerZones->stack,playerZones->exile }; MTGGameZone * zones[] = { playerZones->hand, playerZones->library, playerZones->inPlay, playerZones->graveyard,playerZones->stack,playerZones->exile,playerZones->reveal };
for (int j = 0; j < 6; j++) for (int j = 0; j < 7; j++)
{ {
MTGGameZone * zone = zones[j]; MTGGameZone * zone = zones[j];
for (int k = 0; k < zone->nb_cards; k++) for (int k = 0; k < zone->nb_cards; k++)
+6 -3
View File
@@ -77,7 +77,7 @@ void ActionLayer::cleanGarbage()
int ActionLayer::reactToClick(ActionElement * ability, MTGCardInstance * card) int ActionLayer::reactToClick(ActionElement * ability, MTGCardInstance * card)
{ {
int result = ability->reactToClick(card); int result = ability?ability->reactToClick(card):0;
if (result) if (result)
stuffHappened = 1; stuffHappened = 1;
return result; return result;
@@ -186,8 +186,11 @@ void ActionLayer::Update(float dt)
without this, the game locks into a freeze state while you try to select the targets and dont have enough to without this, the game locks into a freeze state while you try to select the targets and dont have enough to
fill the maxtargets list. fill the maxtargets list.
*/ */
if(int(ae->getActionTc()->getNbTargets()) == countTargets-1) if (int(ae->getActionTc()->getNbTargets()) == countTargets)//if the amount of targets is equal the all we can target
ae->getActionTc()->done = true; {
ae->getActionTc()->done = true;//were done
ae->getActionTc()->source->getObserver()->cardClick(ae->getActionTc()->source, 0, false);//click source.
}
} }
} }
} }
+4
View File
@@ -578,6 +578,10 @@ int ActionStack::addAbility(MTGAbility * ability)
if (!observer->players[0]->isAI() && ability->source->controller() == observer->players[0] && 0 if (!observer->players[0]->isAI() && ability->source->controller() == observer->players[0] && 0
== options[Options::INTERRUPTMYABILITIES].number) == options[Options::INTERRUPTMYABILITIES].number)
interruptDecision[0] = DONT_INTERRUPT; interruptDecision[0] = DONT_INTERRUPT;
if (observer->OpenedDisplay && observer->players[0]->game->reveal->cards.size())
{
interruptDecision[0] = DONT_INTERRUPT;
}
return result; return result;
} }
File diff suppressed because it is too large Load Diff
+4 -2
View File
@@ -756,9 +756,10 @@ int TapTargetCost::isPaymentSet()
int TapTargetCost::doPay() int TapTargetCost::doPay()
{ {
MTGCardInstance * _target = (MTGCardInstance *) target; MTGCardInstance * _target = (MTGCardInstance *) target;
source->storedCard = target->createSnapShot();
if (target) if (target)
{ {
source->storedCard = target->createSnapShot();
_target->tap(); _target->tap();
target = NULL; target = NULL;
if (tc) if (tc)
@@ -799,9 +800,10 @@ int UnTapTargetCost::isPaymentSet()
int UnTapTargetCost::doPay() int UnTapTargetCost::doPay()
{ {
MTGCardInstance * _target = (MTGCardInstance *) target; MTGCardInstance * _target = (MTGCardInstance *) target;
source->storedCard = target->createSnapShot();
if (target) if (target)
{ {
source->storedCard = target->createSnapShot();
_target->untap(); _target->untap();
target = NULL; target = NULL;
if (tc) if (tc)
+52 -3
View File
@@ -51,6 +51,7 @@ void GameObserver::cleanup()
connectRule = false; connectRule = false;
actionsList.clear(); actionsList.clear();
gameTurn.clear(); gameTurn.clear();
OpenedDisplay = NULL;
} }
GameObserver::~GameObserver() GameObserver::~GameObserver()
@@ -93,6 +94,7 @@ GameObserver::GameObserver(WResourceManager *output, JGE* input)
targetChooser = NULL; targetChooser = NULL;
cardWaitingForTargets = NULL; cardWaitingForTargets = NULL;
mExtraPayment = NULL; mExtraPayment = NULL;
OpenedDisplay = NULL;
gameOver = NULL; gameOver = NULL;
phaseRing = NULL; phaseRing = NULL;
replacementEffects = NEW ReplacementEffects(); replacementEffects = NEW ReplacementEffects();
@@ -322,7 +324,11 @@ void GameObserver::userRequestNextGamePhase(bool allowInterrupt, bool log)
// Here's what I find weird - if the extra cost is something like a sacrifice, doesn't that imply a TargetChooser? // Here's what I find weird - if the extra cost is something like a sacrifice, doesn't that imply a TargetChooser?
if (WaitForExtraPayment(NULL)) if (WaitForExtraPayment(NULL))
return; return;
/*if (OpenedDisplay)//dont let us fly through all the phases with grave and library box still open.
{
return;//I want this here, but it locks up on opponents turn, we need to come up with a clever way to close opened
//displays, it makes no sense that you travel through 4 or 5 phases with library or grave still open.
}*/
Phase * cPhaseOld = phaseRing->getCurrentPhase(); Phase * cPhaseOld = phaseRing->getCurrentPhase();
if (allowInterrupt && ((cPhaseOld->id == MTG_PHASE_COMBATBLOCKERS && combatStep == ORDER) if (allowInterrupt && ((cPhaseOld->id == MTG_PHASE_COMBATBLOCKERS && combatStep == ORDER)
|| (cPhaseOld->id == MTG_PHASE_COMBATBLOCKERS && combatStep == TRIGGERS) || (cPhaseOld->id == MTG_PHASE_COMBATBLOCKERS && combatStep == TRIGGERS)
@@ -727,12 +733,20 @@ void GameObserver::gameStateBasedEffects()
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
//Remove auras that don't have a valid target anymore// //Remove auras that don't have a valid target anymore//
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
if (card->target && !isInPlay(card->target) && card->isBestowed && card->hasType("aura"))
{
card->removeType("aura");
card->addType("creature");
card->target = NULL;
card->isBestowed = false;
}
if ((card->target||card->playerTarget) && !card->hasType(Subtypes::TYPE_EQUIPMENT)) if ((card->target||card->playerTarget) && !card->hasType(Subtypes::TYPE_EQUIPMENT))
{ {
if(card->target && !isInPlay(card->target)) if(card->target && !isInPlay(card->target))
players[i]->game->putInGraveyard(card); players[i]->game->putInGraveyard(card);
if(card->target && isInPlay(card->target)) if(card->target && isInPlay(card->target))
{ {//what exactly does this section do?
if(card->spellTargetType.find("creature") != string::npos && !card->target->hasType("creature")) if(card->spellTargetType.find("creature") != string::npos && !card->target->hasType("creature"))
players[i]->game->putInGraveyard(card); players[i]->game->putInGraveyard(card);
if(card->spellTargetType.find("artifact") != string::npos && !card->target->hasType("artifact")) if(card->spellTargetType.find("artifact") != string::npos && !card->target->hasType("artifact"))
@@ -1029,9 +1043,41 @@ void GameObserver::Affinity()
if (!card) if (!card)
continue; continue;
bool NewAffinityFound = false;
for (unsigned int na = 0; na < card->cardsAbilities.size(); na++)
{
if (!card->cardsAbilities[na])
break;
ANewAffinity * newAff = dynamic_cast<ANewAffinity*>(card->cardsAbilities[na]);
if (newAff)
{
NewAffinityFound = true;
}
}
bool DoReduceIncrease = false;
if (card->has(Constants::AFFINITYARTIFACTS) ||
card->has(Constants::AFFINITYFOREST) ||
card->has(Constants::AFFINITYGREENCREATURES) ||
card->has(Constants::AFFINITYISLAND) ||
card->has(Constants::AFFINITYMOUNTAIN) ||
card->has(Constants::AFFINITYPLAINS) ||
card->has(Constants::AFFINITYSWAMP) ||
card->has(Constants::TRINISPHERE) ||
card->getIncreasedManaCost()->getConvertedCost() ||
card->getReducedManaCost()->getConvertedCost() ||
NewAffinityFound)
DoReduceIncrease = true;
if (!DoReduceIncrease)
continue;
//above we check if there are even any cards that effect cards manacost
//if there are none, leave this function. manacost->copy( is a very expensive funtion
//1mb a sec to run at all time even when no known reducers or increasers are in play.
//memory snapshot shots pointed to this as such a heavy load that games with many cards inplay
//would slow to a crawl.
//only do any of the following if a card with the stated ability is in your hand.
int color = 0; int color = 0;
string type = ""; string type = "";
//only do any of the following if a card with the stated ability is in your hand.
ManaCost * original = NEW ManaCost(); ManaCost * original = NEW ManaCost();
original->copy(card->model->data->getManaCost()); original->copy(card->model->data->getManaCost());
if(card->getIncreasedManaCost()->getConvertedCost()||card->getReducedManaCost()->getConvertedCost()) if(card->getIncreasedManaCost()->getConvertedCost()||card->getReducedManaCost()->getConvertedCost())
@@ -1054,6 +1100,8 @@ void GameObserver::Affinity()
bool resetCost = false; bool resetCost = false;
for(unsigned int na = 0; na < card->cardsAbilities.size();na++) for(unsigned int na = 0; na < card->cardsAbilities.size();na++)
{//start2 {//start2
if (!card->cardsAbilities[na])
break;
ANewAffinity * newAff = dynamic_cast<ANewAffinity*>(card->cardsAbilities[na]); ANewAffinity * newAff = dynamic_cast<ANewAffinity*>(card->cardsAbilities[na]);
if(newAff) if(newAff)
{ {
@@ -1372,6 +1420,7 @@ int GameObserver::cardClick(MTGCardInstance * card, Targetable * object, bool lo
int _result = targetChooser->ForceTargetListReady(); int _result = targetChooser->ForceTargetListReady();
if(targetChooser->targetMin && int(targetChooser->getNbTargets()) < targetChooser->maxtargets) if(targetChooser->targetMin && int(targetChooser->getNbTargets()) < targetChooser->maxtargets)
_result = 0; _result = 0;
if (_result) if (_result)
{ {
result = TARGET_OK_FULL; result = TARGET_OK_FULL;
+2 -1
View File
@@ -48,7 +48,8 @@ void GameStateOptions::Start()
} }
optionsList->Add(NEW OptionInteger(Options::INTERRUPT_SECONDS, "Seconds to pause for an Interrupt", 20, 1)); optionsList->Add(NEW OptionInteger(Options::INTERRUPT_SECONDS, "Seconds to pause for an Interrupt", 20, 1));
optionsList->Add(NEW OptionInteger(Options::INTERRUPTMYSPELLS, "Interrupt my spells")); optionsList->Add(NEW OptionInteger(Options::INTERRUPTMYSPELLS, "Interrupt my spells"));
optionsList->Add(NEW OptionInteger(Options::INTERRUPTMYABILITIES, "Interrupt my abilities")); // optionsList->Add(NEW OptionInteger(Options::INTERRUPTMYABILITIES, "Interrupt my abilities"));
//this is a dev option, not meant for standard play. uncomment if you need to see abilities you own hitting the stack.
optionsList->Add(NEW OptionInteger(Options::INTERRUPT_SECONDMAIN, "Interrupt opponent's end of turn")); optionsList->Add(NEW OptionInteger(Options::INTERRUPT_SECONDMAIN, "Interrupt opponent's end of turn"));
optionsTabs = NEW WGuiTabMenu(); optionsTabs = NEW WGuiTabMenu();
optionsTabs->Add(optionsList); optionsTabs->Add(optionsList);
+5 -1
View File
@@ -150,11 +150,15 @@ ostream& GuiAvatar::toString(ostream& out) const
void GuiGameZone::toggleDisplay() void GuiGameZone::toggleDisplay()
{ {
if (showCards) if (showCards)
{
showCards = 0; showCards = 0;
else cd->zone->owner->getObserver()->OpenedDisplay = NULL;
}
else if(!cd->zone->owner->getObserver()->OpenedDisplay)//one display at a time please.
{ {
showCards = 1; showCards = 1;
cd->init(zone); cd->init(zone);
cd->zone->owner->getObserver()->OpenedDisplay = cd;
} }
} }
+156 -13
View File
@@ -19,8 +19,8 @@
const string kLordKeywords[] = { "lord(", "foreach(", "aslongas(", "teach(", "all(" }; const string kLordKeywords[] = { "lord(", "foreach(", "aslongas(", "teach(", "all(" };
const size_t kLordKeywordsCount = 5; const size_t kLordKeywordsCount = 5;
const string kThisKeywords[] = { "this(", "thisforeach(" }; const string kThisKeywords[] = { "this(", "thisforeach(","while(", };
const size_t kThisKeywordsCount = 2; const size_t kThisKeywordsCount = 3;
// Used for the maxCast/maxPlay ability parsing // Used for the maxCast/maxPlay ability parsing
@@ -353,6 +353,24 @@ int AbilityFactory::parseCastRestrictions(MTGCardInstance * card, Player * playe
return 0; return 0;
} }
check = restriction[i].find("delirium");
if (check != string::npos)
{
Player * checkCurrent = card->controller();
MTGGameZone * grave = checkCurrent->game->graveyard;
int checkTypesAmount = 0;
if(grave->hasType("creature")) checkTypesAmount++;
if (grave->hasType("enchantment")) checkTypesAmount++;
if (grave->hasType("sorcery")) checkTypesAmount++;
if (grave->hasType("instant")) checkTypesAmount++;
if (grave->hasType("land")) checkTypesAmount++;
if (grave->hasType("artifact")) checkTypesAmount++;
if (grave->hasType("planeswalker")) checkTypesAmount++;
if (checkTypesAmount < 4)
return 0;
}
check = restriction[i].find("miracle"); check = restriction[i].find("miracle");
if(check != string::npos) if(check != string::npos)
{ {
@@ -362,6 +380,13 @@ int AbilityFactory::parseCastRestrictions(MTGCardInstance * card, Player * playe
return 0; return 0;
} }
check = restriction[i].find("madnessplayed");
if (check != string::npos)
{
if (card->previous && !card->previous->MadnessPlay)
return 0;
}
check = restriction[i].find("prowl"); check = restriction[i].find("prowl");
if(check != string::npos) if(check != string::npos)
{ {
@@ -437,6 +462,13 @@ int AbilityFactory::parseCastRestrictions(MTGCardInstance * card, Player * playe
return 0; return 0;
} }
check = restriction[i].find("geared");
if (check != string::npos)
{
if (card->equipment < 1)
return 0;
}
check = restriction[i].find("raid"); check = restriction[i].find("raid");
if(check != string::npos) if(check != string::npos)
{ {
@@ -1139,6 +1171,13 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
observer->addObserver(NEW MTGFlashBackRule(observer, -1)); observer->addObserver(NEW MTGFlashBackRule(observer, -1));
return NULL; return NULL;
} }
//alternative cost type flashback
found = s.find("bestowrule");
if (found != string::npos)
{
observer->addObserver(NEW MTGBestowRule(observer, -1));
return NULL;
}
//alternative cost type retrace //alternative cost type retrace
found = s.find("retracerule"); found = s.find("retracerule");
if(found != string::npos) if(found != string::npos)
@@ -1306,11 +1345,19 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
//actual abilities, this is a limitation. //actual abilities, this is a limitation.
string unchangedS = ""; string unchangedS = "";
unchangedS.append(s); unchangedS.append(s);
//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("); found = s.find("pay(");
if (found != string::npos && storedPayString.empty()) if (found != string::npos && storedPayString.empty() && !transPayfound.size())
{ {
vector<string> splitMayPaystr = parseBetween(s, "pay(", ")", true); vector<string> splitMayPaystr = parseBetween(s, "pay(", ")", true);
if(splitMayPaystr.size()) if (splitMayPaystr.size())
{ {
storedPayString.append(splitMayPaystr[2]); storedPayString.append(splitMayPaystr[2]);
s = splitMayPaystr[0]; s = splitMayPaystr[0];
@@ -1319,6 +1366,25 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
s.append(")"); s.append(")");
} }
} }
vector<string> splitRevealx = parseBetween(s, "reveal:", " revealend", false);
if (!abilfound.size() && !transfound.size() && splitRevealx.size() && storedAbilityString.empty())
{
storedAbilityString = splitRevealx[1];
s = splitRevealx[0];
s.append("reveal: ");
s.append(splitRevealx[2]);
}
vector<string> splitScryx = parseBetween(s, "scry:", " scryend", false);
if (splitScryx.size() && storedAbilityString.empty())
{
storedAbilityString = splitScryx[1];
s = splitScryx[0];
s.append("scry: ");
s.append(splitScryx[2]);
}
found = s.find("transforms(("); found = s.find("transforms((");
if (found != string::npos && storedString.empty()) if (found != string::npos && storedString.empty())
{ {
@@ -1750,15 +1816,25 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
} }
if (end != string::npos) if (end != string::npos)
{ {
ThisDescriptor * td = NULL;
string thisDescriptorString = s.substr(found + header, end - found - header); string thisDescriptorString = s.substr(found + header, end - found - header);
vector<string> splitRest = parseBetween(s, "restriction{", "}");
if (splitRest.size())
{
}
else
{
ThisDescriptorFactory tdf; ThisDescriptorFactory tdf;
ThisDescriptor * td = tdf.createThisDescriptor(observer, thisDescriptorString); td = tdf.createThisDescriptor(observer, thisDescriptorString);
if (!td) if (!td)
{ {
DebugTrace("MTGABILITY: Parsing Error:" << s); DebugTrace("MTGABILITY: Parsing Error:" << s);
return NULL; return NULL;
} }
}
MTGAbility * a = parseMagicLine(s1, id, spell, card, 0, activated); MTGAbility * a = parseMagicLine(s1, id, spell, card, 0, activated);
if (!a) if (!a)
@@ -1795,6 +1871,9 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
case 1: case 1:
result = NEW AThisForEach(observer, id, card, _target, td, a); result = NEW AThisForEach(observer, id, card, _target, td, a);
break; break;
case 2:
result = NEW AThis(observer, id, card, _target, NULL, a, thisDescriptorString);
break;
default: default:
result = NULL; result = NULL;
} }
@@ -1986,7 +2065,6 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
return NEW APaired(observer,id, card,card->myPair,a); return NEW APaired(observer,id, card,card->myPair,a);
return NULL; return NULL;
} }
//mana of the listed type doesnt get emptied from the pools. //mana of the listed type doesnt get emptied from the pools.
vector<string>colorType = parseBetween(s,"poolsave(",")",false); vector<string>colorType = parseBetween(s,"poolsave(",")",false);
if (colorType.size()) if (colorType.size())
@@ -2272,6 +2350,18 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
string tokenDesc = splitToken[1]; string tokenDesc = splitToken[1];
vector<string> tokenParameters = split(tokenDesc, ','); vector<string> tokenParameters = split(tokenDesc, ',');
//lets try finding a token by card name.
if (splitToken[1].size() && tokenParameters.size() ==1)
{
string cardName = splitToken[1];
MTGCard * safetycard = MTGCollection()->getCardByName(cardName);
if (safetycard) //lets try constructing it then,we didnt find it by name
{
ATokenCreator * tok = NEW ATokenCreator(observer, id, card, target, NULL, cardName, starfound, multiplier, who);
tok->oneShot = 1;
return tok;
}
}
if (tokenParameters.size() < 3) if (tokenParameters.size() < 3)
{ {
DebugTrace("incorrect Parameters for Token" << tokenDesc); DebugTrace("incorrect Parameters for Token" << tokenDesc);
@@ -2474,6 +2564,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
bool withRestrictions = splitCastCard[1].find("restricted") != string::npos; bool withRestrictions = splitCastCard[1].find("restricted") != string::npos;
bool asCopy = splitCastCard[1].find("copied") != string::npos; bool asCopy = splitCastCard[1].find("copied") != string::npos;
bool asNormal = splitCastCard[1].find("normal") != string::npos; bool asNormal = splitCastCard[1].find("normal") != string::npos;
bool asNormalMadness = splitCastCard[1].find("madness") != string::npos;
bool sendNoEvent = splitCastCard[1].find("noevent") != string::npos; bool sendNoEvent = splitCastCard[1].find("noevent") != string::npos;
bool putinplay = splitCastCard[1].find("putinplay") != string::npos; bool putinplay = splitCastCard[1].find("putinplay") != string::npos;
string nameCard = ""; string nameCard = "";
@@ -2485,7 +2576,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
nameCard = splitCastName[1]; nameCard = splitCastName[1];
} }
} }
MTGAbility *a = NEW AACastCard(observer, id, card, target,withRestrictions,asCopy,asNormal,nameCard,newName,sendNoEvent,putinplay); MTGAbility *a = NEW AACastCard(observer, id, card, target,withRestrictions,asCopy,asNormal,nameCard,newName,sendNoEvent,putinplay, asNormalMadness);
a->oneShot = false; a->oneShot = false;
if(splitCastCard[1].find("trigger[to]") != string::npos) if(splitCastCard[1].find("trigger[to]") != string::npos)
{ {
@@ -2933,6 +3024,16 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
return a; return a;
} }
//bestow
found = s.find("bstw");
if (found != string::npos)
{
MTGAbility * a = NEW ABestow(observer, id, card, target);
a->oneShot = 1;
return a;
}
//no counters on target of optional type //no counters on target of optional type
vector<string> splitCounterShroud = parseBetween(s, "countershroud(", ")"); vector<string> splitCounterShroud = parseBetween(s, "countershroud(", ")");
if (splitCounterShroud.size()) if (splitCounterShroud.size())
@@ -3122,6 +3223,30 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
} }
//Reveal:x (activate aility)
vector<string> splitReveal = parseBetween(s, "reveal:", "revealend", false);
if (splitReveal.size())
{
string backup = storedAbilityString;
storedAbilityString = "";//we clear the string here for cards that contain more than 1 reveal.
GenericRevealAbility * a = NEW GenericRevealAbility(observer, id, card, target, backup);
a->oneShot = 1;
a->canBeInterrupted = false;
return a;
}
//scry:x (activate aility)
vector<string> splitScry = parseBetween(s, "scry:", "scryend", false);
if (splitScry.size())
{
string backup = storedAbilityString;
storedAbilityString = "";//we clear the string here for cards that contain more than 1 reveal.
GenericScryAbility * a = NEW GenericScryAbility(observer, id, card, target, backup);
a->oneShot = 1;
a->canBeInterrupted = false;
return a;
}
//flip //flip
vector<string> splitFlipStat = parseBetween(s, "flip(", ")", true); vector<string> splitFlipStat = parseBetween(s, "flip(", ")", true);
if(splitFlipStat.size()) if(splitFlipStat.size())
@@ -3291,7 +3416,16 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
found = s.find("frozen"); found = s.find("frozen");
if (found != string::npos) if (found != string::npos)
{ {
MTGAbility * a = NEW AAFrozen(observer, id, card, target); MTGAbility * a = NEW AAFrozen(observer, id, card, target,false);
a->oneShot = 1;
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; a->oneShot = 1;
return a; return a;
} }
@@ -3330,6 +3464,14 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
return a; return a;
} }
vector<string> splitCountObject = parseBetween(s, "count(", ")", false);
if (splitCountObject.size())
{
MTGAbility * a = NEW AACountObject(observer, id, card, card, NULL, splitCountObject[1]);
a->oneShot = 1;
return a;
}
//switch targest power with toughness //switch targest power with toughness
found = s.find("swap"); found = s.find("swap");
if (found != string::npos) if (found != string::npos)
@@ -4625,6 +4767,7 @@ MTGAbility::MTGAbility(const MTGAbility& a): ActionElement(a)
BuyBack = a.BuyBack; //? NEW ManaCost(a.BuyBack) : NULL; BuyBack = a.BuyBack; //? NEW ManaCost(a.BuyBack) : NULL;
FlashBack = a.FlashBack; // ? NEW ManaCost(a.FlashBack) : NULL; FlashBack = a.FlashBack; // ? NEW ManaCost(a.FlashBack) : NULL;
Retrace = a.Retrace;// ? NEW ManaCost(a.Retrace) : NULL; Retrace = a.Retrace;// ? NEW ManaCost(a.Retrace) : NULL;
Bestow = a.Bestow;
morph = a.morph; //? NEW ManaCost(a.morph) : NULL; morph = a.morph; //? NEW ManaCost(a.morph) : NULL;
suspend = a.suspend;// ? NEW ManaCost(a.suspend) : NULL; suspend = a.suspend;// ? NEW ManaCost(a.suspend) : NULL;
@@ -5101,7 +5244,7 @@ int TargetAbility::reactToClick(MTGCardInstance * card)
} }
else else
{ {
if (tc->toggleTarget(card) == TARGET_OK_FULL) if (tc->toggleTarget(card) == TARGET_OK_FULL && tc->targetsReadyCheck() == TARGET_OK_FULL)
{ {
int result = ActivatedAbility::reactToClick(source); int result = ActivatedAbility::reactToClick(source);
if (result) if (result)
@@ -5360,8 +5503,8 @@ void ListMaintainerAbility::updateTargets()
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
Player * p = game->players[i]; Player * p = game->players[i];
MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->stack, p->game->exile }; MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->stack, p->game->exile ,p->game->reveal };
for (int k = 0; k < 6; k++) for (int k = 0; k < 7; k++)
{ {
MTGGameZone * zone = zones[k]; MTGGameZone * zone = zones[k];
if (canTarget(zone)) if (canTarget(zone))
@@ -5432,8 +5575,8 @@ void ListMaintainerAbility::checkTargets()
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
Player * p = game->players[i]; Player * p = game->players[i];
MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->stack, p->game->exile }; MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->stack, p->game->exile, p->game->reveal };
for (int k = 0; k < 6; k++) for (int k = 0; k < 7; k++)
{ {
MTGGameZone * zone = zones[k]; MTGGameZone * zone = zones[k];
if (canTarget(zone)) if (canTarget(zone))
+6 -2
View File
@@ -69,6 +69,8 @@ MTGCardInstance::MTGCardInstance(MTGCard * card, MTGPlayerCards * arg_belongs_to
cardistargetted = 0; cardistargetted = 0;
cardistargetter = 0; cardistargetter = 0;
myconvertedcost = getManaCost()->getConvertedCost(); myconvertedcost = getManaCost()->getConvertedCost();
revealedLast = NULL;
MadnessPlay = false;
} }
MTGCardInstance * MTGCardInstance::createSnapShot() MTGCardInstance * MTGCardInstance::createSnapShot()
@@ -194,6 +196,7 @@ void MTGCardInstance::initMTGCI()
wasDealtDamage = false; wasDealtDamage = false;
isDualWielding = false; isDualWielding = false;
suspended = false; suspended = false;
isBestowed = false;
castMethod = Constants::NOT_CAST; castMethod = Constants::NOT_CAST;
mPropertiesChangedSinceLastUpdate = false; mPropertiesChangedSinceLastUpdate = false;
stillNeeded = true; stillNeeded = true;
@@ -222,6 +225,7 @@ void MTGCardInstance::initMTGCI()
imprintW = 0; imprintW = 0;
currentimprintName = ""; currentimprintName = "";
imprintedNames.clear(); imprintedNames.clear();
CountedObjects = 0;
for (int i = 0; i < ManaCost::MANA_PAID_WITH_SUSPEND +1; i++) for (int i = 0; i < ManaCost::MANA_PAID_WITH_SUSPEND +1; i++)
alternateCostPaid[i] = 0; alternateCostPaid[i] = 0;
@@ -870,7 +874,7 @@ int MTGCardInstance::canBlock(MTGCardInstance * opponent)
return 0; return 0;
if (opponent->basicAbilities[(int)Constants::ONEBLOCKER] && opponent->blocked) if (opponent->basicAbilities[(int)Constants::ONEBLOCKER] && opponent->blocked)
return 0; return 0;
if(opponent->basicAbilities[(int)Constants::EVADEBIGGER] && power > opponent->power) if((opponent->basicAbilities[(int)Constants::EVADEBIGGER]|| opponent->basicAbilities[(int)Constants::SKULK]) && power > opponent->power)
return 0; return 0;
if(opponent->basicAbilities[(int)Constants::STRONG] && power < opponent->power) if(opponent->basicAbilities[(int)Constants::STRONG] && power < opponent->power)
return 0; return 0;
@@ -1266,7 +1270,7 @@ int MTGCardInstance::setDefenser(MTGCardInstance * opponent)
if (defenser) if (defenser)
{ {
if (observer->players[0]->game->battlefield->hasCard(defenser) || observer->players[1]->game->battlefield->hasCard(defenser)) if (observer->players[0]->game->battlefield->hasCard(defenser) || observer->players[1]->game->battlefield->hasCard(defenser))
{ {//remove blocker "this" from the attackers list of blockers.
defenser->removeBlocker(this); defenser->removeBlocker(this);
} }
} }
+12 -1
View File
@@ -105,8 +105,19 @@ int MTGAllCards::processConfLine(string &s, MTGCard *card, CardPrimitive * primi
} }
break; break;
case 'b': //buyback case 'b': //buyback/Bestow
if (!primitive) primitive = NEW CardPrimitive(); if (!primitive) primitive = NEW CardPrimitive();
if (key[1] == 'e' && key[2] == 's')
{ //bestow
if (!primitive) primitive = NEW CardPrimitive();
if (ManaCost * cost = primitive->getManaCost())
{
string value = val;
std::transform(value.begin(), value.end(), value.begin(), ::tolower);
cost->setBestow(ManaCost::parseManaCost(value));
}
}
else//buyback
if (ManaCost * cost = primitive->getManaCost()) if (ManaCost * cost = primitive->getManaCost())
{ {
string value = val; string value = val;
+6 -1
View File
@@ -26,6 +26,7 @@ const string Constants::kFlashBackKeyword = "flashback";
const string Constants::kRetraceKeyword = "retrace"; const string Constants::kRetraceKeyword = "retrace";
const string Constants::kKickerKeyword = "kicker"; const string Constants::kKickerKeyword = "kicker";
const string Constants::kMorphKeyword = "facedown"; const string Constants::kMorphKeyword = "facedown";
const string Constants::kBestowKeyword = "bestow";
int Constants::NB_Colors = 0; //Store the Max number of colors. int Constants::NB_Colors = 0; //Store the Max number of colors.
@@ -157,7 +158,11 @@ const char* Constants::MTGBasicAbilities[] = {
"cantchangelife", "cantchangelife",
"combattoughness", "combattoughness",
"cantpaylife", "cantpaylife",
"cantbesacrified" "cantbesacrified",
"skulk",
"menace",
"nosolo",
"mustblock"
}; };
map<string,int> Constants::MTGBasicAbilitiesMap; map<string,int> Constants::MTGBasicAbilitiesMap;
+1
View File
@@ -9,6 +9,7 @@ MTGGamePhase::MTGGamePhase(GameObserver* g, int id) :
animation = 0; animation = 0;
currentState = -1; currentState = -1;
mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT); mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT);
if(mFont)
mFont->SetBase(0); // using 2nd font mFont->SetBase(0); // using 2nd font
} }
+41 -2
View File
@@ -74,6 +74,7 @@ MTGPlayerCards::~MTGPlayerCards()
SAFE_DELETE(stack); SAFE_DELETE(stack);
SAFE_DELETE(removedFromGame); SAFE_DELETE(removedFromGame);
SAFE_DELETE(garbage); SAFE_DELETE(garbage);
SAFE_DELETE(reveal);
SAFE_DELETE(temp); SAFE_DELETE(temp);
SAFE_DELETE(playRestrictions); SAFE_DELETE(playRestrictions);
} }
@@ -91,6 +92,7 @@ void MTGPlayerCards::beforeBeginPhase()
stack->beforeBeginPhase(); stack->beforeBeginPhase();
removedFromGame->beforeBeginPhase(); removedFromGame->beforeBeginPhase();
garbage->beforeBeginPhase(); garbage->beforeBeginPhase();
reveal->beforeBeginPhase();
temp->beforeBeginPhase(); temp->beforeBeginPhase();
} }
@@ -105,6 +107,7 @@ void MTGPlayerCards::setOwner(Player * player)
stack->setOwner(player); stack->setOwner(player);
garbage->setOwner(player); garbage->setOwner(player);
garbageLastTurn->setOwner(player); garbageLastTurn->setOwner(player);
reveal->setOwner(player);
temp->setOwner(player); temp->setOwner(player);
} }
@@ -272,6 +275,7 @@ void MTGPlayerCards::init()
exile = removedFromGame; exile = removedFromGame;
garbage = NEW MTGGameZone(); garbage = NEW MTGGameZone();
garbageLastTurn = garbage; garbageLastTurn = garbage;
reveal = NEW MTGGameZone();
temp = NEW MTGGameZone(); temp = NEW MTGGameZone();
playRestrictions = NEW PlayRestrictions(); playRestrictions = NEW PlayRestrictions();
@@ -360,6 +364,12 @@ MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone
to = g->players[i]->game->exile; to = g->players[i]->game->exile;
} }
} }
//all cards that go from the hand to the graveyard is ALWAYS a discard.
if ((to == g->players[0]->game->graveyard || to == g->players[1]->game->graveyard) && (from == g->players[0]->game->hand || from
== g->players[1]->game->hand))
{
card->discarded = true;
}
//When a card is moved from inPlay to inPlay (controller change, for example), it is still the same object //When a card is moved from inPlay to inPlay (controller change, for example), it is still the same object
if ((to == g->players[0]->game->inPlay || to == g->players[1]->game->inPlay) && (from == g->players[0]->game->inPlay || from if ((to == g->players[0]->game->inPlay || to == g->players[1]->game->inPlay) && (from == g->players[0]->game->inPlay || from
== g->players[1]->game->inPlay)) == g->players[1]->game->inPlay))
@@ -371,6 +381,7 @@ MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone
if (!(copy = from->removeCard(card, doCopy))) if (!(copy = from->removeCard(card, doCopy)))
return NULL; //ERROR return NULL; //ERROR
if (card->miracle) if (card->miracle)
{ {
copy->miracle = true; copy->miracle = true;
@@ -435,11 +446,12 @@ MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone
previous->next = NULL; previous->next = NULL;
SAFE_DELETE(previous); SAFE_DELETE(previous);
} }
} }
if(!asCopy) if(!asCopy)
{ {
if(shufflelibrary) if(shufflelibrary)
copy->owner->game->library->shuffle(); copy->owner->game->library->shuffle();//shouldnt we only ever do this if you clicked close on your library gui??????
WEvent * e = NEW WEventZoneChange(copy, from, to); WEvent * e = NEW WEventZoneChange(copy, from, to);
g->receiveEvent(e); g->receiveEvent(e);
@@ -995,6 +1007,14 @@ MTGGameZone * MTGGameZone::intToZone(int zoneId, Player * p, Player * p2)
return p->opponent()->game->stack; return p->opponent()->game->stack;
case STACK: case STACK:
return p->game->stack; return p->game->stack;
case MY_REVEAL:
return p->game->reveal;
case OPPONENT_REVEAL:
return p->opponent()->game->reveal;
case REVEAL:
return p->game->reveal;
} }
if (!p2) return NULL; if (!p2) return NULL;
switch (zoneId) switch (zoneId)
@@ -1017,6 +1037,9 @@ MTGGameZone * MTGGameZone::intToZone(int zoneId, Player * p, Player * p2)
case TARGET_CONTROLLER_STACK: case TARGET_CONTROLLER_STACK:
return p2->game->stack; return p2->game->stack;
case TARGET_CONTROLLER_REVEAL:
return p2->game->reveal;
default: default:
return NULL; return NULL;
} }
@@ -1114,6 +1137,18 @@ MTGGameZone * MTGGameZone::intToZone(GameObserver *g, int zoneId, MTGCardInstanc
if(source->playerTarget) if(source->playerTarget)
return source->playerTarget->game->stack; return source->playerTarget->game->stack;
else return source->controller()->game->stack; else return source->controller()->game->stack;
case TARGET_OWNER_REVEAL:
return target->owner->game->reveal;
case REVEAL:
return target->owner->game->reveal;
case OWNER_REVEAL:
return target->owner->game->reveal;
case TARGETED_PLAYER_REVEAL:
if (source->playerTarget)
return source->playerTarget->game->reveal;
else return source->controller()->game->reveal;
default: default:
return NULL; return NULL;
} }
@@ -1141,6 +1176,8 @@ int MTGGameZone::zoneStringToId(string zoneName)
"mystack", "opponentstack", "targetownerstack", "targetcontrollerstack", "ownerstack", "stack","targetedpersonsstack", "mystack", "opponentstack", "targetownerstack", "targetcontrollerstack", "ownerstack", "stack","targetedpersonsstack",
"myreveal", "opponentreveal", "targetownerreveal", "targetcontrollerreveal", "ownerreveal", "reveal","targetedpersonsreveal",
}; };
int values[] = { MY_GRAVEYARD, OPPONENT_GRAVEYARD, TARGET_OWNER_GRAVEYARD, TARGET_CONTROLLER_GRAVEYARD, OWNER_GRAVEYARD, int values[] = { MY_GRAVEYARD, OPPONENT_GRAVEYARD, TARGET_OWNER_GRAVEYARD, TARGET_CONTROLLER_GRAVEYARD, OWNER_GRAVEYARD,
@@ -1160,7 +1197,9 @@ int MTGGameZone::zoneStringToId(string zoneName)
MY_EXILE, OPPONENT_EXILE, TARGET_OWNER_EXILE, TARGET_CONTROLLER_EXILE, OWNER_EXILE, EXILE,TARGETED_PLAYER_EXILE, MY_EXILE, OPPONENT_EXILE, TARGET_OWNER_EXILE, TARGET_CONTROLLER_EXILE, OWNER_EXILE, EXILE,TARGETED_PLAYER_EXILE,
MY_STACK, OPPONENT_STACK, TARGET_OWNER_STACK, TARGET_CONTROLLER_STACK, OWNER_STACK, STACK,TARGETED_PLAYER_STACK }; MY_STACK, OPPONENT_STACK, TARGET_OWNER_STACK, TARGET_CONTROLLER_STACK, OWNER_STACK, STACK,TARGETED_PLAYER_STACK,
MY_REVEAL, OPPONENT_REVEAL, TARGET_OWNER_REVEAL, TARGET_CONTROLLER_REVEAL, OWNER_REVEAL, REVEAL,TARGETED_PLAYER_REVEAL };
int max = sizeof(values) / sizeof *(values); int max = sizeof(values) / sizeof *(values);
+136 -4
View File
@@ -367,9 +367,7 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card)
return 0; return 0;
Player * player = game->currentlyActing(); Player * player = game->currentlyActing();
ManaCost * cost = card->getManaCost(); ManaCost * cost = card->getManaCost();
//this handles extra cost payments at the moment a card is played. //this handles extra cost payments at the moment a card is played.
if (cost->isExtraPaymentSet()) if (cost->isExtraPaymentSet())
{ {
if (!game->targetListIsSet(card)) if (!game->targetListIsSet(card))
@@ -497,6 +495,9 @@ int MTGKickerRule::isReactingToClick(MTGCardInstance * card, ManaCost *)
ManaCost * withKickerCost= NEW ManaCost(card->getManaCost()); ManaCost * withKickerCost= NEW ManaCost(card->getManaCost());
withKickerCost->add(card->getManaCost()->getKicker()); withKickerCost->add(card->getManaCost()->getKicker());
//cost reduction/recalculation must be here or outside somehow... //cost reduction/recalculation must be here or outside somehow...
//no recalculations beyound this point, reactToClick is the function that
//happens only with the assumption that you could actually pay for it, any calculations after will
//have negitive effects. this function is basically "can i play this card?"
#ifdef WIN32 #ifdef WIN32
withKickerCost->Dump(); withKickerCost->Dump();
#endif #endif
@@ -532,7 +533,7 @@ int MTGKickerRule::reactToClick(MTGCardInstance * card)
ManaCost * previousManaPool = NEW ManaCost(player->getManaPool()); ManaCost * previousManaPool = NEW ManaCost(player->getManaPool());
int payResult = player->getManaPool()->pay(card->getManaCost()); int payResult = player->getManaPool()->pay(card->getManaCost());
if (card->getManaCost()->getKicker()) if (card->getManaCost()->getKicker())
{ //cost reduction/recalculation must be here or outside somehow... {
ManaCost * withKickerCost= NEW ManaCost(card->getManaCost()); ManaCost * withKickerCost= NEW ManaCost(card->getManaCost());
withKickerCost->add(withKickerCost->getKicker()); withKickerCost->add(withKickerCost->getKicker());
if (card->getManaCost()->getKicker()->isMulti) if (card->getManaCost()->getKicker()->isMulti)
@@ -1345,7 +1346,68 @@ MTGOverloadRule * MTGOverloadRule::clone() const
{ {
return NEW MTGOverloadRule(*this); return NEW MTGOverloadRule(*this);
} }
///////////////////////////////////////////////////////////////////////////////////////////////////
//bestow
MTGBestowRule::MTGBestowRule(GameObserver* observer, int _id) :
MTGAlternativeCostRule(observer, _id)
{
aType = MTGAbility::BESTOW_COST;
}
int MTGBestowRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
{
if (!card->model)
return 0;
Player * player = game->currentlyActing();
if (!card->model->data->getManaCost()->getBestow())
return 0;
if (card->isInPlay(game))
return 0;
ManaCost * cost = NEW ManaCost(card->model->data->getManaCost()->getBestow());
ManaCost * newCost = card->computeNewCost(card, cost, cost);
if (newCost->extraCosts)
for (unsigned int i = 0; i < newCost->extraCosts->costs.size(); i++)
{
newCost->extraCosts->costs[i]->setSource(card);
}
SAFE_DELETE(cost);
if (card->isLand())
return 0;
if (!card->controller()->inPlay()->hasType("creature") && !card->controller()->opponent()->inPlay()->hasType("creature"))
return 0;
return MTGAlternativeCostRule::isReactingToClick(card, mana, newCost);
}
int MTGBestowRule::reactToClick(MTGCardInstance * card)
{
if (!isReactingToClick(card))
return 0;
//this new method below in all alternative cost type causes a memleak, however, you cant safedelete the cost here as it cause a crash
//TODO::::we need to get to the source of this leak and fix it.
ManaCost * cost = NEW ManaCost(card->model->data->getManaCost()->getBestow());
ManaCost * newCost = card->computeNewCost(card, cost, cost);
if (newCost->extraCosts)
for (unsigned int i = 0; i < newCost->extraCosts->costs.size(); i++)
{
newCost->extraCosts->costs[i]->setSource(card);
}
card->paymenttype = MTGAbility::BESTOW_COST;
card->spellTargetType = "creature|battlefield";
return MTGAlternativeCostRule::reactToClick(card, newCost, ManaCost::MANA_PAID_WITH_BESTOW, false);
}
ostream& MTGBestowRule::toString(ostream& out) const
{
out << "MTGBestowRule ::: (";
return MTGAbility::toString(out) << ")";
}
MTGBestowRule * MTGBestowRule::clone() const
{
return NEW MTGBestowRule(*this);
}
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
//ATTACK COST //ATTACK COST
@@ -1425,7 +1487,6 @@ MTGBlockCostRule::MTGBlockCostRule(GameObserver* observer, int _id) :
aType = MTGAbility::BLOCK_COST; aType = MTGAbility::BLOCK_COST;
scost = "Pay to block"; scost = "Pay to block";
} }
int MTGBlockCostRule::isReactingToClick(MTGCardInstance * card, ManaCost *) int MTGBlockCostRule::isReactingToClick(MTGCardInstance * card, ManaCost *)
{ {
if (currentPhase == MTG_PHASE_COMBATBLOCKERS && !game->isInterrupting if (currentPhase == MTG_PHASE_COMBATBLOCKERS && !game->isInterrupting
@@ -1536,6 +1597,14 @@ int MTGAttackRule::receiveEvent(WEvent *e)
for (int i = 0; i < z->nb_cards; i++) for (int i = 0; i < z->nb_cards; i++)
{ {
MTGCardInstance * card = z->cards[i]; MTGCardInstance * card = z->cards[i];
if (card->isAttacker() && card->has(Constants::NOSOLO))
{
TargetChooserFactory tf(game);
TargetChooser * tc = tf.createTargetChooser("creature[attacking]", NULL);
int Check = card->controller()->game->battlefield->countByCanTarget(tc);
if (Check <2)
card->initAttackersDefensers();
}
if (!card->isAttacker() && !event->from->isExtra && card->has(Constants::MUSTATTACK))//cards are only required to attack in the real attack phase of a turn. if (!card->isAttacker() && !event->from->isExtra && card->has(Constants::MUSTATTACK))//cards are only required to attack in the real attack phase of a turn.
reactToClick(card); reactToClick(card);
if (!card->isAttacker() && card->has(Constants::TREASON) && p->isAI()) if (!card->isAttacker() && card->has(Constants::TREASON) && p->isAI())
@@ -1848,6 +1917,50 @@ PermanentAbility(observer, _id)
int MTGBlockRule::receiveEvent(WEvent *e) int MTGBlockRule::receiveEvent(WEvent *e)
{ {
if (dynamic_cast<WEventBlockersChosen*>(e))
{//do not refactor, these are keep seperate for readability.
Player * p = game->currentPlayer;
vector<MTGCardInstance *> Attacker;
MTGGameZone * k = p->game->inPlay;
for (int i = 0; i < k->nb_cards; i++)
{
MTGCardInstance * card = k->cards[i];
if (card->isAttacker())
{
Attacker.push_back(card);
}
}
//force cards that must block, to block whatever is first found. players have a chance to set thier own
//but if ignored we do it for them.
if (Attacker.size())
{
MTGGameZone * tf = p->opponent()->game->inPlay;
for (size_t i = 0; i < tf->cards.size(); i++)
{
MTGCardInstance * card = tf->cards[i];
if (card->has(Constants::MUSTBLOCK) && !card->defenser && card->canBlock())
{//force mustblockers to block the first thing theyre allowed to block if player leaves blockers with them
//unassigned as a block.
for (size_t i = 0; i < Attacker.size(); i++)
{
if (card->canBlock(Attacker[i]) && !card->defenser)
{
blocker = NEW AABlock(card->getObserver(), -1, card, NULL);
blocker->oneShot = true;
blocker->forceDestroy = 1;
blocker->canBeInterrupted = false;
blocker->target = Attacker[i];
blocker->resolve();
SAFE_DELETE(blocker);
}
}
}
}
}
if (dynamic_cast<WEventBlockersChosen*>(e)) if (dynamic_cast<WEventBlockersChosen*>(e))
{ {
@@ -1866,6 +1979,25 @@ int MTGBlockRule::receiveEvent(WEvent *e)
//but this action can not be ignored. //but this action can not be ignored.
} }
} }
//if a card with menace is not blocked by 2 or more, remove any known blockers and attacking as normal.
MTGGameZone * z = p->game->inPlay;
for (int i = 0; i < z->nb_cards; i++)
{
MTGCardInstance * card = z->cards[i];
if (card->has(Constants::MENACE) && card->blockers.size() < 2)
{
while (card->blockers.size())
{
MTGCardInstance * blockingCard = card->blockers.front();
blockingCard->toggleDefenser(NULL);
}
}
}
}
return 1; return 1;
} }
+15 -1
View File
@@ -152,7 +152,8 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstan
manaCost->addExtraCost(NEW SacrificeCost(tc)); manaCost->addExtraCost(NEW SacrificeCost(tc));
} }
break; break;
case 'e': //Exile case 'e':
//Exile
manaCost->addExtraCost(NEW ExileTargetCost(tc)); manaCost->addExtraCost(NEW ExileTargetCost(tc));
break; break;
case 'h': //bounce (move to Hand) case 'h': //bounce (move to Hand)
@@ -387,6 +388,7 @@ ManaCost::ManaCost(ManaCost * manaCost)
FlashBack = NEW ManaCost( manaCost->FlashBack ); FlashBack = NEW ManaCost( manaCost->FlashBack );
morph = NEW ManaCost( manaCost->morph ); morph = NEW ManaCost( manaCost->morph );
suspend = NEW ManaCost( manaCost->suspend ); suspend = NEW ManaCost( manaCost->suspend );
Bestow = NEW ManaCost(manaCost->Bestow);
extraCosts = manaCost->extraCosts ? manaCost->extraCosts->clone() : NULL; extraCosts = manaCost->extraCosts ? manaCost->extraCosts->clone() : NULL;
manaUsedToCast = NULL; manaUsedToCast = NULL;
@@ -415,6 +417,7 @@ ManaCost::ManaCost(const ManaCost& manaCost)
FlashBack = NEW ManaCost( manaCost.FlashBack ); FlashBack = NEW ManaCost( manaCost.FlashBack );
morph = NEW ManaCost( manaCost.morph ); morph = NEW ManaCost( manaCost.morph );
suspend = NEW ManaCost( manaCost.suspend ); suspend = NEW ManaCost( manaCost.suspend );
Bestow = NEW ManaCost(manaCost.Bestow);
extraCosts = manaCost.extraCosts ? manaCost.extraCosts->clone() : NULL; extraCosts = manaCost.extraCosts ? manaCost.extraCosts->clone() : NULL;
manaUsedToCast = NULL; manaUsedToCast = NULL;
@@ -438,6 +441,7 @@ ManaCost & ManaCost::operator= (const ManaCost & manaCost)
FlashBack = manaCost.FlashBack; FlashBack = manaCost.FlashBack;
morph = manaCost.morph; morph = manaCost.morph;
suspend = manaCost.suspend; suspend = manaCost.suspend;
Bestow = manaCost.Bestow;
manaUsedToCast = manaCost.manaUsedToCast; manaUsedToCast = manaCost.manaUsedToCast;
xColor = manaCost.xColor; xColor = manaCost.xColor;
} }
@@ -454,6 +458,7 @@ ManaCost::~ManaCost()
SAFE_DELETE(Retrace); SAFE_DELETE(Retrace);
SAFE_DELETE(morph); SAFE_DELETE(morph);
SAFE_DELETE(suspend); SAFE_DELETE(suspend);
SAFE_DELETE(Bestow);
SAFE_DELETE(manaUsedToCast); SAFE_DELETE(manaUsedToCast);
cost.erase(cost.begin() ,cost.end()); cost.erase(cost.begin() ,cost.end());
@@ -539,6 +544,7 @@ void ManaCost::init()
Retrace = NULL; Retrace = NULL;
morph = NULL; morph = NULL;
suspend = NULL; suspend = NULL;
Bestow = NULL;
manaUsedToCast = NULL; manaUsedToCast = NULL;
isMulti = false; isMulti = false;
xColor = -1; xColor = -1;
@@ -563,6 +569,7 @@ void ManaCost::resetCosts()
SAFE_DELETE(Retrace); SAFE_DELETE(Retrace);
SAFE_DELETE(morph); SAFE_DELETE(morph);
SAFE_DELETE(suspend); SAFE_DELETE(suspend);
SAFE_DELETE(Bestow);
} }
void ManaCost::copy(ManaCost * _manaCost) void ManaCost::copy(ManaCost * _manaCost)
@@ -628,6 +635,12 @@ void ManaCost::copy(ManaCost * _manaCost)
suspend = NEW ManaCost(); suspend = NEW ManaCost();
suspend->copy(_manaCost->suspend); suspend->copy(_manaCost->suspend);
} }
SAFE_DELETE(Bestow);
if (_manaCost->Bestow)
{
Bestow = NEW ManaCost();
Bestow->copy(_manaCost->Bestow);
}
xColor = _manaCost->xColor; xColor = _manaCost->xColor;
} }
@@ -1092,6 +1105,7 @@ void ManaPool::Empty()
SAFE_DELETE(Retrace); SAFE_DELETE(Retrace);
SAFE_DELETE(morph); SAFE_DELETE(morph);
SAFE_DELETE(suspend); SAFE_DELETE(suspend);
SAFE_DELETE(Bestow);
SAFE_DELETE(manaUsedToCast); SAFE_DELETE(manaUsedToCast);
init(); init();
WEvent * e = NEW WEventEmptyManaPool(this); WEvent * e = NEW WEventEmptyManaPool(this);
+3 -2
View File
@@ -413,12 +413,13 @@ void Rules::initGame(GameObserver *g, bool currentPlayerSet)
{ {
p->mAvatarName = initState.playerData[i].player->mAvatarName; p->mAvatarName = initState.playerData[i].player->mAvatarName;
} }
MTGGameZone * playerZones[] = { p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay, p->game->exile }; MTGGameZone * playerZones[] = { p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay, p->game->exile , p->game->reveal };
MTGGameZone * loadedPlayerZones[] = { initState.playerData[i].player->game->graveyard, MTGGameZone * loadedPlayerZones[] = { initState.playerData[i].player->game->graveyard,
initState.playerData[i].player->game->library, initState.playerData[i].player->game->library,
initState.playerData[i].player->game->hand, initState.playerData[i].player->game->hand,
initState.playerData[i].player->game->inPlay, initState.playerData[i].player->game->inPlay,
initState.playerData[i].player->game->exile }; initState.playerData[i].player->game->exile,
initState.playerData[i].player->game->reveal };
for (int j = 0; j < 5; j++) for (int j = 0; j < 5; j++)
{ {
MTGGameZone * zone = playerZones[j]; MTGGameZone * zone = playerZones[j];
+15 -5
View File
@@ -156,6 +156,11 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
{ {
zones[nbzones++] = MTGGameZone::ALL_ZONES; zones[nbzones++] = MTGGameZone::ALL_ZONES;
} }
else if (zoneName.compare("reveal") == 0)
{
zones[nbzones++] = MTGGameZone::MY_REVEAL;
zones[nbzones++] = MTGGameZone::OPPONENT_REVEAL;
}
else if (zoneName.compare("graveyard") == 0) else if (zoneName.compare("graveyard") == 0)
{ {
zones[nbzones++] = MTGGameZone::MY_GRAVEYARD; zones[nbzones++] = MTGGameZone::MY_GRAVEYARD;
@@ -637,7 +642,7 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
} }
} }
if (attribute.find("iscolorless") != string::npos) if (attribute.find("colorless") != string::npos)
{ {
attributefound = 1; attributefound = 1;
for (int cid = 1; cid < Constants::NB_Colors; cid++) for (int cid = 1; cid < Constants::NB_Colors; cid++)
@@ -817,6 +822,7 @@ TargetChooser::TargetChooser(GameObserver *observer, MTGCardInstance * card, int
TargetsList(), observer(observer) TargetsList(), observer(observer)
{ {
forceTargetListReady = 0; forceTargetListReady = 0;
forceTargetListReadyByPlayer = 0;
source = card; source = card;
targetter = card; targetter = card;
maxtargets = _maxtargets; maxtargets = _maxtargets;
@@ -899,6 +905,10 @@ int TargetChooser::ForceTargetListReady()
int TargetChooser::targetsReadyCheck() int TargetChooser::targetsReadyCheck()
{ {
if (targetMin == false && !targets.size() && forceTargetListReadyByPlayer)
{
return TARGET_OK_FULL;//we have no min amount for targets and 0 targets is a valid amount player called for a forced finish.
}
if (!targets.size()) if (!targets.size())
{ {
return TARGET_NOK; return TARGET_NOK;
@@ -931,8 +941,8 @@ bool TargetChooser::validTargetsExist(int maxTargets)
int maxAmount = 0; int maxAmount = 0;
Player *p = observer->players[i]; Player *p = observer->players[i];
if (canTarget(p)) return true; if (canTarget(p)) return true;
MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->exile, p->game->stack }; MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->exile, p->game->stack, p->game->reveal };
for (int k = 0; k < 6; k++) for (int k = 0; k < 7; k++)
{ {
MTGGameZone * z = zones[k]; MTGGameZone * z = zones[k];
if (targetsZone(z)) if (targetsZone(z))
@@ -965,8 +975,8 @@ int TargetChooser::countValidTargets(bool withoutProtections)
Player *p = observer->players[i]; Player *p = observer->players[i];
if(canTarget(p)) if(canTarget(p))
result++; result++;
MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->exile, p->game->stack }; MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->exile, p->game->stack, p->game->reveal };
for (int k = 0; k < 6; k++) for (int k = 0; k < 7; k++)
{ {
MTGGameZone * z = zones[k]; MTGGameZone * z = zones[k];
if (targetsZone(z)) if (targetsZone(z))
+1
View File
@@ -123,6 +123,7 @@ WEventTarget::WEventTarget(MTGCardInstance * card,MTGCardInstance * source) :
WEventCardUpdate(card),card(card),source(source) WEventCardUpdate(card),card(card),source(source)
{ {
card->cardistargetted = 1; card->cardistargetted = 1;
if(source)
source->cardistargetter = 1; source->cardistargetter = 1;
} }