ok this is the last commit but i had massive issues after chopping it all up, hopefully it doesn't hilight everything that was already commited...if it does i apologize my own patch started giving me conflicts....
im like 7 tries into commiting this part....
This commit is contained in:
@@ -1004,9 +1004,10 @@ class IfThenAbility: public InstantAbility
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MTGAbility * delayedAbility;
|
MTGAbility * delayedAbility;
|
||||||
|
MTGAbility * delayedElseAbility;
|
||||||
int type;
|
int type;
|
||||||
string Cond;
|
string Cond;
|
||||||
IfThenAbility(GameObserver* observer, int _id,MTGAbility * delayedAbility = NULL, MTGCardInstance * _source=NULL, Targetable * target = NULL, int type = 1,string Cond = "");
|
IfThenAbility(GameObserver* observer, int _id,MTGAbility * delayedAbility = NULL,MTGAbility * delayedElseAbility = NULL, MTGCardInstance * _source=NULL, Targetable * target = NULL, int type = 1,string Cond = "");
|
||||||
int resolve();
|
int resolve();
|
||||||
const char * getMenuText();
|
const char * getMenuText();
|
||||||
IfThenAbility * clone() const;
|
IfThenAbility * clone() const;
|
||||||
@@ -1110,6 +1111,16 @@ public:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//place a card on the bottom of owners library
|
||||||
|
class AALibraryBottom: public ActivatedAbility
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AALibraryBottom(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target = NULL, ManaCost * _cost = NULL);
|
||||||
|
int resolve();
|
||||||
|
const char * getMenuText();
|
||||||
|
AALibraryBottom * clone() const;
|
||||||
|
};
|
||||||
|
|
||||||
//Copier. ActivatedAbility
|
//Copier. ActivatedAbility
|
||||||
class AACopier: public ActivatedAbility
|
class AACopier: public ActivatedAbility
|
||||||
{
|
{
|
||||||
@@ -2659,6 +2670,11 @@ public:
|
|||||||
if(sabilities.find("battleready") != string::npos)
|
if(sabilities.find("battleready") != string::npos)
|
||||||
battleReady = true;
|
battleReady = true;
|
||||||
|
|
||||||
|
if(sabilities.find("chosencolor") != string::npos)
|
||||||
|
{
|
||||||
|
colors.push_back(source->chooseacolor);
|
||||||
|
}
|
||||||
|
|
||||||
for (int j = 0; j < Constants::NB_Colors; j++)
|
for (int j = 0; j < Constants::NB_Colors; j++)
|
||||||
{
|
{
|
||||||
size_t found = sabilities.find(Constants::MTGColorStrings[j]);
|
size_t found = sabilities.find(Constants::MTGColorStrings[j]);
|
||||||
@@ -2674,12 +2690,21 @@ public:
|
|||||||
size_t found = s.find(" ");
|
size_t found = s.find(" ");
|
||||||
if (found != string::npos)
|
if (found != string::npos)
|
||||||
{
|
{
|
||||||
int id = MTGAllCards::findType(s.substr(0, found));
|
string toCheck = s.substr(0, found);
|
||||||
|
if(toCheck.find("chosentype") != string::npos || toCheck.find("Chosentype") != string::npos)
|
||||||
|
{
|
||||||
|
toCheck = source->chooseasubtype;
|
||||||
|
}
|
||||||
|
int id = MTGAllCards::findType(toCheck);
|
||||||
types.push_back(id);
|
types.push_back(id);
|
||||||
s = s.substr(found + 1);
|
s = s.substr(found + 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if(s.find("chosentype") != string::npos || s.find("Chosentype") != string::npos)
|
||||||
|
{
|
||||||
|
s = source->chooseasubtype;
|
||||||
|
}
|
||||||
int id = MTGAllCards::findType(s);
|
int id = MTGAllCards::findType(s);
|
||||||
types.push_back(id);
|
types.push_back(id);
|
||||||
s = "";
|
s = "";
|
||||||
@@ -3406,6 +3431,17 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class AAExchangeLife: public ActivatedAbilityTP
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AAExchangeLife(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, ManaCost * _cost = NULL,
|
||||||
|
int who = TargetChooser::UNSET);
|
||||||
|
int resolve();
|
||||||
|
const char * getMenuText();
|
||||||
|
AAExchangeLife * clone() const;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
// Add life of gives damage if a given zone has more or less than [condition] cards at the beginning of [phase]
|
// Add life of gives damage if a given zone has more or less than [condition] cards at the beginning of [phase]
|
||||||
//Ex : the rack, ivory tower...
|
//Ex : the rack, ivory tower...
|
||||||
class ALifeZoneLink: public MTGAbility
|
class ALifeZoneLink: public MTGAbility
|
||||||
@@ -4951,9 +4987,6 @@ public:
|
|||||||
return NEW APhaseAlter(*this);
|
return NEW APhaseAlter(*this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//--------------Addon Abra------------------
|
|
||||||
|
|
||||||
//Basilik --> needs to be made more generic to avoid duplicate (also something like if opponent=type then ...)
|
//Basilik --> needs to be made more generic to avoid duplicate (also something like if opponent=type then ...)
|
||||||
class ABasilik: public MTGAbility
|
class ABasilik: public MTGAbility
|
||||||
{
|
{
|
||||||
@@ -5015,6 +5048,19 @@ public:
|
|||||||
AADepleter * clone() const;
|
AADepleter * clone() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//Generic skip turn/extra turn
|
||||||
|
class AAModTurn: public ActivatedAbilityTP
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
string nbTurnStr;
|
||||||
|
|
||||||
|
AAModTurn(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target,string nbTurnStr, ManaCost * _cost = NULL,
|
||||||
|
int who = TargetChooser::UNSET);
|
||||||
|
int resolve();
|
||||||
|
const char * getMenuText();
|
||||||
|
AAModTurn * clone() const;
|
||||||
|
};
|
||||||
|
|
||||||
//Shuffle
|
//Shuffle
|
||||||
class AAShuffle: public ActivatedAbilityTP
|
class AAShuffle: public ActivatedAbilityTP
|
||||||
{
|
{
|
||||||
@@ -5283,6 +5329,15 @@ public:
|
|||||||
int resolve()
|
int resolve()
|
||||||
{
|
{
|
||||||
MTGCardInstance * _theftTarget = (MTGCardInstance*)target;
|
MTGCardInstance * _theftTarget = (MTGCardInstance*)target;
|
||||||
|
bool recast = false;
|
||||||
|
if(!_theftTarget->isInPlay(game))
|
||||||
|
{
|
||||||
|
recast = true;
|
||||||
|
}
|
||||||
|
while(_theftTarget->next)
|
||||||
|
{
|
||||||
|
_theftTarget= _theftTarget->next;
|
||||||
|
}
|
||||||
if(_theftTarget)
|
if(_theftTarget)
|
||||||
{
|
{
|
||||||
TrueController = _theftTarget->controller();
|
TrueController = _theftTarget->controller();
|
||||||
@@ -5291,7 +5346,13 @@ public:
|
|||||||
target = copy;
|
target = copy;
|
||||||
source->target = copy;
|
source->target = copy;
|
||||||
copy->summoningSickness = 0;
|
copy->summoningSickness = 0;
|
||||||
|
if(recast)
|
||||||
|
{
|
||||||
|
Spell * spell = NEW Spell(game, copy);
|
||||||
|
spell->resolve();
|
||||||
|
SAFE_DELETE(spell);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5318,6 +5379,76 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//----------------------------------------------
|
||||||
|
class AASetColorChosen: public InstantAbility
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int color;
|
||||||
|
string abilityToAlter;
|
||||||
|
MTGAbility * abilityAltered;
|
||||||
|
AASetColorChosen(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target, int _color = 0 ,string toAdd = "");
|
||||||
|
int resolve();
|
||||||
|
const char* getMenuText();
|
||||||
|
AASetColorChosen * clone() const;
|
||||||
|
~AASetColorChosen();
|
||||||
|
};
|
||||||
|
class AASetTypeChosen: public InstantAbility
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int type;
|
||||||
|
string menutext;
|
||||||
|
string abilityToAlter;
|
||||||
|
MTGAbility * abilityAltered;
|
||||||
|
AASetTypeChosen(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target, int _type = 0,string menu = "error" ,string toAdd = "");
|
||||||
|
int resolve();
|
||||||
|
const char* getMenuText();
|
||||||
|
AASetTypeChosen * clone() const;
|
||||||
|
~AASetTypeChosen();
|
||||||
|
};
|
||||||
|
class GenericChooseTypeColor: public ActivatedAbility
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
string baseAbility;
|
||||||
|
bool chooseColor;
|
||||||
|
AASetColorChosen * setColor;
|
||||||
|
AASetTypeChosen * setType;
|
||||||
|
bool ANonWall;
|
||||||
|
GenericChooseTypeColor(GameObserver* observer, int id, MTGCardInstance * source, Targetable * target, string toAdd = "",bool chooseColor = false,bool nonwall = false, ManaCost * cost = NULL);
|
||||||
|
int resolve();
|
||||||
|
const char* getMenuText();
|
||||||
|
GenericChooseTypeColor * clone() const;
|
||||||
|
~GenericChooseTypeColor();
|
||||||
|
|
||||||
|
};
|
||||||
|
//------------------------------------------------
|
||||||
|
//flip a coin and call it, with win or lose abilities
|
||||||
|
class AASetCoin: public InstantAbility
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int side;
|
||||||
|
string abilityToAlter;
|
||||||
|
string abilityWin;
|
||||||
|
string abilityLose;
|
||||||
|
MTGAbility * abilityAltered;
|
||||||
|
AASetCoin(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target, int side = -1,string toAdd = "");
|
||||||
|
int resolve();
|
||||||
|
const char* getMenuText();
|
||||||
|
AASetCoin * clone() const;
|
||||||
|
~AASetCoin();
|
||||||
|
};
|
||||||
|
class GenericFlipACoin: public ActivatedAbility
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
string baseAbility;
|
||||||
|
bool chooseColor;
|
||||||
|
AASetCoin * setCoin;
|
||||||
|
GenericFlipACoin(GameObserver* observer, int id, MTGCardInstance * source, Targetable * target, string toAdd = "", ManaCost * cost = NULL);
|
||||||
|
int resolve();
|
||||||
|
const char* getMenuText();
|
||||||
|
GenericFlipACoin * clone() const;
|
||||||
|
~GenericFlipACoin();
|
||||||
|
|
||||||
|
};
|
||||||
// utility functions
|
// utility functions
|
||||||
|
|
||||||
void PopulateColorIndexVector(list<int>& colors, const string& colorsString, char delimiter = ',');
|
void PopulateColorIndexVector(list<int>& colors, const string& colorsString, char delimiter = ',');
|
||||||
|
|||||||
@@ -212,8 +212,12 @@ class Constants
|
|||||||
HYDRA = 92,
|
HYDRA = 92,
|
||||||
UNDYING = 93,
|
UNDYING = 93,
|
||||||
POISONSHROUD = 94,
|
POISONSHROUD = 94,
|
||||||
|
NOACTIVATED = 95,
|
||||||
|
NOACTIVATEDTAP = 96,
|
||||||
|
NOMANA = 97,
|
||||||
|
ONLYMANA = 98,
|
||||||
|
|
||||||
NB_BASIC_ABILITIES = 95,
|
NB_BASIC_ABILITIES = 99,
|
||||||
|
|
||||||
|
|
||||||
RARITY_S = 'S', //Special Rarity
|
RARITY_S = 'S', //Special Rarity
|
||||||
|
|||||||
@@ -203,6 +203,33 @@ public:
|
|||||||
virtual MTGAttackRule * clone() const;
|
virtual MTGAttackRule * clone() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class MTGPlaneswalkerAttackRule: public PermanentAbility, public Limitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual bool select(Target*);
|
||||||
|
virtual bool greyout(Target*);
|
||||||
|
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL);
|
||||||
|
int reactToClick(MTGCardInstance * card);
|
||||||
|
MTGPlaneswalkerAttackRule(GameObserver* observer, int _id);
|
||||||
|
const char * getMenuText()
|
||||||
|
{
|
||||||
|
return "Attack Planeswalker";
|
||||||
|
}
|
||||||
|
virtual MTGPlaneswalkerAttackRule * clone() const;
|
||||||
|
};
|
||||||
|
class AAPlaneswalkerAttacked: public InstantAbility
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
string menuText;
|
||||||
|
MTGCardInstance* attacker;
|
||||||
|
AAPlaneswalkerAttacked(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target);
|
||||||
|
int resolve();
|
||||||
|
const char* getMenuText();
|
||||||
|
AAPlaneswalkerAttacked * clone() const;
|
||||||
|
~AAPlaneswalkerAttacked();
|
||||||
|
};
|
||||||
/* handles combat trigger send recieve events*/
|
/* handles combat trigger send recieve events*/
|
||||||
class MTGCombatTriggersRule: public PermanentAbility
|
class MTGCombatTriggersRule: public PermanentAbility
|
||||||
{
|
{
|
||||||
@@ -292,7 +319,16 @@ public:
|
|||||||
virtual ostream& toString(ostream& out) const;
|
virtual ostream& toString(ostream& out) const;
|
||||||
virtual MTGPlaneWalkerRule * clone() const;
|
virtual MTGPlaneWalkerRule * clone() const;
|
||||||
};
|
};
|
||||||
|
/* LifeLink */
|
||||||
|
class MTGPlaneswalkerDamage: public PermanentAbility
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MTGPlaneswalkerDamage(GameObserver* observer, int _id);
|
||||||
|
|
||||||
|
int receiveEvent(WEvent * event);
|
||||||
|
|
||||||
|
virtual MTGPlaneswalkerDamage * clone() const;
|
||||||
|
};
|
||||||
class MTGMomirRule: public PermanentAbility
|
class MTGMomirRule: public PermanentAbility
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -183,6 +183,7 @@ AADamager::AADamager(GameObserver* observer, int _id, MTGCardInstance * _source,
|
|||||||
ActivatedAbilityTP(observer, _id, _source, _target, _cost, who), d(d)
|
ActivatedAbilityTP(observer, _id, _source, _target, _cost, who), d(d)
|
||||||
{
|
{
|
||||||
aType = MTGAbility::DAMAGER;
|
aType = MTGAbility::DAMAGER;
|
||||||
|
redirected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AADamager::resolve()
|
int AADamager::resolve()
|
||||||
@@ -191,6 +192,33 @@ AADamager::AADamager(GameObserver* observer, int _id, MTGCardInstance * _source,
|
|||||||
if (_target)
|
if (_target)
|
||||||
{
|
{
|
||||||
WParsedInt damage(d, NULL, (MTGCardInstance *)source);
|
WParsedInt damage(d, NULL, (MTGCardInstance *)source);
|
||||||
|
if(_target == game->opponent() && game->opponent()->inPlay()->hasType("planeswalker") && !redirected)
|
||||||
|
{
|
||||||
|
vector<MTGAbility*>selection;
|
||||||
|
MTGCardInstance * check = NULL;
|
||||||
|
this->redirected = true;
|
||||||
|
MTGAbility * setPlayer = this->clone();
|
||||||
|
selection.push_back(setPlayer);
|
||||||
|
int checkWalkers = ((Player*)_target)->game->battlefield->cards.size();
|
||||||
|
for(int i = 0; i < checkWalkers;++i)
|
||||||
|
{
|
||||||
|
check = ((Player*)_target)->game->battlefield->cards[i];
|
||||||
|
if(check->hasType(Subtypes::TYPE_PLANESWALKER))
|
||||||
|
{
|
||||||
|
MTGAbility * setWalker = this->clone();
|
||||||
|
setWalker->oneShot = true;
|
||||||
|
setWalker->target = check;
|
||||||
|
selection.push_back(setWalker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(selection.size())
|
||||||
|
{
|
||||||
|
MTGAbility * a1 = NEW MenuAbility(game, this->GetId(), source, source,true,selection);
|
||||||
|
game->mLayers->actionLayer()->currentActionCard = source;
|
||||||
|
a1->resolve();
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
game->mLayers->stackLayer()->addDamage(source, _target, damage.getValue());
|
game->mLayers->stackLayer()->addDamage(source, _target, damage.getValue());
|
||||||
game->mLayers->stackLayer()->resolve();
|
game->mLayers->stackLayer()->resolve();
|
||||||
return 1;
|
return 1;
|
||||||
@@ -206,6 +234,11 @@ AADamager::AADamager(GameObserver* observer, int _id, MTGCardInstance * _source,
|
|||||||
|
|
||||||
const char * AADamager::getMenuText()
|
const char * AADamager::getMenuText()
|
||||||
{
|
{
|
||||||
|
MTGCardInstance * _target = dynamic_cast<MTGCardInstance*>(target);
|
||||||
|
if(_target && _target->hasType(Subtypes::TYPE_PLANESWALKER))
|
||||||
|
return _target->name.c_str();
|
||||||
|
if(redirected)
|
||||||
|
return "Damage Player";
|
||||||
return "Damage";
|
return "Damage";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,6 +281,83 @@ AADepleter * AADepleter::clone() const
|
|||||||
return NEW AADepleter(*this);
|
return NEW AADepleter(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//take extra turns or skip turns, values in the negitive will make you skip.
|
||||||
|
AAModTurn::AAModTurn(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target,string nbTurnStr, ManaCost * _cost, int who) :
|
||||||
|
ActivatedAbilityTP(observer, _id, card, _target, _cost, who),nbTurnStr(nbTurnStr)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
int AAModTurn::resolve()
|
||||||
|
{
|
||||||
|
Player * player = getPlayerFromTarget(getTarget());
|
||||||
|
if (player)
|
||||||
|
{
|
||||||
|
WParsedInt numTurns(nbTurnStr, NULL, source);
|
||||||
|
if(numTurns.getValue() > 0)
|
||||||
|
{
|
||||||
|
player->extraTurn += numTurns.getValue();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
player->skippingTurn += abs(numTurns.getValue());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * AAModTurn::getMenuText()
|
||||||
|
{
|
||||||
|
WParsedInt numTurns(nbTurnStr, NULL, source);
|
||||||
|
if(numTurns.getValue() > 0)
|
||||||
|
return "Take Extra Turn(s)";
|
||||||
|
else
|
||||||
|
return "Skip A Turn(s)";
|
||||||
|
}
|
||||||
|
|
||||||
|
AAModTurn * AAModTurn::clone() const
|
||||||
|
{
|
||||||
|
return NEW AAModTurn(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
//move target to bottom of owners library
|
||||||
|
AALibraryBottom::AALibraryBottom(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target, ManaCost * _cost) :
|
||||||
|
ActivatedAbility(observer, _id, _source, _cost, 0)
|
||||||
|
{
|
||||||
|
target = _target;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AALibraryBottom::resolve()
|
||||||
|
{
|
||||||
|
MTGCardInstance * _target = (MTGCardInstance *) target;
|
||||||
|
if (_target = _target->owner->game->putInLibrary(_target))
|
||||||
|
{
|
||||||
|
MTGLibrary * library = _target->owner->game->library;
|
||||||
|
vector<MTGCardInstance *>oldOrder = library->cards;
|
||||||
|
vector<MTGCardInstance *>newOrder;
|
||||||
|
newOrder.push_back(_target);
|
||||||
|
for(unsigned int k = 0;k < oldOrder.size();++k)
|
||||||
|
{
|
||||||
|
MTGCardInstance * rearranged = oldOrder[k];
|
||||||
|
if(rearranged != _target)
|
||||||
|
newOrder.push_back(rearranged);
|
||||||
|
}
|
||||||
|
library->cards = newOrder;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * AALibraryBottom::getMenuText()
|
||||||
|
{
|
||||||
|
return "Bottom Of Library";
|
||||||
|
}
|
||||||
|
|
||||||
|
AALibraryBottom * AALibraryBottom::clone() const
|
||||||
|
{
|
||||||
|
return NEW AALibraryBottom(*this);
|
||||||
|
}
|
||||||
|
|
||||||
//AACopier
|
//AACopier
|
||||||
AACopier::AACopier(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target, ManaCost * _cost) :
|
AACopier::AACopier(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target, ManaCost * _cost) :
|
||||||
ActivatedAbility(observer, _id, _source, _cost, 0)
|
ActivatedAbility(observer, _id, _source, _cost, 0)
|
||||||
@@ -670,8 +780,318 @@ AAProliferate * AAProliferate::clone() const
|
|||||||
AAProliferate::~AAProliferate()
|
AAProliferate::~AAProliferate()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
//choosing a type or color
|
||||||
|
GenericChooseTypeColor::GenericChooseTypeColor(GameObserver* observer, int id, MTGCardInstance * source, Targetable * target,string _toAdd,bool chooseColor,bool nonwall, ManaCost * cost) :
|
||||||
|
ActivatedAbility(observer, id, source, cost, 0), baseAbility(_toAdd),chooseColor(chooseColor),ANonWall(nonwall)
|
||||||
|
{
|
||||||
|
this->GetId();
|
||||||
|
setColor = NULL;
|
||||||
|
}
|
||||||
|
int GenericChooseTypeColor::resolve()
|
||||||
|
{
|
||||||
|
if (!target)
|
||||||
|
return 0;
|
||||||
|
vector<MTGAbility*>selection;
|
||||||
|
if(chooseColor)
|
||||||
|
{
|
||||||
|
for (int i = Constants::MTG_COLOR_GREEN; i <= Constants::MTG_COLOR_WHITE; ++i)
|
||||||
|
{
|
||||||
|
setColor = NEW AASetColorChosen(game, game->mLayers->actionLayer()->getMaxId(), source,(MTGCardInstance*)target, i, baseAbility);
|
||||||
|
MTGAbility * set = setColor->clone();
|
||||||
|
set->oneShot = true;
|
||||||
|
selection.push_back(set);
|
||||||
|
SAFE_DELETE(setColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vector<string> values = MTGAllCards::getCreatureValuesById();
|
||||||
|
for (size_t i = 0; i < values.size(); ++i)
|
||||||
|
{
|
||||||
|
string menu = values[i];
|
||||||
|
if(!ANonWall || (menu != "wall" && menu != "Wall"))
|
||||||
|
{
|
||||||
|
setType = NEW AASetTypeChosen(game, game->mLayers->actionLayer()->getMaxId(), source,(MTGCardInstance*)target, i,menu,baseAbility);
|
||||||
|
MTGAbility * set = setType->clone();
|
||||||
|
set->oneShot = true;
|
||||||
|
selection.push_back(set);
|
||||||
|
SAFE_DELETE(setType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(selection.size())
|
||||||
|
{
|
||||||
|
MTGAbility * a1 = NEW MenuAbility(game, this->GetId(), target, source,true,selection);
|
||||||
|
game->mLayers->actionLayer()->currentActionCard = (MTGCardInstance *)target;
|
||||||
|
a1->resolve();
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* GenericChooseTypeColor::getMenuText()
|
||||||
|
{
|
||||||
|
if(chooseColor)
|
||||||
|
return "Choose a color";
|
||||||
|
else
|
||||||
|
return "Choose a type";
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericChooseTypeColor * GenericChooseTypeColor::clone() const
|
||||||
|
{
|
||||||
|
GenericChooseTypeColor * a = NEW GenericChooseTypeColor(*this);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericChooseTypeColor::~GenericChooseTypeColor()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//set color choosen
|
||||||
|
AASetColorChosen::AASetColorChosen(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * _target,int _color , string toAlter):
|
||||||
|
InstantAbility(observer, id, source),color(_color), abilityToAlter(toAlter)
|
||||||
|
{
|
||||||
|
this->target = _target;
|
||||||
|
abilityAltered = NULL;
|
||||||
|
}
|
||||||
|
int AASetColorChosen::resolve()
|
||||||
|
{
|
||||||
|
MTGCardInstance * _target = (MTGCardInstance *)target;
|
||||||
|
_target->chooseacolor = color;
|
||||||
|
|
||||||
|
if(abilityToAlter.size())
|
||||||
|
{
|
||||||
|
AbilityFactory af(game);
|
||||||
|
abilityAltered = af.parseMagicLine(abilityToAlter, 0, NULL, _target);
|
||||||
|
if(!abilityAltered)
|
||||||
|
return 0;
|
||||||
|
abilityAltered->canBeInterrupted = false;
|
||||||
|
if(abilityAltered->oneShot)
|
||||||
|
{
|
||||||
|
abilityAltered->resolve();
|
||||||
|
SAFE_DELETE(abilityAltered);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
abilityAltered->target = _target;
|
||||||
|
MayAbility * dontAdd = dynamic_cast<MayAbility*>(abilityAltered);
|
||||||
|
if (!dontAdd)
|
||||||
|
{
|
||||||
|
_target->cardsAbilities.push_back(abilityAltered);
|
||||||
|
for(unsigned int j = 0;j < _target->cardsAbilities.size();++j)
|
||||||
|
{
|
||||||
|
if(_target->cardsAbilities[j] == this)
|
||||||
|
_target->cardsAbilities.erase(_target->cardsAbilities.begin() + j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
abilityAltered->addToGame();
|
||||||
|
}
|
||||||
|
_target->skipDamageTestOnce = true;//some cards rely on this ability updating before damage test are run. otherwise they die before toughnes bonus applies.
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* AASetColorChosen::getMenuText()
|
||||||
|
{
|
||||||
|
return Constants::MTGColorStrings[color];
|
||||||
|
}
|
||||||
|
|
||||||
|
AASetColorChosen * AASetColorChosen::clone() const
|
||||||
|
{
|
||||||
|
return NEW AASetColorChosen(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
AASetColorChosen::~AASetColorChosen()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//set type choosen
|
||||||
|
AASetTypeChosen::AASetTypeChosen(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * _target,int _type ,string _menu,string toAlter):
|
||||||
|
InstantAbility(observer, id, source),type(_type), abilityToAlter(toAlter), menutext(_menu)
|
||||||
|
{
|
||||||
|
this->target = _target;
|
||||||
|
abilityAltered = NULL;
|
||||||
|
}
|
||||||
|
int AASetTypeChosen::resolve()
|
||||||
|
{
|
||||||
|
MTGCardInstance * _target = (MTGCardInstance *)target;
|
||||||
|
string typeChoosen = menutext;
|
||||||
|
_target->chooseasubtype = typeChoosen;
|
||||||
|
|
||||||
|
if(abilityToAlter.size())
|
||||||
|
{
|
||||||
|
AbilityFactory af(game);
|
||||||
|
abilityAltered = af.parseMagicLine(abilityToAlter, 0, NULL, _target);
|
||||||
|
if(abilityAltered->oneShot)
|
||||||
|
{
|
||||||
|
abilityAltered->resolve();
|
||||||
|
SAFE_DELETE(abilityAltered);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
abilityAltered->target = _target;
|
||||||
|
MayAbility * dontAdd = dynamic_cast<MayAbility*>(abilityAltered);
|
||||||
|
if (!dontAdd)
|
||||||
|
{
|
||||||
|
_target->cardsAbilities.push_back(abilityAltered);
|
||||||
|
for(unsigned int j = 0;j < _target->cardsAbilities.size();++j)
|
||||||
|
{
|
||||||
|
if(_target->cardsAbilities[j] == this)
|
||||||
|
_target->cardsAbilities.erase(_target->cardsAbilities.begin() + j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abilityAltered->addToGame();
|
||||||
|
}
|
||||||
|
_target->skipDamageTestOnce = true;//some cards rely on this ability updating before damage test are run. otherwise they die before toughnes bonus applies.
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* AASetTypeChosen::getMenuText()
|
||||||
|
{
|
||||||
|
return menutext.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
AASetTypeChosen * AASetTypeChosen::clone() const
|
||||||
|
{
|
||||||
|
return NEW AASetTypeChosen(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
AASetTypeChosen::~AASetTypeChosen()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
//choosing a type or color
|
||||||
|
GenericFlipACoin::GenericFlipACoin(GameObserver* observer, int id, MTGCardInstance * source, Targetable * target,string _toAdd, ManaCost * cost) :
|
||||||
|
ActivatedAbility(observer, id, source, cost, 0), baseAbility(_toAdd),chooseColor(chooseColor)
|
||||||
|
{
|
||||||
|
this->GetId();
|
||||||
|
setCoin = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GenericFlipACoin::resolve()
|
||||||
|
{
|
||||||
|
if (!target)
|
||||||
|
return 0;
|
||||||
|
vector<MTGAbility*>selection;
|
||||||
|
for (int i = 0; i <2; ++i)
|
||||||
|
{
|
||||||
|
setCoin = NEW AASetCoin(game, game->mLayers->actionLayer()->getMaxId(), source,(MTGCardInstance*)target, i, baseAbility);
|
||||||
|
MTGAbility * set = setCoin->clone();
|
||||||
|
set->oneShot = true;
|
||||||
|
selection.push_back(set);
|
||||||
|
SAFE_DELETE(setCoin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(selection.size())
|
||||||
|
{
|
||||||
|
MTGAbility * a1 = NEW MenuAbility(game, this->GetId(), target, source,false,selection);
|
||||||
|
game->mLayers->actionLayer()->currentActionCard = (MTGCardInstance *)target;
|
||||||
|
a1->resolve();
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* GenericFlipACoin::getMenuText()
|
||||||
|
{
|
||||||
|
return "Flip A Coin";
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericFlipACoin * GenericFlipACoin::clone() const
|
||||||
|
{
|
||||||
|
GenericFlipACoin * a = NEW GenericFlipACoin(*this);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericFlipACoin::~GenericFlipACoin()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//set color choosen
|
||||||
|
AASetCoin::AASetCoin(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * _target,int _side , string toAlter):
|
||||||
|
InstantAbility(observer, id, source),side(_side), abilityToAlter(toAlter)
|
||||||
|
{
|
||||||
|
this->target = _target;
|
||||||
|
abilityAltered = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AASetCoin::resolve()
|
||||||
|
{
|
||||||
|
MTGCardInstance * _target = (MTGCardInstance *)target;
|
||||||
|
_target->coinSide = side;
|
||||||
|
|
||||||
|
int flip = game->getRandomGenerator()->random() % 2;
|
||||||
|
vector<string>Win = parseBetween(abilityToAlter,"winability "," winabilityend");
|
||||||
|
if(Win.size())
|
||||||
|
{
|
||||||
|
abilityWin = Win[1];
|
||||||
|
}
|
||||||
|
vector<string>Lose = parseBetween(abilityToAlter,"loseability "," loseabilityend");
|
||||||
|
if(Lose.size())
|
||||||
|
{
|
||||||
|
abilityLose = Lose[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(abilityWin.size() && flip == side)
|
||||||
|
{
|
||||||
|
AbilityFactory af(game);
|
||||||
|
abilityAltered = af.parseMagicLine(abilityWin, 0, NULL, _target);
|
||||||
|
abilityAltered->canBeInterrupted = false;
|
||||||
|
if(abilityAltered->oneShot)
|
||||||
|
{
|
||||||
|
abilityAltered->resolve();
|
||||||
|
SAFE_DELETE(abilityAltered);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
abilityAltered->addToGame();
|
||||||
|
}
|
||||||
|
MTGAbility * message = NEW MTGEventText(game,this->GetId(), source, "You Won The Flip");
|
||||||
|
message->oneShot = true;
|
||||||
|
message->addToGame();
|
||||||
|
}
|
||||||
|
else if(abilityLose.size() && flip != side)
|
||||||
|
{
|
||||||
|
AbilityFactory af(game);
|
||||||
|
abilityAltered = af.parseMagicLine(abilityLose, 0, NULL, _target);
|
||||||
|
abilityAltered->canBeInterrupted = false;
|
||||||
|
if(abilityAltered->oneShot)
|
||||||
|
{
|
||||||
|
abilityAltered->resolve();
|
||||||
|
SAFE_DELETE(abilityAltered);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
abilityAltered->addToGame();
|
||||||
|
}
|
||||||
|
MTGAbility * message = NEW MTGEventText(game,this->GetId(), source, "You Lost The Flip");
|
||||||
|
message->oneShot = true;
|
||||||
|
message->addToGame();
|
||||||
|
}
|
||||||
|
_target->skipDamageTestOnce = true;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* AASetCoin::getMenuText()
|
||||||
|
{
|
||||||
|
if(side == 1)
|
||||||
|
return "Tails";
|
||||||
|
return "Heads";
|
||||||
|
}
|
||||||
|
|
||||||
|
AASetCoin * AASetCoin::clone() const
|
||||||
|
{
|
||||||
|
return NEW AASetCoin(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
AASetCoin::~AASetCoin()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
//Reset Damage on creatures
|
//Reset Damage on creatures
|
||||||
AAResetDamage::AAResetDamage(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * _target, ManaCost * cost):
|
AAResetDamage::AAResetDamage(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * _target, ManaCost * cost):
|
||||||
@@ -2548,8 +2968,8 @@ ANewAffinity * ANewAffinity::clone() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
//IfThenEffect
|
//IfThenEffect
|
||||||
IfThenAbility::IfThenAbility(GameObserver* observer, int _id, MTGAbility * delayedAbility, MTGCardInstance * _source, Targetable * _target, int type,string Cond) :
|
IfThenAbility::IfThenAbility(GameObserver* observer, int _id, MTGAbility * delayedAbility, MTGAbility * delayedElseAbility, MTGCardInstance * _source, Targetable * _target, int type,string Cond) :
|
||||||
InstantAbility(observer, _id, _source),delayedAbility(delayedAbility), type(type),Cond(Cond)
|
InstantAbility(observer, _id, _source),delayedAbility(delayedAbility),delayedElseAbility(delayedElseAbility), type(type),Cond(Cond)
|
||||||
{
|
{
|
||||||
target = _target;
|
target = _target;
|
||||||
}
|
}
|
||||||
@@ -2575,12 +2995,19 @@ int IfThenAbility::resolve()
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
MTGAbility * a1 = NULL;
|
||||||
if((checkCond && type == 1)||(!checkCond && type == 2))
|
if((checkCond && type == 1)||(!checkCond && type == 2))
|
||||||
{
|
{
|
||||||
MTGAbility * a1 = delayedAbility->clone();
|
a1 = delayedAbility->clone();
|
||||||
if (!a1)
|
}
|
||||||
return 0;
|
else if(delayedElseAbility)
|
||||||
|
{
|
||||||
|
delayedElseAbility->clone();
|
||||||
|
}
|
||||||
|
if (!a1)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
if(a1->target && !dynamic_cast<Player *>(a1->target))
|
if(a1->target && !dynamic_cast<Player *>(a1->target))
|
||||||
a1->target = aTarget;
|
a1->target = aTarget;
|
||||||
|
|
||||||
@@ -2820,6 +3247,9 @@ MenuAbility::~MenuAbility()
|
|||||||
{
|
{
|
||||||
for(int i = 0;i < int(abilities.size());i++)
|
for(int i = 0;i < int(abilities.size());i++)
|
||||||
{
|
{
|
||||||
|
AASetColorChosen * chooseA = dynamic_cast<AASetColorChosen *>(abilities[i]);
|
||||||
|
if(chooseA && chooseA->abilityAltered)
|
||||||
|
SAFE_DELETE(chooseA->abilityAltered);
|
||||||
SAFE_DELETE(abilities[i]);
|
SAFE_DELETE(abilities[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3128,6 +3558,10 @@ ATransformer::ATransformer(GameObserver* observer, int id, MTGCardInstance * sou
|
|||||||
|
|
||||||
PopulateAbilityIndexVector(abilities, sabilities);
|
PopulateAbilityIndexVector(abilities, sabilities);
|
||||||
PopulateColorIndexVector(colors, sabilities);
|
PopulateColorIndexVector(colors, sabilities);
|
||||||
|
if(sabilities.find("chosencolor") != string::npos)
|
||||||
|
{
|
||||||
|
colors.push_back(source->chooseacolor);
|
||||||
|
}
|
||||||
|
|
||||||
//this subkeyword adds a color without removing the existing colors.
|
//this subkeyword adds a color without removing the existing colors.
|
||||||
addNewColors = (sabilities.find("newcolors") != string::npos);
|
addNewColors = (sabilities.find("newcolors") != string::npos);
|
||||||
@@ -3148,6 +3582,10 @@ ATransformer::ATransformer(GameObserver* observer, int id, MTGCardInstance * sou
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if(stypes.find("chosentype") != string::npos)
|
||||||
|
{
|
||||||
|
stypes = source->chooseasubtype;
|
||||||
|
}
|
||||||
PopulateSubtypesIndexVector(types, stypes);
|
PopulateSubtypesIndexVector(types, stypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3520,6 +3958,68 @@ ASwapPTUEOT::~ASwapPTUEOT()
|
|||||||
SAFE_DELETE(ability);
|
SAFE_DELETE(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//exhange life with targetchooser
|
||||||
|
AAExchangeLife::AAExchangeLife(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, ManaCost * _cost,
|
||||||
|
int who) :
|
||||||
|
ActivatedAbilityTP(observer, _id, _source, _target, _cost, who)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int AAExchangeLife::resolve()
|
||||||
|
{
|
||||||
|
Damageable * _target = (Damageable *) getTarget();
|
||||||
|
if (_target)
|
||||||
|
{
|
||||||
|
Player *player = source->controller();
|
||||||
|
int oldlife = player->getLife();
|
||||||
|
int targetOldLife = _target->getLife();
|
||||||
|
int modifier = oldlife > targetOldLife? oldlife - targetOldLife:targetOldLife - oldlife;
|
||||||
|
if (_target->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE)
|
||||||
|
{
|
||||||
|
int increaser = 0;
|
||||||
|
MTGCardInstance * card = ((MTGCardInstance*)_target);
|
||||||
|
int toughMod = 0;
|
||||||
|
targetOldLife <= card->origtoughness?toughMod = card->origtoughness - targetOldLife: toughMod = targetOldLife - card->origtoughness;
|
||||||
|
if(oldlife > targetOldLife)
|
||||||
|
{
|
||||||
|
increaser = oldlife - targetOldLife;
|
||||||
|
player->gainOrLoseLife(modifier * -1);
|
||||||
|
card->addToToughness(increaser+toughMod);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_target->life = oldlife;
|
||||||
|
card->toughness = oldlife;
|
||||||
|
player->gainOrLoseLife(modifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
Player * opponent = (Player*)_target;
|
||||||
|
if(oldlife > targetOldLife)
|
||||||
|
{
|
||||||
|
player->gainOrLoseLife(modifier * -1);
|
||||||
|
opponent->gainOrLoseLife(modifier);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
player->gainOrLoseLife(modifier);
|
||||||
|
opponent->gainOrLoseLife(modifier * -1);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * AAExchangeLife::getMenuText()
|
||||||
|
{
|
||||||
|
return "Exchange life";
|
||||||
|
}
|
||||||
|
|
||||||
|
AAExchangeLife * AAExchangeLife::clone() const
|
||||||
|
{
|
||||||
|
return NEW AAExchangeLife(*this);
|
||||||
|
}
|
||||||
|
|
||||||
//ALoseAbilities
|
//ALoseAbilities
|
||||||
ALoseAbilities::ALoseAbilities(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * _target) :
|
ALoseAbilities::ALoseAbilities(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * _target) :
|
||||||
|
|||||||
@@ -37,8 +37,6 @@ CardPrimitive::CardPrimitive()
|
|||||||
|
|
||||||
CardPrimitive::CardPrimitive(CardPrimitive * source)
|
CardPrimitive::CardPrimitive(CardPrimitive * source)
|
||||||
{
|
{
|
||||||
if(!source)
|
|
||||||
return;
|
|
||||||
if(!source)
|
if(!source)
|
||||||
return;
|
return;
|
||||||
basicAbilities = source->basicAbilities;
|
basicAbilities = source->basicAbilities;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
#include "GameObserver.h"
|
#include "GameObserver.h"
|
||||||
#include "MTGDeck.h"
|
#include "MTGDeck.h"
|
||||||
#include "ManaCostHybrid.h"
|
#include "ManacostHybrid.h"
|
||||||
|
|
||||||
DeckStats * DeckStats::mInstance = NULL;
|
DeckStats * DeckStats::mInstance = NULL;
|
||||||
|
|
||||||
|
|||||||
@@ -455,18 +455,37 @@ void GuiCombat::Render()
|
|||||||
(*it)->Render(step);
|
(*it)->Render(step);
|
||||||
if (activeAtk)
|
if (activeAtk)
|
||||||
{
|
{
|
||||||
|
float setH = 0;
|
||||||
|
float setW = 0;
|
||||||
signed damage = activeAtk->card->stepPower(step);
|
signed damage = activeAtk->card->stepPower(step);
|
||||||
for (vector<DefenserDamaged*>::iterator q = activeAtk->blockers.begin(); q != activeAtk->blockers.end(); ++q)
|
for (vector<DefenserDamaged*>::iterator q = activeAtk->blockers.begin(); q != activeAtk->blockers.end(); ++q)
|
||||||
{
|
{
|
||||||
(*q)->Render(step);
|
(*q)->Render(step);
|
||||||
damage -= (*q)->sumDamages();
|
damage -= (*q)->sumDamages();
|
||||||
|
setH = (*q)->Height;
|
||||||
|
setW = (*q)->Width;
|
||||||
}
|
}
|
||||||
if (damage < 0)
|
if (damage < 0)
|
||||||
damage = 0;
|
damage = 0;
|
||||||
if (activeAtk->card->has(Constants::TRAMPLE))
|
if (activeAtk->card->has(Constants::TRAMPLE))
|
||||||
{
|
{
|
||||||
observer->opponent()->getIcon()->SetHotSpot(18, 25);
|
if(activeAtk->card->isAttacking && activeAtk->card->isAttacking != observer->opponent())
|
||||||
enemy_avatar.Render(observer->opponent()->getIcon().get());
|
{
|
||||||
|
JQuadPtr enemy = WResourceManager::Instance()->RetrieveCard((MTGCardInstance*)activeAtk->card->isAttacking, CACHE_THUMB);
|
||||||
|
float oldH = enemy->mHeight;
|
||||||
|
float oldW = enemy->mWidth;
|
||||||
|
enemy->mHeight = setH;
|
||||||
|
enemy->mWidth = setW;
|
||||||
|
enemy->SetHotSpot(18, 25);
|
||||||
|
enemy_avatar.Render(enemy.get());
|
||||||
|
enemy->mHeight = oldH;
|
||||||
|
enemy->mWidth = oldW;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
observer->opponent()->getIcon()->SetHotSpot(18, 25);
|
||||||
|
enemy_avatar.Render(observer->opponent()->getIcon().get());
|
||||||
|
}
|
||||||
WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT);
|
WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT);
|
||||||
mFont->SetColor(ARGB(255, 255, 64, 0));
|
mFont->SetColor(ARGB(255, 255, 64, 0));
|
||||||
{
|
{
|
||||||
@@ -474,6 +493,7 @@ void GuiCombat::Render()
|
|||||||
sprintf(buf, "%i", damage);
|
sprintf(buf, "%i", damage);
|
||||||
mFont->DrawString(buf, enemy_avatar.actX - 25, enemy_avatar.actY - 40);
|
mFont->DrawString(buf, enemy_avatar.actX - 25, enemy_avatar.actY - 40);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ok_tex)
|
if (ok_tex)
|
||||||
@@ -506,7 +526,8 @@ int GuiCombat::resolve() // Returns the number of damage objects dealt this turn
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dmg > 0 && ((!attacker->isBlocked()) || attacker->has(Constants::TRAMPLE)))
|
if (dmg > 0 && ((!attacker->isBlocked()) || attacker->has(Constants::TRAMPLE)))
|
||||||
stack->Add(NEW Damage(observer, (*it)->card, observer->opponent(), dmg, DAMAGE_COMBAT));
|
stack->Add(NEW Damage(observer, (*it)->card, (Damageable*)attacker->isAttacking?(Damageable*)attacker->isAttacking:observer->opponent(), dmg, DAMAGE_COMBAT));
|
||||||
|
|
||||||
for (vector<Damage>::iterator d = (*it)->damages.begin(); d != (*it)->damages.end(); ++d)
|
for (vector<Damage>::iterator d = (*it)->damages.begin(); d != (*it)->damages.end(); ++d)
|
||||||
stack->Add(NEW Damage(*d));
|
stack->Add(NEW Damage(*d));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ void GuiPlay::Replace()
|
|||||||
for (iterator it = cards.begin(); it != end_spells; ++it)
|
for (iterator it = cards.begin(); it != end_spells; ++it)
|
||||||
if (!(*it)->card->target)
|
if (!(*it)->card->target)
|
||||||
{
|
{
|
||||||
if(!(*it)->card->hasSubtype(Subtypes::TYPE_AURA) && !(*it)->card->hasType(Subtypes::TYPE_PLANESWALKER))
|
if((!(*it)->card->hasSubtype(Subtypes::TYPE_AURA)|| ((*it)->card->hasSubtype(Subtypes::TYPE_AURA) && (*it)->card->playerTarget)) && !(*it)->card->hasType(Subtypes::TYPE_PLANESWALKER))
|
||||||
{
|
{
|
||||||
if (observer->players[0] == (*it)->card->controller())
|
if (observer->players[0] == (*it)->card->controller())
|
||||||
++selfSpellsN;
|
++selfSpellsN;
|
||||||
@@ -226,7 +226,7 @@ void GuiPlay::Replace()
|
|||||||
for (iterator it = cards.begin(); it != end_spells; ++it)
|
for (iterator it = cards.begin(); it != end_spells; ++it)
|
||||||
if (!(*it)->card->target)
|
if (!(*it)->card->target)
|
||||||
{
|
{
|
||||||
if(!(*it)->card->hasSubtype(Subtypes::TYPE_AURA) && !(*it)->card->hasType(Subtypes::TYPE_PLANESWALKER))
|
if((!(*it)->card->hasSubtype(Subtypes::TYPE_AURA)|| ((*it)->card->hasSubtype(Subtypes::TYPE_AURA) && (*it)->card->playerTarget)) && !(*it)->card->hasType(Subtypes::TYPE_PLANESWALKER))
|
||||||
{
|
{
|
||||||
if (observer->players[0] == (*it)->card->controller())
|
if (observer->players[0] == (*it)->card->controller())
|
||||||
selfSpells.Enstack(*it);
|
selfSpells.Enstack(*it);
|
||||||
|
|||||||
+358
-99
@@ -423,58 +423,59 @@ Counter * AbilityFactory::parseCounter(string s, MTGCardInstance * target, Spell
|
|||||||
int nb = 1;
|
int nb = 1;
|
||||||
int maxNb = 0;
|
int maxNb = 0;
|
||||||
string name = "";
|
string name = "";
|
||||||
size_t start = 0;
|
string nbstr = "1";
|
||||||
size_t end = s.length();
|
string maxNbstr = "0";
|
||||||
size_t separator = s.find(",", start);
|
string spt = "";
|
||||||
if (separator == string::npos)
|
|
||||||
separator = s.find(".", start);
|
vector<string>splitCounter = split(s,',');
|
||||||
if (separator != string::npos)
|
vector<string>splitCounterCheck = split(s,'.');
|
||||||
{
|
if(splitCounter.size() < splitCounterCheck.size())
|
||||||
size_t separator2 = s.find(",", separator + 1);
|
{
|
||||||
if (separator2 == string::npos)
|
splitCounter = splitCounterCheck;//use the one with the most results.
|
||||||
separator2 = s.find(".", separator + 1);
|
}
|
||||||
size_t separator3 = string::npos;
|
if(!splitCounter.size())
|
||||||
if (separator2 != string::npos)
|
{
|
||||||
{
|
return NULL;
|
||||||
name = s.substr(separator2 + 1, end - separator2 - 1);
|
}
|
||||||
separator3 = s.find(",", separator2 + 1);
|
if(splitCounter.size() > 0)//counter(1/1)
|
||||||
if (separator3 != string::npos)
|
{
|
||||||
{
|
spt = splitCounter[0];
|
||||||
name = s.substr(separator2 + 1,separator3 - separator2 - 1);
|
}
|
||||||
}
|
if(splitCounter.size() > 1)//counter(1/1,1)
|
||||||
}
|
{
|
||||||
string nbstr = s.substr(separator + 1, separator2 - separator - 1);
|
nbstr = splitCounter[1];
|
||||||
WParsedInt * wpi;
|
}
|
||||||
if (target)
|
if(splitCounter.size() > 2)//counter(0/0,1,charge)
|
||||||
{
|
{
|
||||||
wpi = NEW WParsedInt(nbstr, spell, target);
|
name = splitCounter[2];
|
||||||
}
|
}
|
||||||
else
|
if(splitCounter.size() > 3)//counter(0/0,1,charge,2)
|
||||||
{
|
{
|
||||||
wpi = NEW WParsedInt(atoi(nbstr.c_str()));
|
maxNbstr = splitCounter[3];
|
||||||
}
|
}
|
||||||
nb = wpi->getValue();
|
WParsedInt * wpi;
|
||||||
delete (wpi);
|
if (target)
|
||||||
string maxNbstr;
|
{
|
||||||
if (separator3 != string::npos)
|
wpi = NEW WParsedInt(nbstr, spell, target);
|
||||||
{
|
}
|
||||||
maxNbstr = s.substr(separator3 + 1, end - separator3 - 1);
|
else
|
||||||
WParsedInt * wpinb;
|
{
|
||||||
if (target)
|
wpi = NEW WParsedInt(atoi(nbstr.c_str()));
|
||||||
{
|
}
|
||||||
wpinb = NEW WParsedInt(maxNbstr, spell, target);
|
nb = wpi->getValue();
|
||||||
}
|
delete (wpi);
|
||||||
else
|
WParsedInt * wpinb;
|
||||||
{
|
if (target)
|
||||||
wpinb = NEW WParsedInt(atoi(maxNbstr.c_str()));
|
{
|
||||||
}
|
wpinb = NEW WParsedInt(maxNbstr, spell, target);
|
||||||
maxNb = wpinb->getValue();
|
}
|
||||||
delete(wpinb);
|
else
|
||||||
}
|
{
|
||||||
end = separator;
|
wpinb = NEW WParsedInt(atoi(maxNbstr.c_str()));
|
||||||
}
|
}
|
||||||
|
maxNb = wpinb->getValue();
|
||||||
|
delete(wpinb);
|
||||||
|
|
||||||
string spt = s.substr(start, end - start);
|
|
||||||
int power, toughness;
|
int power, toughness;
|
||||||
if (parsePowerToughness(spt, &power, &toughness))
|
if (parsePowerToughness(spt, &power, &toughness))
|
||||||
{
|
{
|
||||||
@@ -488,22 +489,19 @@ Counter * AbilityFactory::parseCounter(string s, MTGCardInstance * target, Spell
|
|||||||
|
|
||||||
int AbilityFactory::parsePowerToughness(string s, int *power, int *toughness)
|
int AbilityFactory::parsePowerToughness(string s, int *power, int *toughness)
|
||||||
{
|
{
|
||||||
size_t found = s.find("/");
|
vector<string>splitPT = split(s,'/');
|
||||||
if (found != string::npos)
|
vector<string>splitPTCheck = split(s,'%');
|
||||||
|
if(splitPT.size() < 2 && splitPT.size() < splitPTCheck.size())
|
||||||
{
|
{
|
||||||
size_t end = s.find(" ", found);
|
splitPT = splitPTCheck;
|
||||||
if (end == string::npos)
|
|
||||||
end = s.size();
|
|
||||||
size_t start = s.find_last_of(" ", found);
|
|
||||||
if (start == string::npos)
|
|
||||||
start = -1;
|
|
||||||
|
|
||||||
*power = atoi(s.substr(start + 1, s.size() - found).c_str());
|
|
||||||
*toughness = atoi(s.substr(found + 1, end - found - 1).c_str());
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
return 0;
|
if(!splitPT.size())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*power = atoi(splitPT[0].c_str());
|
||||||
|
*toughness = atoi(splitPT[1].c_str());
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
TargetChooser * AbilityFactory::parseSimpleTC(const std::string& s, const std::string& _starter, MTGCardInstance * card, bool forceNoTarget)
|
TargetChooser * AbilityFactory::parseSimpleTC(const std::string& s, const std::string& _starter, MTGCardInstance * card, bool forceNoTarget)
|
||||||
@@ -551,6 +549,7 @@ TriggeredAbility * AbilityFactory::parseTrigger(string s, string magicText, int
|
|||||||
bool opponentPoisoned = (s.find("opponentpoisoned") != string::npos);
|
bool opponentPoisoned = (s.find("opponentpoisoned") != string::npos);
|
||||||
bool lifelost = (s.find("foelost(") != string::npos);
|
bool lifelost = (s.find("foelost(") != string::npos);
|
||||||
int lifeamount = lifelost ? atoi(s.substr(s.find("foelost(") + 8,')').c_str()) : 0;
|
int lifeamount = lifelost ? atoi(s.substr(s.find("foelost(") + 8,')').c_str()) : 0;
|
||||||
|
bool neverRemove = (s.find("dontremove") != string::npos);
|
||||||
|
|
||||||
//Card Changed Zone
|
//Card Changed Zone
|
||||||
found = s.find("movedto(");
|
found = s.find("movedto(");
|
||||||
@@ -602,7 +601,13 @@ TriggeredAbility * AbilityFactory::parseTrigger(string s, string magicText, int
|
|||||||
fromTc = tcf.createTargetChooser(starget, card);
|
fromTc = tcf.createTargetChooser(starget, card);
|
||||||
fromTc->targetter = NULL; //avoid protection from
|
fromTc->targetter = NULL; //avoid protection from
|
||||||
}
|
}
|
||||||
return NEW TrCardAddedToZone(observer, id, card, (TargetZoneChooser *) toTc, toTcCard, (TargetZoneChooser *) fromTc, fromTcCard,once,sourceUntapped,isSuspended);
|
TriggeredAbility * mover = NEW TrCardAddedToZone(observer, id, card, (TargetZoneChooser *) toTc, toTcCard, (TargetZoneChooser *) fromTc, fromTcCard,once,sourceUntapped,isSuspended);
|
||||||
|
if(neverRemove)
|
||||||
|
{
|
||||||
|
mover->forcedAlive = 1;
|
||||||
|
mover->forceDestroy = -1;
|
||||||
|
}
|
||||||
|
return mover;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Card unTapped
|
//Card unTapped
|
||||||
@@ -922,6 +927,19 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
observer->addObserver(NEW MTGPlaneWalkerRule(observer, -1));
|
observer->addObserver(NEW MTGPlaneWalkerRule(observer, -1));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
found = s.find("planeswalkerdamage");
|
||||||
|
if(found != string::npos)
|
||||||
|
{
|
||||||
|
observer->addObserver(NEW MTGPlaneswalkerDamage(observer, -1));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
found = s.find("planeswalkerattack");
|
||||||
|
if(found != string::npos)
|
||||||
|
{
|
||||||
|
observer->addObserver(NEW MTGPlaneswalkerAttackRule(observer, -1));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
//this handles the clean up of tokens !!MUST BE ADDED BEFORE PERSIST RULE!!
|
//this handles the clean up of tokens !!MUST BE ADDED BEFORE PERSIST RULE!!
|
||||||
found = s.find("tokencleanuprule");
|
found = s.find("tokencleanuprule");
|
||||||
if(found != string::npos)
|
if(found != string::npos)
|
||||||
@@ -965,10 +983,21 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(strncmp(s.c_str(), "chooseacolor ", strlen("chooseacolor ")) == 0 || strncmp(s.c_str(), "chooseatype ", strlen("chooseatype ")) == 0)
|
||||||
|
{
|
||||||
|
MTGAbility * choose = parseChooseActionAbility(s,card,spell,target,0,id);
|
||||||
|
choose = NEW GenericActivatedAbility(observer, "","",id, card,choose,NULL);
|
||||||
|
MayAbility * mainAbility = NEW MayAbility(observer, id, choose, card,true);
|
||||||
|
return mainAbility;
|
||||||
|
}
|
||||||
|
|
||||||
//need to remove the section inside the transforms ability from the string before parsing
|
//need to remove the section inside the transforms ability from the string before parsing
|
||||||
//TODO: store string values of "&&" so we can remove the classes added just to add support
|
//TODO: store string values of "&&" so we can remove the classes added just to add support
|
||||||
//the current parser finds other abilities inside what should be nested abilities, and converts them into
|
//the current parser finds other abilities inside what should be nested abilities, and converts them into
|
||||||
//actual abilities, this is a limitation.
|
//actual abilities, this is a limitation.
|
||||||
|
string unchangedS = "";
|
||||||
|
unchangedS.append(s);
|
||||||
found = s.find("transforms((");
|
found = s.find("transforms((");
|
||||||
if (found != string::npos && storedString.empty())
|
if (found != string::npos && storedString.empty())
|
||||||
{
|
{
|
||||||
@@ -1040,7 +1069,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
|
|
||||||
TargetChooser * tc = NULL;
|
TargetChooser * tc = NULL;
|
||||||
string sWithoutTc = s;
|
string sWithoutTc = s;
|
||||||
|
string tcString = "";
|
||||||
//Target Abilities - We also handle the case "notatarget" here, for things such as copy effects
|
//Target Abilities - We also handle the case "notatarget" here, for things such as copy effects
|
||||||
bool isTarget = true;
|
bool isTarget = true;
|
||||||
vector<string> splitTarget = parseBetween(s, "notatarget(", ")");
|
vector<string> splitTarget = parseBetween(s, "notatarget(", ")");
|
||||||
@@ -1053,6 +1082,8 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
{
|
{
|
||||||
TargetChooserFactory tcf(observer);
|
TargetChooserFactory tcf(observer);
|
||||||
tc = tcf.createTargetChooser(splitTarget[1], card);
|
tc = tcf.createTargetChooser(splitTarget[1], card);
|
||||||
|
tcString = splitTarget[1];
|
||||||
|
|
||||||
if (!isTarget)
|
if (!isTarget)
|
||||||
tc->targetter = NULL;
|
tc->targetter = NULL;
|
||||||
sWithoutTc = splitTarget[0];
|
sWithoutTc = splitTarget[0];
|
||||||
@@ -1139,7 +1170,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
if (tc)
|
if (tc)
|
||||||
{
|
{
|
||||||
tc->belongsToAbility = sWithoutTc;
|
tc->belongsToAbility = sWithoutTc;
|
||||||
return NEW GenericTargetAbility(observer, newName,castRestriction,id, card, tc, a, cost, limit,sideEffect,usesBeforeSideEffect, restrictions, dest);
|
return NEW GenericTargetAbility(observer, newName,castRestriction,id, card, tc, a, cost, limit,sideEffect,usesBeforeSideEffect, restrictions, dest,tcString);
|
||||||
}
|
}
|
||||||
return NEW GenericActivatedAbility(observer, newName,castRestriction,id, card, a, cost, limit,sideEffect,usesBeforeSideEffect,restrictions, dest);
|
return NEW GenericActivatedAbility(observer, newName,castRestriction,id, card, a, cost, limit,sideEffect,usesBeforeSideEffect,restrictions, dest);
|
||||||
}
|
}
|
||||||
@@ -1171,10 +1202,20 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
if (sWithoutTc.find(ifKeywords[i]) == 0)
|
if (sWithoutTc.find(ifKeywords[i]) == 0)
|
||||||
{
|
{
|
||||||
string cond = sWithoutTc.substr(ifKeywords[i].length(),ifKeywords[i].length() + sWithoutTc.find(" then ")-6);
|
string cond = sWithoutTc.substr(ifKeywords[i].length(),ifKeywords[i].length() + sWithoutTc.find(" then ")-6);
|
||||||
string s1 = s.substr(s.find(" then ")+6);
|
size_t foundElse = s.find(" else ");
|
||||||
|
MTGAbility * a2 = NULL;
|
||||||
|
if(foundElse != string::npos)
|
||||||
|
{
|
||||||
|
string s2 = s.substr(foundElse+6);
|
||||||
|
if(s2.size())
|
||||||
|
s.erase(s.find(" else ")+1);
|
||||||
|
a2 = parseMagicLine(s2, id, spell, card);
|
||||||
|
}
|
||||||
|
string s1 = s.substr(foundElse+6);
|
||||||
MTGAbility * a1 = parseMagicLine(s1, id, spell, card);
|
MTGAbility * a1 = parseMagicLine(s1, id, spell, card);
|
||||||
|
|
||||||
if(!a1) return NULL;
|
if(!a1) return NULL;
|
||||||
MTGAbility * a = NEW IfThenAbility(observer, id, a1, card,(Targetable*)target,checkIf[i],cond);
|
MTGAbility * a = NEW IfThenAbility(observer, id, a1,a2, card,(Targetable*)target,checkIf[i],cond);
|
||||||
a->canBeInterrupted = false;
|
a->canBeInterrupted = false;
|
||||||
a->oneShot = true;
|
a->oneShot = true;
|
||||||
if(tc)
|
if(tc)
|
||||||
@@ -1218,7 +1259,6 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
return mainAbility;
|
return mainAbility;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic "Until end of turn" effect
|
// Generic "Until end of turn" effect
|
||||||
if (s.find("ueot ") == 0)
|
if (s.find("ueot ") == 0)
|
||||||
{
|
{
|
||||||
@@ -1230,6 +1270,31 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
return NEW GenericInstantAbility(observer, 1, card, (Damageable *) target, a1);
|
return NEW GenericInstantAbility(observer, 1, card, (Damageable *) target, a1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// neverending effect
|
||||||
|
if (s.find("emblem ") == 0)
|
||||||
|
{
|
||||||
|
string s1 = s.substr(7);
|
||||||
|
MTGAbility * a1 = parseMagicLine(s1, id, spell, card);
|
||||||
|
if (!a1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return NEW GenericAbilityMod(observer, 1, card,spell?spell->getNextDamageableTarget():(Damageable *) target, a1);;
|
||||||
|
}
|
||||||
|
|
||||||
|
//choose a color
|
||||||
|
vector<string> splitChooseAColor = parseBetween(s, "activatechooseacolor ", " activatechooseend");
|
||||||
|
if (splitChooseAColor.size())
|
||||||
|
{
|
||||||
|
return parseChooseActionAbility(unchangedS,card,spell,target,restrictions,id);
|
||||||
|
}
|
||||||
|
|
||||||
|
//choose a type
|
||||||
|
vector<string> splitChooseAType = parseBetween(s, "activatechooseatype ", " activatechooseend");
|
||||||
|
if (splitChooseAType.size())
|
||||||
|
{
|
||||||
|
return parseChooseActionAbility(unchangedS,card,spell,target,restrictions,id);
|
||||||
|
}
|
||||||
|
|
||||||
//Upkeep Cost
|
//Upkeep Cost
|
||||||
found = s.find("upcostmulti");
|
found = s.find("upcostmulti");
|
||||||
if (found != string::npos)
|
if (found != string::npos)
|
||||||
@@ -1249,7 +1314,10 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
found = s.find("forcedalive");
|
found = s.find("forcedalive");
|
||||||
if (found != string::npos)
|
if (found != string::npos)
|
||||||
forcedalive = 1;
|
forcedalive = 1;
|
||||||
|
bool neverRemove = false;
|
||||||
|
found = s.find("dontremove");
|
||||||
|
if (found != string::npos)
|
||||||
|
neverRemove = true;
|
||||||
//rather dirty way to stop thises and lords from conflicting with each other.
|
//rather dirty way to stop thises and lords from conflicting with each other.
|
||||||
size_t lord = string::npos;
|
size_t lord = string::npos;
|
||||||
for (size_t j = 0; j < kLordKeywordsCount; ++j)
|
for (size_t j = 0; j < kLordKeywordsCount; ++j)
|
||||||
@@ -1343,6 +1411,14 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
{
|
{
|
||||||
result->oneShot = oneShot;
|
result->oneShot = oneShot;
|
||||||
a->forcedAlive = forcedalive;
|
a->forcedAlive = forcedalive;
|
||||||
|
if(neverRemove)
|
||||||
|
{
|
||||||
|
result->forceDestroy = -1;
|
||||||
|
result->forcedAlive = 1;
|
||||||
|
a->forceDestroy = -1;
|
||||||
|
a->forcedAlive = 1;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -1495,6 +1571,14 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
{
|
{
|
||||||
result->oneShot = oneShot;
|
result->oneShot = oneShot;
|
||||||
a->forcedAlive = forcedalive;
|
a->forcedAlive = forcedalive;
|
||||||
|
if(neverRemove)
|
||||||
|
{
|
||||||
|
result->oneShot = false;
|
||||||
|
result->forceDestroy = -1;
|
||||||
|
result->forcedAlive = 1;
|
||||||
|
a->forceDestroy = -1;
|
||||||
|
a->forcedAlive = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -1585,6 +1669,18 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
{
|
{
|
||||||
return parsePhaseActionAbility(s,card,spell,target,restrictions,id);
|
return parsePhaseActionAbility(s,card,spell,target,restrictions,id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//flip a coin
|
||||||
|
vector<string> splitFlipCoin = parseBetween(s, "flipacoin ", " flipend");
|
||||||
|
if (splitFlipCoin.size())
|
||||||
|
{
|
||||||
|
string a1 = splitFlipCoin[1];
|
||||||
|
MTGAbility * a = NEW GenericFlipACoin(observer, id, card, target,a1);
|
||||||
|
a->oneShot = 1;
|
||||||
|
a->canBeInterrupted = false;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
//Upkeep Cost
|
//Upkeep Cost
|
||||||
found = s.find("upcost");
|
found = s.find("upcost");
|
||||||
if (found != string::npos)
|
if (found != string::npos)
|
||||||
@@ -1769,6 +1865,15 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//put a card on bottom of library
|
||||||
|
found = s.find("bottomoflibrary");
|
||||||
|
if (found != string::npos)
|
||||||
|
{
|
||||||
|
MTGAbility * a = NEW AALibraryBottom(observer, id, card, target);
|
||||||
|
a->oneShot = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
//Copy a target
|
//Copy a target
|
||||||
found = s.find("copy");
|
found = s.find("copy");
|
||||||
if (found != string::npos)
|
if (found != string::npos)
|
||||||
@@ -1813,6 +1918,14 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
{
|
{
|
||||||
MTGAbility *a = NEW AABuryCard(observer, id, card, target);
|
MTGAbility *a = NEW AABuryCard(observer, id, card, target);
|
||||||
a->oneShot = 1;
|
a->oneShot = 1;
|
||||||
|
if(s.find("and(") != string::npos)
|
||||||
|
{
|
||||||
|
vector<string> splitAnd = parseBetween(s, "and((", " ))",false);
|
||||||
|
if(splitAnd.size())
|
||||||
|
{
|
||||||
|
((AABuryCard*)a)->andAbility = parseMagicLine(splitAnd[1], id, spell, card);
|
||||||
|
}
|
||||||
|
}
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1820,6 +1933,14 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
{
|
{
|
||||||
MTGAbility * a = NEW AADestroyCard(observer, id, card, target);
|
MTGAbility * a = NEW AADestroyCard(observer, id, card, target);
|
||||||
a->oneShot = 1;
|
a->oneShot = 1;
|
||||||
|
if(s.find("and(") != string::npos)
|
||||||
|
{
|
||||||
|
vector<string> splitAnd = parseBetween(s, "and((", " ))",false);
|
||||||
|
if(splitAnd.size())
|
||||||
|
{
|
||||||
|
((AADestroyCard*)a)->andAbility = parseMagicLine(splitAnd[1], id, spell, card);
|
||||||
|
}
|
||||||
|
}
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1827,6 +1948,14 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
{
|
{
|
||||||
MTGAbility *a = NEW AASacrificeCard(observer, id, card, target);
|
MTGAbility *a = NEW AASacrificeCard(observer, id, card, target);
|
||||||
a->oneShot = 1;
|
a->oneShot = 1;
|
||||||
|
if(s.find("and(") != string::npos)
|
||||||
|
{
|
||||||
|
vector<string> splitAnd = parseBetween(s, "and((", " ))",false);
|
||||||
|
if(splitAnd.size())
|
||||||
|
{
|
||||||
|
((AASacrificeCard*)a)->andAbility = parseMagicLine(splitAnd[1], id, spell, card);
|
||||||
|
}
|
||||||
|
}
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1834,6 +1963,14 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
{
|
{
|
||||||
MTGAbility *a = NEW AADiscardCard(observer, id, card, target);
|
MTGAbility *a = NEW AADiscardCard(observer, id, card, target);
|
||||||
a->oneShot = 1;
|
a->oneShot = 1;
|
||||||
|
if(s.find("and(") != string::npos)
|
||||||
|
{
|
||||||
|
vector<string> splitAnd = parseBetween(s, "and((", " ))",false);
|
||||||
|
if(splitAnd.size())
|
||||||
|
{
|
||||||
|
((AADiscardCard*)a)->andAbility = parseMagicLine(splitAnd[1], id, spell, card);
|
||||||
|
}
|
||||||
|
}
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
bool oneShot = false;
|
bool oneShot = false;
|
||||||
@@ -1984,6 +2121,16 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//modify turns
|
||||||
|
vector<string> splitModTurn = parseBetween(s, "turns:", " ", false);
|
||||||
|
if (splitModTurn.size())
|
||||||
|
{
|
||||||
|
Targetable * t = spell ? spell->getNextTarget() : NULL;
|
||||||
|
MTGAbility * a = NEW AAModTurn(observer, id, card, t , splitModTurn[1], NULL, who);
|
||||||
|
a->oneShot = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
//Shuffle
|
//Shuffle
|
||||||
found = s.find("shuffle");
|
found = s.find("shuffle");
|
||||||
if (found != string::npos)
|
if (found != string::npos)
|
||||||
@@ -2094,6 +2241,24 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
return NULL;
|
return NULL;
|
||||||
return NEW ABushidoAbility(observer, id, card,splitBushido[1]);
|
return NEW ABushidoAbility(observer, id, card,splitBushido[1]);
|
||||||
}
|
}
|
||||||
|
vector<string> splitPhaseAlter = parseBetween(s, "phasealter(", ")");
|
||||||
|
if (splitPhaseAlter.size())
|
||||||
|
{
|
||||||
|
string power, toughness;
|
||||||
|
vector<string>splitPhaseAlter2 = split(splitPhaseAlter[1],',');
|
||||||
|
if(splitPhaseAlter2.size() < 3)
|
||||||
|
return NULL;
|
||||||
|
string after = "";
|
||||||
|
if(splitPhaseAlter2.size() > 3)
|
||||||
|
{
|
||||||
|
vector<string> splitPhaseAlterAfter = parseBetween(splitPhaseAlter2[3], "after<", ">");
|
||||||
|
if(splitPhaseAlterAfter.size())
|
||||||
|
after = splitPhaseAlterAfter[1];
|
||||||
|
}
|
||||||
|
MTGAbility * a1 = NEW APhaseAlter(observer, id, card, target,splitPhaseAlter2[0].find("add") != string::npos, splitPhaseAlter2[1],splitPhaseAlter2[2], s.find("nextphase") != string::npos,after);
|
||||||
|
a1->canBeInterrupted = false;
|
||||||
|
return NEW GenericAbilityMod(observer, 1, card,spell?spell->getNextDamageableTarget():(Damageable *) target, a1);
|
||||||
|
}
|
||||||
|
|
||||||
//loseAbilities
|
//loseAbilities
|
||||||
if (s.find("loseabilities") != string::npos)
|
if (s.find("loseabilities") != string::npos)
|
||||||
@@ -2184,17 +2349,21 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
string newPower = "";
|
string newPower = "";
|
||||||
string newToughness = "";
|
string newToughness = "";
|
||||||
bool ptFound = false;
|
bool ptFound = false;
|
||||||
if(becomesParameters.size() >1)
|
if(becomesParameters.size() >1)
|
||||||
{
|
{
|
||||||
vector<string> pt = split(becomesParameters[1], '/');
|
vector<string> pt = split(becomesParameters[1], '/');
|
||||||
newPower = pt[0];
|
if(pt.size() > 1)
|
||||||
newToughness = pt[1];
|
{
|
||||||
ptFound = true;
|
newPower = pt[0];
|
||||||
}
|
newToughness = pt[1];
|
||||||
|
ptFound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
string sabilities = "";
|
string sabilities = "";
|
||||||
if(becomesParameters.size() > 2)
|
unsigned int becomesSize = ptFound?2:1;
|
||||||
|
if(becomesParameters.size() > becomesSize)
|
||||||
{
|
{
|
||||||
for(unsigned int i = 2;i < becomesParameters.size();i++)
|
for(unsigned int i = becomesSize;i < becomesParameters.size();i++)
|
||||||
{
|
{
|
||||||
sabilities.append(becomesParameters[i].c_str());
|
sabilities.append(becomesParameters[i].c_str());
|
||||||
if(i+1 < becomesParameters.size())
|
if(i+1 < becomesParameters.size())
|
||||||
@@ -2339,7 +2508,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
found = s.find("add");
|
found = s.find("add");
|
||||||
if (found != string::npos)
|
if (found != string::npos)
|
||||||
{
|
{
|
||||||
ManaCost * output = ManaCost::parseManaCost(s.substr(found));
|
ManaCost * output = ManaCost::parseManaCost(s.substr(found),NULL,card);
|
||||||
Targetable * t = spell ? spell->getNextTarget() : NULL;
|
Targetable * t = spell ? spell->getNextTarget() : NULL;
|
||||||
MTGAbility * a = NEW AManaProducer(observer, id, card, t, output, NULL, who);
|
MTGAbility * a = NEW AManaProducer(observer, id, card, t, output, NULL, who);
|
||||||
a->oneShot = 1;
|
a->oneShot = 1;
|
||||||
@@ -2476,6 +2645,15 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
a->oneShot = 1;
|
a->oneShot = 1;
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
//exchange life with target; if creature then toughness is life.
|
||||||
|
found = s.find("exchangelife");
|
||||||
|
if (found != string::npos)
|
||||||
|
{
|
||||||
|
Targetable * t = spell ? spell->getNextTarget() : NULL;
|
||||||
|
MTGAbility * a = NEW AAExchangeLife(observer, id, card, t, NULL, who);
|
||||||
|
a->oneShot = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
//Regeneration
|
//Regeneration
|
||||||
found = s.find("regenerate");
|
found = s.find("regenerate");
|
||||||
@@ -2645,6 +2823,50 @@ MTGAbility * AbilityFactory::parsePhaseActionAbility(string s,MTGCardInstance *
|
|||||||
return NEW APhaseActionGeneric(observer, id, card,_target, trim(splitActions[2]), restrictions, phase,sourceinPlay,next,myturn,opponentturn,once);
|
return NEW APhaseActionGeneric(observer, id, card,_target, trim(splitActions[2]), restrictions, phase,sourceinPlay,next,myturn,opponentturn,once);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MTGAbility * AbilityFactory::parseChooseActionAbility(string s,MTGCardInstance * card,Spell * spell,MTGCardInstance * target, int restrictions,int id)
|
||||||
|
{
|
||||||
|
vector<string> splitChooseAColor2 = parseBetween(s, "activatechooseacolor ", " activatechooseend");
|
||||||
|
if (splitChooseAColor2.size())
|
||||||
|
{
|
||||||
|
string a1 = splitChooseAColor2[1];
|
||||||
|
MTGAbility * a = NEW GenericChooseTypeColor(observer, id, card, target,a1,true);
|
||||||
|
a->oneShot = 1;
|
||||||
|
a->canBeInterrupted = false;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
//choose a type
|
||||||
|
vector<string> splitChooseAType2 = parseBetween(s, "activatechooseatype ", " activatechooseend");
|
||||||
|
if (splitChooseAType2.size())
|
||||||
|
{
|
||||||
|
string a1 = splitChooseAType2[1];
|
||||||
|
MTGAbility * a = NEW GenericChooseTypeColor(observer, id, card, target,a1,false,s.find("nonwall")!=string::npos);
|
||||||
|
a->oneShot = 1;
|
||||||
|
a->canBeInterrupted = false;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
//choose a color
|
||||||
|
vector<string> splitChooseAColor = parseBetween(s, "chooseacolor ", " chooseend");
|
||||||
|
if (splitChooseAColor.size())
|
||||||
|
{
|
||||||
|
string a1 = splitChooseAColor[1];
|
||||||
|
MTGAbility * a = NEW GenericChooseTypeColor(observer, id, card, target,a1,true);
|
||||||
|
a->oneShot = 1;
|
||||||
|
a->canBeInterrupted = false;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
//choose a type
|
||||||
|
vector<string> splitChooseAType = parseBetween(s, "chooseatype ", " chooseend");
|
||||||
|
if (splitChooseAType.size())
|
||||||
|
{
|
||||||
|
string a1 = splitChooseAType[1];
|
||||||
|
MTGAbility * a = NEW GenericChooseTypeColor(observer, id, card, target,a1,false,s.find("nonwall")!=string::npos);
|
||||||
|
a->oneShot = 1;
|
||||||
|
a->canBeInterrupted = false;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
//Tells the AI if the ability should target itself or an ennemy
|
//Tells the AI if the ability should target itself or an ennemy
|
||||||
int AbilityFactory::abilityEfficiency(MTGAbility * a, Player * p, int mode, TargetChooser * tc,Targetable * target)
|
int AbilityFactory::abilityEfficiency(MTGAbility * a, Player * p, int mode, TargetChooser * tc,Targetable * target)
|
||||||
{
|
{
|
||||||
@@ -3024,11 +3246,14 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card, int
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
a->addToGame();
|
a->addToGame();
|
||||||
|
MayAbility * dontAdd = dynamic_cast<MayAbility*>(a);
|
||||||
|
if(!dontAdd)
|
||||||
|
{
|
||||||
if (a->source)
|
if (a->source)
|
||||||
a->source->cardsAbilities.push_back(a);
|
a->source->cardsAbilities.push_back(a);
|
||||||
else if(spell && spell->source)
|
else if(spell && spell->source)
|
||||||
spell->source->cardsAbilities.push_back(a);
|
spell->source->cardsAbilities.push_back(a);
|
||||||
|
}
|
||||||
//keep track of abilities being added to the game on each card it belongs to, this ignores p/t bonuses given
|
//keep track of abilities being added to the game on each card it belongs to, this ignores p/t bonuses given
|
||||||
//from other cards, or ability bonuses, making it generally easier to strip a card of it's abilities.
|
//from other cards, or ability bonuses, making it generally easier to strip a card of it's abilities.
|
||||||
}
|
}
|
||||||
@@ -3051,6 +3276,7 @@ void AbilityFactory::addAbilities(int _id, Spell * spell)
|
|||||||
zones->putInZone(card, spell->from, card->owner->game->graveyard);
|
zones->putInZone(card, spell->from, card->owner->game->graveyard);
|
||||||
return; //fizzle
|
return; //fizzle
|
||||||
}
|
}
|
||||||
|
card->playerTarget = spell->getNextPlayerTarget();
|
||||||
}
|
}
|
||||||
_id = magicText(_id, spell);
|
_id = magicText(_id, spell);
|
||||||
|
|
||||||
@@ -3818,7 +4044,6 @@ int ActivatedAbility::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
|
|||||||
{
|
{
|
||||||
if(card->isPhased)
|
if(card->isPhased)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
Player * player = game->currentlyActing();
|
Player * player = game->currentlyActing();
|
||||||
int cPhase = game->getCurrentGamePhase();
|
int cPhase = game->getCurrentGamePhase();
|
||||||
switch (restrictions)
|
switch (restrictions)
|
||||||
@@ -3886,7 +4111,44 @@ int ActivatedAbility::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
|
|||||||
ManaCost * cost = getCost();
|
ManaCost * cost = getCost();
|
||||||
if (!cost)
|
if (!cost)
|
||||||
return 1;
|
return 1;
|
||||||
|
if(card->hasType(Subtypes::TYPE_PLANESWALKER))
|
||||||
|
{
|
||||||
|
for(unsigned int k = 0;k < card->cardsAbilities.size();++k)
|
||||||
|
{
|
||||||
|
ActivatedAbility * check = dynamic_cast<ActivatedAbility*>(card->cardsAbilities[k]);
|
||||||
|
if(check && check->counters)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (player != game->currentPlayer)
|
||||||
|
return 0;
|
||||||
|
if (cPhase != MTG_PHASE_FIRSTMAIN && cPhase != MTG_PHASE_SECONDMAIN)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (source->has(Constants::NOACTIVATED))
|
||||||
|
return 0;
|
||||||
|
AbilityFactory af(game);
|
||||||
|
MTGAbility * fmp = NULL;
|
||||||
|
fmp = af.getCoreAbility(this);
|
||||||
|
AManaProducer * amp = dynamic_cast<AManaProducer *> (this);
|
||||||
|
AManaProducer * femp = dynamic_cast<AManaProducer *> (fmp);
|
||||||
|
if (source->has(Constants::NOMANA) && (amp||femp))
|
||||||
|
return 0;
|
||||||
|
if(source->has(Constants::ONLYMANA) && !(amp||femp))
|
||||||
|
return 0;
|
||||||
cost->setExtraCostsAction(this, card);
|
cost->setExtraCostsAction(this, card);
|
||||||
|
if (source->has(Constants::NOACTIVATEDTAP) && cost->extraCosts)
|
||||||
|
{
|
||||||
|
for(unsigned int i = 0;i < cost->extraCosts->costs.size();++i)
|
||||||
|
{
|
||||||
|
ExtraCost * eCost = cost->getExtraCost(i);
|
||||||
|
if(dynamic_cast<TapCost *>(eCost))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (!mana)
|
if (!mana)
|
||||||
mana = player->getManaPool();
|
mana = player->getManaPool();
|
||||||
if (!mana->canAfford(cost))
|
if (!mana->canAfford(cost))
|
||||||
@@ -4126,9 +4388,9 @@ int TargetAbility::resolve()
|
|||||||
Targetable * t = tc->getNextTarget();
|
Targetable * t = tc->getNextTarget();
|
||||||
if (t && ability)
|
if (t && ability)
|
||||||
{
|
{
|
||||||
source->X = 0;
|
|
||||||
if (abilityCost)
|
if (abilityCost)
|
||||||
{
|
{
|
||||||
|
source->X = 0;
|
||||||
ManaCost * diff = abilityCost->Diff(getCost());
|
ManaCost * diff = abilityCost->Diff(getCost());
|
||||||
source->X = diff->hasX();
|
source->X = diff->hasX();
|
||||||
delete (diff);
|
delete (diff);
|
||||||
@@ -4275,20 +4537,19 @@ void InstantAbility::Update(float dt)
|
|||||||
|
|
||||||
InstantAbility::InstantAbility(GameObserver* observer, int _id, MTGCardInstance * source, Targetable * _target) :
|
InstantAbility::InstantAbility(GameObserver* observer, int _id, MTGCardInstance * source, Targetable * _target) :
|
||||||
MTGAbility(observer, _id, source, _target)
|
MTGAbility(observer, _id, source, _target)
|
||||||
{
|
{
|
||||||
init = 0;
|
init = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Instant abilities last generally until the end of the turn
|
//Instant abilities last generally until the end of the turn
|
||||||
int InstantAbility::testDestroy()
|
int InstantAbility::testDestroy()
|
||||||
{
|
{
|
||||||
GamePhase newPhase = game->getCurrentGamePhase();
|
GamePhase newPhase = game->getCurrentGamePhase();
|
||||||
if (newPhase != currentPhase && newPhase == MTG_PHASE_AFTER_EOT)
|
if (newPhase != currentPhase && newPhase == MTG_PHASE_AFTER_EOT)
|
||||||
return 1;
|
return 1;
|
||||||
currentPhase = newPhase;
|
currentPhase = newPhase;
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ostream& InstantAbility::toString(ostream& out) const
|
ostream& InstantAbility::toString(ostream& out) const
|
||||||
{
|
{
|
||||||
@@ -4328,9 +4589,7 @@ void ListMaintainerAbility::updateTargets()
|
|||||||
cards.erase(card);
|
cards.erase(card);
|
||||||
removed(card);
|
removed(card);
|
||||||
}
|
}
|
||||||
|
|
||||||
temp.clear();
|
temp.clear();
|
||||||
|
|
||||||
//add New valid ones
|
//add New valid ones
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -168,7 +168,6 @@ void MTGCardInstance::initMTGCI()
|
|||||||
flanked = 0;
|
flanked = 0;
|
||||||
target = NULL;
|
target = NULL;
|
||||||
playerTarget = NULL;
|
playerTarget = NULL;
|
||||||
playerTarget = NULL;
|
|
||||||
type_as_damageable = DAMAGEABLE_MTGCARDINSTANCE;
|
type_as_damageable = DAMAGEABLE_MTGCARDINSTANCE;
|
||||||
banding = NULL;
|
banding = NULL;
|
||||||
owner = NULL;
|
owner = NULL;
|
||||||
|
|||||||
@@ -123,7 +123,11 @@ const char* Constants::MTGBasicAbilities[] = {
|
|||||||
"canattack",
|
"canattack",
|
||||||
"hydra",
|
"hydra",
|
||||||
"undying",
|
"undying",
|
||||||
"poisonshroud"
|
"poisonshroud",
|
||||||
|
"noactivatedability",
|
||||||
|
"notapability",
|
||||||
|
"nomanaability",
|
||||||
|
"onlymanaability"
|
||||||
};
|
};
|
||||||
|
|
||||||
map<string,int> Constants::MTGBasicAbilitiesMap;
|
map<string,int> Constants::MTGBasicAbilitiesMap;
|
||||||
|
|||||||
@@ -1190,7 +1190,7 @@ 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::MUSTATTACK))
|
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())
|
||||||
reactToClick(card);
|
reactToClick(card);
|
||||||
@@ -1232,6 +1232,121 @@ MTGAttackRule * MTGAttackRule::clone() const
|
|||||||
{
|
{
|
||||||
return NEW MTGAttackRule(*this);
|
return NEW MTGAttackRule(*this);
|
||||||
}
|
}
|
||||||
|
//handling for planeswalker attacking choice
|
||||||
|
MTGPlaneswalkerAttackRule::MTGPlaneswalkerAttackRule(GameObserver* observer, int _id) :
|
||||||
|
PermanentAbility(observer, _id)
|
||||||
|
{
|
||||||
|
aType = MTGAbility::MTG_ATTACK_RULE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MTGPlaneswalkerAttackRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
|
||||||
|
{
|
||||||
|
if (currentPhase == MTG_PHASE_COMBATATTACKERS && card->controller() == game->currentPlayer && card->controller() == game->currentlyActing())//on my turn and when I am the acting player.
|
||||||
|
{
|
||||||
|
if(!card->controller()->opponent()->game->inPlay->hasType("planeswalker"))
|
||||||
|
return 0;
|
||||||
|
if(card->isPhased)
|
||||||
|
return 0;
|
||||||
|
if (card->isAttacker())
|
||||||
|
return 1;
|
||||||
|
if (card->canAttack())
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MTGPlaneswalkerAttackRule::reactToClick(MTGCardInstance * card)
|
||||||
|
{
|
||||||
|
if (!isReactingToClick(card))
|
||||||
|
return 0;
|
||||||
|
//Graphically select the next card that can attack
|
||||||
|
if (!card->isAttacker())
|
||||||
|
{
|
||||||
|
game->getCardSelector()->PushLimitor();
|
||||||
|
game->getCardSelector()->Limit(this, CardView::playZone);
|
||||||
|
game->getCardSelector()->CheckUserInput(JGE_BTN_RIGHT);
|
||||||
|
game->getCardSelector()->Limit(NULL, CardView::playZone);
|
||||||
|
game->getCardSelector()->PopLimitor();
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<MTGAbility*>selection;
|
||||||
|
MTGCardInstance * check = NULL;
|
||||||
|
int checkWalkers = card->controller()->opponent()->game->battlefield->cards.size();
|
||||||
|
for(int i = 0; i < checkWalkers;++i)
|
||||||
|
{
|
||||||
|
check = card->controller()->opponent()->game->battlefield->cards[i];
|
||||||
|
if(check->hasType(Subtypes::TYPE_PLANESWALKER))
|
||||||
|
{
|
||||||
|
MTGAbility * setPw = NEW AAPlaneswalkerAttacked(game, game->mLayers->actionLayer()->getMaxId(), card,check);
|
||||||
|
MTGAbility * setWalker = setPw->clone();
|
||||||
|
setWalker->oneShot = true;
|
||||||
|
selection.push_back(setWalker);
|
||||||
|
SAFE_DELETE(setPw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(selection.size())
|
||||||
|
{
|
||||||
|
MTGAbility * a1 = NEW MenuAbility(game, this->GetId(), card, card,false,selection);
|
||||||
|
game->mLayers->actionLayer()->currentActionCard = card;
|
||||||
|
a1->resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
MTGPlaneswalkerAttackRule * MTGPlaneswalkerAttackRule::clone() const
|
||||||
|
{
|
||||||
|
return NEW MTGPlaneswalkerAttackRule(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MTGPlaneswalkerAttackRule::select(Target* t)
|
||||||
|
{
|
||||||
|
if (CardView* c = dynamic_cast<CardView*>(t))
|
||||||
|
{
|
||||||
|
MTGCardInstance * card = c->getCard();
|
||||||
|
if (card->canAttack() && !card->isPhased)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool MTGPlaneswalkerAttackRule::greyout(Target* t)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//setting combat against planeswalker menu handling
|
||||||
|
AAPlaneswalkerAttacked::AAPlaneswalkerAttacked(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target):
|
||||||
|
InstantAbility(observer, id, source)
|
||||||
|
{
|
||||||
|
this->target = _target;
|
||||||
|
menuText = _target->name.c_str();
|
||||||
|
attacker = card;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AAPlaneswalkerAttacked::resolve()
|
||||||
|
{
|
||||||
|
if(!attacker)
|
||||||
|
return 0;
|
||||||
|
attacker->isAttacking = this->target;
|
||||||
|
attacker->toggleAttacker();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* AAPlaneswalkerAttacked::getMenuText()
|
||||||
|
{
|
||||||
|
return menuText.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
AAPlaneswalkerAttacked * AAPlaneswalkerAttacked::clone() const
|
||||||
|
{
|
||||||
|
return NEW AAPlaneswalkerAttacked(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
AAPlaneswalkerAttacked::~AAPlaneswalkerAttacked()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
//this rules handles returning cards to combat triggers for activations.
|
//this rules handles returning cards to combat triggers for activations.
|
||||||
MTGCombatTriggersRule::MTGCombatTriggersRule(GameObserver* observer, int _id) :
|
MTGCombatTriggersRule::MTGCombatTriggersRule(GameObserver* observer, int _id) :
|
||||||
@@ -2159,6 +2274,49 @@ MTGPlaneWalkerRule * MTGPlaneWalkerRule::clone() const
|
|||||||
{
|
{
|
||||||
return NEW MTGPlaneWalkerRule(*this);
|
return NEW MTGPlaneWalkerRule(*this);
|
||||||
}
|
}
|
||||||
|
/* planeswalker damage rule */
|
||||||
|
MTGPlaneswalkerDamage::MTGPlaneswalkerDamage(GameObserver* observer, int _id) :
|
||||||
|
PermanentAbility(observer, _id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
int MTGPlaneswalkerDamage::receiveEvent(WEvent * event)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (event->type == WEvent::DAMAGE)
|
||||||
|
{
|
||||||
|
WEventDamage * e = (WEventDamage *) event;
|
||||||
|
Damage * d = e->damage;
|
||||||
|
MTGCardInstance * card = dynamic_cast<MTGCardInstance*>(e->getTarget(WEvent::TARGET_TO));
|
||||||
|
if (d->damage > 0 && card && card->hasType(Subtypes::TYPE_PLANESWALKER))
|
||||||
|
{
|
||||||
|
int howMany = d->damage;
|
||||||
|
for(int k = 0;k < howMany;k++)
|
||||||
|
{
|
||||||
|
card->counters->removeCounter("loyalty",0,0);
|
||||||
|
}
|
||||||
|
d->damage = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (WEventCounters * removel = dynamic_cast<WEventCounters*>(event))
|
||||||
|
{
|
||||||
|
if(removel->removed && removel->targetCard && removel->targetCard->hasType(Subtypes::TYPE_PLANESWALKER))
|
||||||
|
if(!removel->targetCard->counters->hasCounter("loyalty",0,0))
|
||||||
|
{
|
||||||
|
removel->targetCard->bury();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MTGPlaneswalkerDamage * MTGPlaneswalkerDamage::clone() const
|
||||||
|
{
|
||||||
|
return NEW MTGPlaneswalkerDamage(*this);
|
||||||
|
}
|
||||||
|
|
||||||
/* Lifelink */
|
/* Lifelink */
|
||||||
MTGLifelinkRule::MTGLifelinkRule(GameObserver* observer, int _id) :
|
MTGLifelinkRule::MTGLifelinkRule(GameObserver* observer, int _id) :
|
||||||
|
|||||||
@@ -165,7 +165,11 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstan
|
|||||||
}
|
}
|
||||||
case 'c': //Counters or cycle
|
case 'c': //Counters or cycle
|
||||||
{
|
{
|
||||||
if(value == "cycle")
|
if(value == "chosencolor")
|
||||||
|
{
|
||||||
|
manaCost->add(c->chooseacolor, 1);
|
||||||
|
}
|
||||||
|
else if(value == "cycle")
|
||||||
{
|
{
|
||||||
manaCost->addExtraCost(NEW CycleCost(tc));
|
manaCost->addExtraCost(NEW CycleCost(tc));
|
||||||
}
|
}
|
||||||
@@ -631,6 +635,11 @@ int ManaCost::addExtraCost(ExtraCost * _cost)
|
|||||||
|
|
||||||
int ManaCost::addExtraCosts(ExtraCosts *_ecost)
|
int ManaCost::addExtraCosts(ExtraCosts *_ecost)
|
||||||
{
|
{
|
||||||
|
if(!_ecost)
|
||||||
|
{
|
||||||
|
extraCosts = NULL;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
if (!extraCosts)
|
if (!extraCosts)
|
||||||
extraCosts = NEW ExtraCosts();
|
extraCosts = NEW ExtraCosts();
|
||||||
for(size_t i = 0; i < _ecost->costs.size(); i++)
|
for(size_t i = 0; i < _ecost->costs.size(); i++)
|
||||||
|
|||||||
@@ -140,6 +140,7 @@ void RulesState::parsePlayerState(int playerId, string s)
|
|||||||
void Rules::addExtraRules(GameObserver* g)
|
void Rules::addExtraRules(GameObserver* g)
|
||||||
{
|
{
|
||||||
int id = g->mLayers->actionLayer()->getMaxId();
|
int id = g->mLayers->actionLayer()->getMaxId();
|
||||||
|
MTGAllCards::sortSubtypeList();
|
||||||
for (int i = 0; i < 2; ++i)
|
for (int i = 0; i < 2; ++i)
|
||||||
{
|
{
|
||||||
Player * p = g->players[i];
|
Player * p = g->players[i];
|
||||||
|
|||||||
@@ -574,6 +574,29 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
|
|||||||
cd->setColor(cid);
|
cd->setColor(cid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (attribute.find("chosencolor") != string::npos)
|
||||||
|
{
|
||||||
|
attributefound = 1;
|
||||||
|
if (minus)
|
||||||
|
cd->SetExclusionColor(card->chooseacolor);
|
||||||
|
else
|
||||||
|
cd->setColor(card->chooseacolor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute.find("chosentype") != string::npos)
|
||||||
|
{
|
||||||
|
attributefound = 1;
|
||||||
|
if (minus)
|
||||||
|
{
|
||||||
|
cd->setNegativeSubtype(card->chooseasubtype);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cd->setSubtype(card->chooseasubtype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!attributefound)
|
if (!attributefound)
|
||||||
{
|
{
|
||||||
//Abilities
|
//Abilities
|
||||||
|
|||||||
Reference in New Issue
Block a user