added basic card draw replacement,
auto=replacedraw choice damage:2
auto=replacedraw choice draw:2 noreplace
notice noreplace exempts the draw from sending a draw event. draw events and drawn events are seperate events.
added dredge and it's rules.
[card]
name=Dakmor Salvage
auto=tap
auto={t}:add{b}
dredge=dredge(2)
text=Dakmor Salvage enters the battlefield tapped. -- {T}: Add {B} to your mana pool. -- Dredge 2 (If you would draw a card, instead you may put exactly two cards from the top of your library into your graveyard. If you do, return this card from your graveyard to your hand. Otherwise, draw a card.)
type=Land
[/card]
This commit is contained in:
@@ -44,7 +44,7 @@ public:
|
|||||||
int reactToTargetClick(ActionElement * ability, Targetable * card);
|
int reactToTargetClick(ActionElement * ability, Targetable * card);
|
||||||
int stillInUse(MTGCardInstance * card);
|
int stillInUse(MTGCardInstance * card);
|
||||||
void setMenuObject(Targetable * object, bool must = false);
|
void setMenuObject(Targetable * object, bool must = false);
|
||||||
void setCustomMenuObject(Targetable * object, bool must = false,vector<MTGAbility*>abilities = vector<MTGAbility*>());
|
void setCustomMenuObject(Targetable * object, bool must = false,vector<MTGAbility*>abilities = vector<MTGAbility*>(),string customName = "");
|
||||||
void ButtonPressed(int controllerid, int controlid);
|
void ButtonPressed(int controllerid, int controlid);
|
||||||
void ButtonPressedOnMultipleChoice(int choice = -1);
|
void ButtonPressedOnMultipleChoice(int choice = -1);
|
||||||
void doReactTo(int menuIndex);
|
void doReactTo(int menuIndex);
|
||||||
|
|||||||
@@ -1105,7 +1105,8 @@ public:
|
|||||||
MTGAbility * mClone;
|
MTGAbility * mClone;
|
||||||
vector<MTGAbility*>abilities;
|
vector<MTGAbility*>abilities;
|
||||||
Player * who;
|
Player * who;
|
||||||
MenuAbility(GameObserver* observer, int _id, Targetable * target, MTGCardInstance * _source, bool must = false, vector<MTGAbility*>abilities = vector<MTGAbility*>(),Player * who = NULL);
|
string newNameString;
|
||||||
|
MenuAbility(GameObserver* observer, int _id, Targetable * target, MTGCardInstance * _source, bool must = false, vector<MTGAbility*>abilities = vector<MTGAbility*>(),Player * who = NULL,string _newName = "");
|
||||||
void Update(float dt);
|
void Update(float dt);
|
||||||
int resolve();
|
int resolve();
|
||||||
const char * getMenuText();
|
const char * getMenuText();
|
||||||
@@ -1393,9 +1394,9 @@ class AADrawer: public ActivatedAbilityTP
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
string nbcardsStr;
|
string nbcardsStr;
|
||||||
|
bool noReplace;
|
||||||
AADrawer(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost,string nbcardsStr, int who =
|
AADrawer(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost,string nbcardsStr, int who =
|
||||||
TargetChooser::UNSET);
|
TargetChooser::UNSET,bool noReplace = false);
|
||||||
int resolve();
|
int resolve();
|
||||||
const char * getMenuText();
|
const char * getMenuText();
|
||||||
AADrawer * clone() const;
|
AADrawer * clone() const;
|
||||||
@@ -2622,7 +2623,14 @@ public:
|
|||||||
int resolve();
|
int resolve();
|
||||||
PairCard * clone() const;
|
PairCard * clone() const;
|
||||||
};
|
};
|
||||||
|
//pick a card to dredge
|
||||||
|
class dredgeCard: public InstantAbility
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
dredgeCard(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target, ManaCost * _cost = NULL);
|
||||||
|
int resolve();
|
||||||
|
dredgeCard * clone() const;
|
||||||
|
};
|
||||||
/* create a parent child association between cards */
|
/* create a parent child association between cards */
|
||||||
class AAConnect: public InstantAbility
|
class AAConnect: public InstantAbility
|
||||||
{
|
{
|
||||||
@@ -4300,6 +4308,18 @@ public:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ADrawReplacer: public MTGAbility
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
REDrawReplacement * re;
|
||||||
|
MTGAbility * replacer;
|
||||||
|
bool OtherPlayer;
|
||||||
|
ADrawReplacer(GameObserver* observer, int id, MTGCardInstance * source, MTGAbility * _replace = NULL,bool otherPlayer = false);
|
||||||
|
int addToGame();
|
||||||
|
int destroy();
|
||||||
|
ADrawReplacer * clone() const;
|
||||||
|
~ADrawReplacer();
|
||||||
|
};
|
||||||
/*
|
/*
|
||||||
Specific Classes
|
Specific Classes
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ public:
|
|||||||
int power;
|
int power;
|
||||||
int toughness;
|
int toughness;
|
||||||
int suspendedTime;
|
int suspendedTime;
|
||||||
|
int dredgeAmount;
|
||||||
|
|
||||||
vector<int>types;
|
vector<int>types;
|
||||||
CardPrimitive();
|
CardPrimitive();
|
||||||
@@ -110,7 +111,7 @@ public:
|
|||||||
bool isCreature();
|
bool isCreature();
|
||||||
bool isLand();
|
bool isLand();
|
||||||
bool isSpell();
|
bool isSpell();
|
||||||
|
int dredge();
|
||||||
void setPower(int _power);
|
void setPower(int _power);
|
||||||
int getPower();
|
int getPower();
|
||||||
void setToughness(int _toughness);
|
void setToughness(int _toughness);
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ public:
|
|||||||
int fresh;
|
int fresh;
|
||||||
int MaxLevelUp;
|
int MaxLevelUp;
|
||||||
int kicked;
|
int kicked;
|
||||||
|
int dredge;
|
||||||
bool isDualWielding;
|
bool isDualWielding;
|
||||||
bool stillNeeded;
|
bool stillNeeded;
|
||||||
Player * lastController;
|
Player * lastController;
|
||||||
|
|||||||
@@ -272,6 +272,24 @@ public:
|
|||||||
virtual ostream& toString(ostream& out) const;
|
virtual ostream& toString(ostream& out) const;
|
||||||
virtual MTGSoulbondRule * clone() const;
|
virtual MTGSoulbondRule * clone() const;
|
||||||
};
|
};
|
||||||
|
/*dredge*/
|
||||||
|
class MTGDredgeRule: public PermanentAbility, public ReplacementEffect
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
vector<MTGCardInstance*>soulbonders;
|
||||||
|
TargetChooser * tcb;
|
||||||
|
MTGAbility * dredgeAbility;
|
||||||
|
MTGAbility * targetAbility;
|
||||||
|
MTGAbility * targetAbilityAdder;
|
||||||
|
MTGAbility * targetAbility1;
|
||||||
|
MTGAbility * mod;
|
||||||
|
MTGAbility * activateDredge;
|
||||||
|
vector<MTGAbility*>pairing;
|
||||||
|
MTGDredgeRule(GameObserver* observer, int _id);
|
||||||
|
WEvent * replace(WEvent *e);
|
||||||
|
virtual ostream& toString(ostream& out) const;
|
||||||
|
virtual MTGDredgeRule * clone() const;
|
||||||
|
};
|
||||||
/* Persist Rule */
|
/* Persist Rule */
|
||||||
class MTGPersistRule: public PermanentAbility
|
class MTGPersistRule: public PermanentAbility
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -49,12 +49,22 @@ public:
|
|||||||
WEvent * replace(WEvent *e);
|
WEvent * replace(WEvent *e);
|
||||||
~RECountersPrevention();
|
~RECountersPrevention();
|
||||||
};
|
};
|
||||||
|
class REDrawReplacement: public ReplacementEffect
|
||||||
class ReplacementEffects
|
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
list<ReplacementEffect *> modifiers;
|
MTGAbility * source;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Player * DrawerOfCard;
|
||||||
|
MTGAbility * replacementAbility;
|
||||||
|
REDrawReplacement(MTGAbility * _source, Player * Drawer = NULL, MTGAbility * replaceWith = NULL);
|
||||||
|
WEvent * replace(WEvent *e);
|
||||||
|
~REDrawReplacement();
|
||||||
|
};
|
||||||
|
class ReplacementEffects
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
list<ReplacementEffect *> modifiers;
|
||||||
ReplacementEffects();
|
ReplacementEffects();
|
||||||
WEvent * replace(WEvent *e);
|
WEvent * replace(WEvent *e);
|
||||||
int add(ReplacementEffect * re);
|
int add(ReplacementEffect * re);
|
||||||
|
|||||||
@@ -298,6 +298,25 @@ public:
|
|||||||
virtual bool equals(TargetChooser * tc);
|
virtual bool equals(TargetChooser * tc);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class dredgeChooser: public TypeTargetChooser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool withoutProtections;
|
||||||
|
dredgeChooser(GameObserver *observer, int * _zones, int _nbzones, MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false, bool targetMin = false) :
|
||||||
|
TypeTargetChooser(observer, "*|mygraveyard",_zones, _nbzones, card, _maxtargets, other, targetMin)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
;
|
||||||
|
dredgeChooser(GameObserver *observer, MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false,bool targetMin = false) :
|
||||||
|
TypeTargetChooser(observer, "*|mygraveyard", card, _maxtargets, other,targetMin)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
;
|
||||||
|
virtual bool canTarget(Targetable * target, bool withoutProtections = false);
|
||||||
|
virtual dredgeChooser * clone() const;
|
||||||
|
virtual bool equals(TargetChooser * tc);
|
||||||
|
};
|
||||||
|
|
||||||
class myCursesChooser: public TypeTargetChooser
|
class myCursesChooser: public TypeTargetChooser
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ class Targetable;
|
|||||||
class ManaPool;
|
class ManaPool;
|
||||||
class AACounter;
|
class AACounter;
|
||||||
class Counters;
|
class Counters;
|
||||||
|
class MTGAbility;
|
||||||
|
class DrawAction;
|
||||||
|
|
||||||
class WEvent {
|
class WEvent {
|
||||||
public:
|
public:
|
||||||
@@ -221,7 +223,13 @@ struct WEventcardDraw : public WEvent {
|
|||||||
int nb_cards;
|
int nb_cards;
|
||||||
virtual Targetable * getTarget(Player * player);
|
virtual Targetable * getTarget(Player * player);
|
||||||
};
|
};
|
||||||
|
//event for a card draw ability resolving
|
||||||
|
struct WEventDraw : public WEvent {
|
||||||
|
WEventDraw(Player * player,int nb_cards,MTGAbility * drawer);
|
||||||
|
Player * player;
|
||||||
|
int nb_cards;
|
||||||
|
MTGAbility * drawAbility;
|
||||||
|
};
|
||||||
//Event when a blocker is reordered
|
//Event when a blocker is reordered
|
||||||
//exchangeWith: exchange card's position with exchangeWith's position
|
//exchangeWith: exchange card's position with exchangeWith's position
|
||||||
//attacker:both card and exchangeWith *should* be in attacker's "blockers" list.
|
//attacker:both card and exchangeWith *should* be in attacker's "blockers" list.
|
||||||
|
|||||||
@@ -602,7 +602,7 @@ int OrderedAIAction::getEfficiency()
|
|||||||
if (!efficiency && may)
|
if (!efficiency && may)
|
||||||
{
|
{
|
||||||
AIPlayer * chk = (AIPlayer*)p;
|
AIPlayer * chk = (AIPlayer*)p;
|
||||||
if(may->ability->getActionTc() && chk->chooseTarget(may->ability->getActionTc(),NULL,NULL,true))
|
if(may->ability && may->ability->getActionTc() && chk->chooseTarget(may->ability->getActionTc(),NULL,NULL,true))
|
||||||
efficiency = 50 + (owner->getRandomGenerator()->random() % 50);
|
efficiency = 50 + (owner->getRandomGenerator()->random() % 50);
|
||||||
}
|
}
|
||||||
if (p->game->hand->nb_cards == 0)
|
if (p->game->hand->nb_cards == 0)
|
||||||
|
|||||||
@@ -415,7 +415,7 @@ void ActionLayer::setMenuObject(Targetable * object, bool must)
|
|||||||
modal = 1;
|
modal = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionLayer::setCustomMenuObject(Targetable * object, bool must,vector<MTGAbility*>abilities)
|
void ActionLayer::setCustomMenuObject(Targetable * object, bool must,vector<MTGAbility*>abilities,string customName)
|
||||||
{
|
{
|
||||||
if (!object)
|
if (!object)
|
||||||
{
|
{
|
||||||
@@ -424,7 +424,7 @@ void ActionLayer::setCustomMenuObject(Targetable * object, bool must,vector<MTGA
|
|||||||
}
|
}
|
||||||
menuObject = object;
|
menuObject = object;
|
||||||
SAFE_DELETE(abilitiesMenu);
|
SAFE_DELETE(abilitiesMenu);
|
||||||
abilitiesMenu = NEW SimpleMenu(observer->getInput(), 10, this, Fonts::MAIN_FONT, 100, 100, object->getDisplayName().c_str());
|
abilitiesMenu = NEW SimpleMenu(observer->getInput(), 10, this, Fonts::MAIN_FONT, 100, 100, customName.size()?customName.c_str():object->getDisplayName().c_str());
|
||||||
currentActionCard = NULL;
|
currentActionCard = NULL;
|
||||||
abilitiesMenu->isMultipleChoice = false;
|
abilitiesMenu->isMultipleChoice = false;
|
||||||
if(abilities.size())
|
if(abilities.size())
|
||||||
|
|||||||
@@ -581,7 +581,7 @@ ACounterShroud::~ACounterShroud()
|
|||||||
SAFE_DELETE(counter);
|
SAFE_DELETE(counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
//shield a card from a certain type of counter.
|
//track counters placed on a card
|
||||||
ACounterTracker::ACounterTracker(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target, string scounter) :
|
ACounterTracker::ACounterTracker(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target, string scounter) :
|
||||||
MTGAbility(observer, id, source, target),scounter(scounter)
|
MTGAbility(observer, id, source, target),scounter(scounter)
|
||||||
{
|
{
|
||||||
@@ -1112,6 +1112,47 @@ AASetCoin::~AASetCoin()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//replace drawing a card with activation of an ability
|
||||||
|
ADrawReplacer::ADrawReplacer(GameObserver* observer, int id, MTGCardInstance * source, MTGAbility * replace, bool otherPlayer) :
|
||||||
|
MTGAbility(observer, id, source),re(NULL),replacer(replace),OtherPlayer(otherPlayer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int ADrawReplacer::addToGame()
|
||||||
|
{
|
||||||
|
SAFE_DELETE(re);
|
||||||
|
if(OtherPlayer)
|
||||||
|
re = NEW REDrawReplacement(this,source->controller()->opponent(),replacer);
|
||||||
|
else
|
||||||
|
re = NEW REDrawReplacement(this,source->controller(),replacer);
|
||||||
|
if (re)
|
||||||
|
{
|
||||||
|
game->replacementEffects->add(re);
|
||||||
|
return MTGAbility::addToGame();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ADrawReplacer::destroy()
|
||||||
|
{
|
||||||
|
game->replacementEffects->remove(re);
|
||||||
|
SAFE_DELETE(re);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ADrawReplacer * ADrawReplacer::clone() const
|
||||||
|
{
|
||||||
|
ADrawReplacer * a = NEW ADrawReplacer(*this);
|
||||||
|
a->re = NULL;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
ADrawReplacer::~ADrawReplacer()
|
||||||
|
{
|
||||||
|
SAFE_DELETE(re);
|
||||||
|
SAFE_DELETE(replacer);
|
||||||
|
}
|
||||||
//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):
|
||||||
ActivatedAbility(observer, id, source, cost, 0)
|
ActivatedAbility(observer, id, source, cost, 0)
|
||||||
@@ -1394,8 +1435,8 @@ AADiscardCard::~AADiscardCard()
|
|||||||
SAFE_DELETE(andAbility);
|
SAFE_DELETE(andAbility);
|
||||||
}
|
}
|
||||||
AADrawer::AADrawer(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost, string nbcardsStr,
|
AADrawer::AADrawer(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost, string nbcardsStr,
|
||||||
int who) :
|
int who, bool noreplace) :
|
||||||
ActivatedAbilityTP(observer, _id, card, _target, _cost, who), nbcardsStr(nbcardsStr)
|
ActivatedAbilityTP(observer, _id, card, _target, _cost, who), nbcardsStr(nbcardsStr),noReplace(noreplace)
|
||||||
{
|
{
|
||||||
aType = MTGAbility::STANDARD_DRAW;
|
aType = MTGAbility::STANDARD_DRAW;
|
||||||
}
|
}
|
||||||
@@ -1407,6 +1448,11 @@ AADrawer::AADrawer(GameObserver* observer, int _id, MTGCardInstance * card, Targ
|
|||||||
if (player)
|
if (player)
|
||||||
{
|
{
|
||||||
WParsedInt numCards(nbcardsStr, NULL, source);
|
WParsedInt numCards(nbcardsStr, NULL, source);
|
||||||
|
WEvent * e = NEW WEventDraw(player, numCards.getValue(),this);
|
||||||
|
if(!noReplace)
|
||||||
|
e = game->replacementEffects->replace(e);
|
||||||
|
if(e)
|
||||||
|
{
|
||||||
game->mLayers->stackLayer()->addDraw(player, numCards.getValue());
|
game->mLayers->stackLayer()->addDraw(player, numCards.getValue());
|
||||||
game->mLayers->stackLayer()->resolve();
|
game->mLayers->stackLayer()->resolve();
|
||||||
for(int i = numCards.getValue(); i > 0;i--)
|
for(int i = numCards.getValue(); i > 0;i--)
|
||||||
@@ -1415,6 +1461,8 @@ AADrawer::AADrawer(GameObserver* observer, int _id, MTGCardInstance * card, Targ
|
|||||||
game->receiveEvent(e);
|
game->receiveEvent(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SAFE_DELETE(e);
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3116,8 +3164,8 @@ MayAbility::~MayAbility()
|
|||||||
|
|
||||||
//Menu building ability Abilities
|
//Menu building ability Abilities
|
||||||
//this will eventaully handle choosen discards/sacrifices.
|
//this will eventaully handle choosen discards/sacrifices.
|
||||||
MenuAbility::MenuAbility(GameObserver* observer, int _id, Targetable * mtarget, MTGCardInstance * _source, bool must,vector<MTGAbility*>abilities,Player * who) :
|
MenuAbility::MenuAbility(GameObserver* observer, int _id, Targetable * mtarget, MTGCardInstance * _source, bool must,vector<MTGAbility*>abilities,Player * who, string newName) :
|
||||||
MayAbility(observer, _id,NULL,_source,must), must(must),abilities(abilities),who(who)
|
MayAbility(observer, _id,NULL,_source,must), must(must),abilities(abilities),who(who),newNameString(newName)
|
||||||
{
|
{
|
||||||
triggered = 0;
|
triggered = 0;
|
||||||
mClone = NULL;
|
mClone = NULL;
|
||||||
@@ -3129,7 +3177,7 @@ void MenuAbility::Update(float dt)
|
|||||||
{
|
{
|
||||||
MTGAbility::Update(dt);
|
MTGAbility::Update(dt);
|
||||||
ActionLayer * object = game->mLayers->actionLayer();
|
ActionLayer * object = game->mLayers->actionLayer();
|
||||||
if (!triggered && !object->menuObject)
|
if (!triggered && !object->menuObject && !object->getCurrentTargetChooser())
|
||||||
{
|
{
|
||||||
|
|
||||||
triggered = 1;
|
triggered = 1;
|
||||||
@@ -3146,7 +3194,7 @@ void MenuAbility::Update(float dt)
|
|||||||
}
|
}
|
||||||
if(triggered)
|
if(triggered)
|
||||||
{
|
{
|
||||||
game->mLayers->actionLayer()->setCustomMenuObject(source, must,abilities);
|
game->mLayers->actionLayer()->setCustomMenuObject(source, must,abilities,newNameString.size()?newNameString.c_str():"");
|
||||||
previousInterrupter = game->isInterrupting;
|
previousInterrupter = game->isInterrupting;
|
||||||
game->mLayers->stackLayer()->setIsInterrupting(source->controller(), false);
|
game->mLayers->stackLayer()->setIsInterrupting(source->controller(), false);
|
||||||
}
|
}
|
||||||
@@ -3238,6 +3286,8 @@ MenuAbility::~MenuAbility()
|
|||||||
if(abilities.size())
|
if(abilities.size())
|
||||||
{
|
{
|
||||||
for(int i = 0;i < int(abilities.size());i++)
|
for(int i = 0;i < int(abilities.size());i++)
|
||||||
|
{
|
||||||
|
if(abilities[i])
|
||||||
{
|
{
|
||||||
AASetColorChosen * chooseA = dynamic_cast<AASetColorChosen *>(abilities[i]);
|
AASetColorChosen * chooseA = dynamic_cast<AASetColorChosen *>(abilities[i]);
|
||||||
if(chooseA && chooseA->abilityAltered)
|
if(chooseA && chooseA->abilityAltered)
|
||||||
@@ -3245,6 +3295,7 @@ MenuAbility::~MenuAbility()
|
|||||||
SAFE_DELETE(abilities[i]);
|
SAFE_DELETE(abilities[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
SAFE_DELETE(ability);
|
SAFE_DELETE(ability);
|
||||||
}
|
}
|
||||||
@@ -4897,7 +4948,35 @@ PairCard * PairCard::clone() const
|
|||||||
{
|
{
|
||||||
return NEW PairCard(*this);
|
return NEW PairCard(*this);
|
||||||
}
|
}
|
||||||
|
//target is dredged
|
||||||
|
dredgeCard::dredgeCard(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target, ManaCost * _cost) :
|
||||||
|
InstantAbility(observer, id, card, target)
|
||||||
|
{
|
||||||
|
target = _target;
|
||||||
|
oneShot = true;
|
||||||
|
forceDestroy = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dredgeCard::resolve()
|
||||||
|
{
|
||||||
|
MTGCardInstance * _target = (MTGCardInstance *) target;
|
||||||
|
if(_target)
|
||||||
|
{
|
||||||
|
for(int j = 0; j < _target->data->dredge();j++)
|
||||||
|
{
|
||||||
|
_target->controller()->game->putInZone(
|
||||||
|
_target->controller()->game->library->cards[_target->controller()->game->library->nb_cards - 1],
|
||||||
|
_target->controller()->game->library, _target->controller()->game->graveyard);
|
||||||
|
}
|
||||||
|
_target->controller()->game->putInZone(_target,_target->currentZone,_target->controller()->game->hand);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dredgeCard * dredgeCard::clone() const
|
||||||
|
{
|
||||||
|
return NEW dredgeCard(*this);
|
||||||
|
}
|
||||||
|
|
||||||
// target becomes a parent of card(source)
|
// target becomes a parent of card(source)
|
||||||
AAConnect::AAConnect(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target, ManaCost * _cost) :
|
AAConnect::AAConnect(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target, ManaCost * _cost) :
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ CardPrimitive::CardPrimitive(CardPrimitive * source)
|
|||||||
toughness = source->toughness;
|
toughness = source->toughness;
|
||||||
restrictions = source->restrictions ? source->restrictions->clone() : NULL;
|
restrictions = source->restrictions ? source->restrictions->clone() : NULL;
|
||||||
suspendedTime = source->suspendedTime;
|
suspendedTime = source->suspendedTime;
|
||||||
|
dredgeAmount = source->dredgeAmount;
|
||||||
|
|
||||||
magicText = source->magicText;
|
magicText = source->magicText;
|
||||||
for (map<string, string>::const_iterator it = source->magicTexts.begin(); it != source->magicTexts.end(); ++it)
|
for (map<string, string>::const_iterator it = source->magicTexts.begin(); it != source->magicTexts.end(); ++it)
|
||||||
@@ -82,6 +83,7 @@ int CardPrimitive::init()
|
|||||||
spellTargetType = "";
|
spellTargetType = "";
|
||||||
alias = 0;
|
alias = 0;
|
||||||
restrictions = NULL;
|
restrictions = NULL;
|
||||||
|
dredgeAmount = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,6 +102,11 @@ bool CardPrimitive::isSpell()
|
|||||||
return (!isCreature() && !isLand());
|
return (!isCreature() && !isLand());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CardPrimitive::dredge()
|
||||||
|
{
|
||||||
|
return dredgeAmount;
|
||||||
|
}
|
||||||
|
|
||||||
void CardPrimitive::setRestrictions(string _restriction)
|
void CardPrimitive::setRestrictions(string _restriction)
|
||||||
{
|
{
|
||||||
if (!restrictions)
|
if (!restrictions)
|
||||||
|
|||||||
@@ -961,13 +961,20 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
observer->addObserver(NEW MTGBlockRule(observer, -1));
|
observer->addObserver(NEW MTGBlockRule(observer, -1));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
//this rule handles blocking ability during blocker phase
|
//this rule handles cards that have soulbond
|
||||||
found = s.find("soulbondrule");
|
found = s.find("soulbondrule");
|
||||||
if(found != string::npos)
|
if(found != string::npos)
|
||||||
{
|
{
|
||||||
observer->addObserver(NEW MTGSoulbondRule(observer, -1));
|
observer->addObserver(NEW MTGSoulbondRule(observer, -1));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
//this rule handles cards that have dredge
|
||||||
|
found = s.find("dredgerule");
|
||||||
|
if(found != string::npos)
|
||||||
|
{
|
||||||
|
observer->replacementEffects->add(NEW MTGDredgeRule(observer, -1));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
//this rule handles combat related triggers. note, combat related triggered abilities will not work without it.
|
//this rule handles combat related triggers. note, combat related triggered abilities will not work without it.
|
||||||
found = s.find("combattriggerrule");
|
found = s.find("combattriggerrule");
|
||||||
if(found != string::npos)
|
if(found != string::npos)
|
||||||
@@ -1700,6 +1707,30 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//opponent replace draw with
|
||||||
|
found = s.find("opponentreplacedraw ");
|
||||||
|
if (found != string::npos)
|
||||||
|
{
|
||||||
|
string s1 = s.substr(found + 19);
|
||||||
|
MTGAbility * a = NULL;
|
||||||
|
a = parseMagicLine(s1, id, spell, card, false, activated);
|
||||||
|
if(a)
|
||||||
|
return NEW ADrawReplacer(observer,id, card,a,true);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//replace draw with
|
||||||
|
found = s.find("replacedraw ");
|
||||||
|
if (found != string::npos)
|
||||||
|
{
|
||||||
|
string s1 = s.substr(found + 11);
|
||||||
|
MTGAbility * a = NULL;
|
||||||
|
a = parseMagicLine(s1, id, spell, card, false, activated);
|
||||||
|
if(a)
|
||||||
|
return NEW ADrawReplacer(observer,id, card,a);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!activated && tc)
|
if (!activated && tc)
|
||||||
{
|
{
|
||||||
MTGAbility * a = parseMagicLine(sWithoutTc, id, spell, card);
|
MTGAbility * a = parseMagicLine(sWithoutTc, id, spell, card);
|
||||||
@@ -1870,9 +1901,19 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
{
|
{
|
||||||
if (storedAbilityString.size())
|
if (storedAbilityString.size())
|
||||||
{
|
{
|
||||||
|
vector<string> splitName = parseBetween(storedAbilityString, "name(", ")");
|
||||||
|
if (splitName.size())
|
||||||
|
{
|
||||||
|
newName = splitName[1];
|
||||||
|
storedAbilityString = splitName[0];
|
||||||
|
storedAbilityString.append(splitName[2]);
|
||||||
|
//we erase the name section from the string to avoid
|
||||||
|
//accidently building an mtg ability with the text meant for menuText.
|
||||||
|
}
|
||||||
ATargetedAbilityCreator * abl = NEW ATargetedAbilityCreator(observer, id, card,target, NULL,newName, storedAbilityString, who);
|
ATargetedAbilityCreator * abl = NEW ATargetedAbilityCreator(observer, id, card,target, NULL,newName, storedAbilityString, who);
|
||||||
abl->oneShot = 1;
|
abl->oneShot = 1;
|
||||||
storedString.clear();
|
storedString.clear();
|
||||||
|
storedAbilityString.clear();
|
||||||
return abl;
|
return abl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2228,7 +2269,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
if (splitDraw.size())
|
if (splitDraw.size())
|
||||||
{
|
{
|
||||||
Targetable * t = spell ? spell->getNextTarget() : NULL;
|
Targetable * t = spell ? spell->getNextTarget() : NULL;
|
||||||
MTGAbility * a = NEW AADrawer(observer, id, card, t, NULL,splitDraw[1], who);
|
MTGAbility * a = NEW AADrawer(observer, id, card, t, NULL,splitDraw[1], who,s.find("noreplace") != string::npos);
|
||||||
a->oneShot = 1;
|
a->oneShot = 1;
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -163,6 +163,7 @@ void MTGCardInstance::initMTGCI()
|
|||||||
mPropertiesChangedSinceLastUpdate = false;
|
mPropertiesChangedSinceLastUpdate = false;
|
||||||
stillNeeded = true;
|
stillNeeded = true;
|
||||||
kicked = 0;
|
kicked = 0;
|
||||||
|
dredge = 0;
|
||||||
chooseacolor = -1;
|
chooseacolor = -1;
|
||||||
chooseasubtype = "";
|
chooseasubtype = "";
|
||||||
coinSide = -1;
|
coinSide = -1;
|
||||||
|
|||||||
@@ -119,7 +119,17 @@ int MTGAllCards::processConfLine(string &s, MTGCard *card, CardPrimitive * primi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'd'://dredge
|
||||||
|
if (!primitive) primitive = NEW CardPrimitive();
|
||||||
|
{
|
||||||
|
string value = val;
|
||||||
|
std::transform(value.begin(), value.end(), value.begin(), ::tolower);
|
||||||
|
vector<string> values = parseBetween(value,"dredge(",")");
|
||||||
|
if(values.size())
|
||||||
|
primitive->dredgeAmount = atoi(values[1].c_str());
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'f': //flashback//morph
|
case 'f': //flashback//morph
|
||||||
{
|
{
|
||||||
if (!primitive) primitive = NEW CardPrimitive();
|
if (!primitive) primitive = NEW CardPrimitive();
|
||||||
|
|||||||
@@ -2098,7 +2098,107 @@ MTGSoulbondRule * MTGSoulbondRule::clone() const
|
|||||||
{
|
{
|
||||||
return NEW MTGSoulbondRule(*this);
|
return NEW MTGSoulbondRule(*this);
|
||||||
}
|
}
|
||||||
|
/*dredge*/
|
||||||
|
MTGDredgeRule::MTGDredgeRule(GameObserver* observer, int _id) :
|
||||||
|
PermanentAbility(observer, _id)
|
||||||
|
{
|
||||||
|
tcb = NULL;
|
||||||
|
dredgeAbility = NULL;
|
||||||
|
targetAbility = NULL;
|
||||||
|
mod = NULL;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
WEvent * MTGDredgeRule::replace(WEvent * event)
|
||||||
|
{
|
||||||
|
WEventDraw * e = dynamic_cast<WEventDraw*> (event);
|
||||||
|
if (e)
|
||||||
|
{
|
||||||
|
MTGCardInstance * card = NULL;
|
||||||
|
if(e->player->game->library->nb_cards)
|
||||||
|
card = e->player->game->library->cards[e->player->game->library->nb_cards-1];
|
||||||
|
if(!card)
|
||||||
|
return event;
|
||||||
|
TargetChooserFactory tf(e->player->getObserver());
|
||||||
|
tcb = tf.createTargetChooser("dredgeable",card);
|
||||||
|
tcb->targetter = NULL;
|
||||||
|
if(!tcb->validTargetsExist())
|
||||||
|
{
|
||||||
|
SAFE_DELETE(tcb);
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
SAFE_DELETE(tcb);
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
Player * p = game->players[i];
|
||||||
|
if (e->player == p)
|
||||||
|
{
|
||||||
|
for(int draw = 0;draw < e->nb_cards;draw++)
|
||||||
|
{
|
||||||
|
tcb = tf.createTargetChooser("dredgeable",card);
|
||||||
|
tcb->targetter = NULL;
|
||||||
|
|
||||||
|
vector<MTGAbility*>selection;
|
||||||
|
//look for other draw replacement effects
|
||||||
|
list<ReplacementEffect *>::iterator it;
|
||||||
|
for (it = game->replacementEffects->modifiers.begin(); it != game->replacementEffects->modifiers.end(); it++)
|
||||||
|
{
|
||||||
|
ReplacementEffect *re = *it;
|
||||||
|
if(REDrawReplacement * DR = dynamic_cast<REDrawReplacement *>(*it))
|
||||||
|
{
|
||||||
|
MTGAbility * otherA = NULL;
|
||||||
|
if(DR->DrawerOfCard == p)
|
||||||
|
if(DR->replacementAbility->oneShot)
|
||||||
|
selection.push_back(DR->replacementAbility->clone());
|
||||||
|
else
|
||||||
|
{
|
||||||
|
otherA = NEW GenericAddToGame(game, game->mLayers->actionLayer()->getMaxId(),DR->replacementAbility->source,NULL,DR->replacementAbility->clone());
|
||||||
|
selection.push_back(otherA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//there is a memleak here that i have no idea what causes it.
|
||||||
|
dredgeAbility = NEW dredgeCard(game, game->mLayers->actionLayer()->getMaxId(), card,NULL);
|
||||||
|
dredgeAbility->oneShot = true;
|
||||||
|
targetAbility = NEW GenericTargetAbility(game, "Dredge A Card","",game->mLayers->actionLayer()->getMaxId(), card,tcb->clone(),dredgeAbility->clone());
|
||||||
|
targetAbility->oneShot = true;
|
||||||
|
SAFE_DELETE(dredgeAbility);
|
||||||
|
|
||||||
|
targetAbilityAdder = NEW GenericAddToGame(game, game->mLayers->actionLayer()->getMaxId(), card,NULL,targetAbility->clone());
|
||||||
|
targetAbilityAdder->oneShot = true;
|
||||||
|
SAFE_DELETE(targetAbility);
|
||||||
|
MTGAbility * setDredge = targetAbilityAdder->clone();
|
||||||
|
SAFE_DELETE(targetAbilityAdder);
|
||||||
|
setDredge->oneShot = true;
|
||||||
|
|
||||||
|
selection.push_back(setDredge);
|
||||||
|
targetAbility1 = NEW AADrawer(game, this->GetId(), card,card,NULL, "1",TargetChooser::CONTROLLER,true);
|
||||||
|
selection.push_back(targetAbility1);
|
||||||
|
MTGAbility * menuChoice = NEW MenuAbility(game, this->GetId(), card, card,true,selection,card->controller(),"Dredge or Draw");
|
||||||
|
|
||||||
|
menuChoice->addToGame();
|
||||||
|
SAFE_DELETE(tcb);
|
||||||
|
}
|
||||||
|
|
||||||
|
SAFE_DELETE(event);
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
ostream& MTGDredgeRule::toString(ostream& out) const
|
||||||
|
{
|
||||||
|
out << "MTGDredgeRule ::: (";
|
||||||
|
return MTGAbility::toString(out) << ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
MTGDredgeRule * MTGDredgeRule::clone() const
|
||||||
|
{
|
||||||
|
return NEW MTGDredgeRule(*this);
|
||||||
|
}
|
||||||
/* Persist */
|
/* Persist */
|
||||||
MTGPersistRule::MTGPersistRule(GameObserver* observer, int _id) :
|
MTGPersistRule::MTGPersistRule(GameObserver* observer, int _id) :
|
||||||
PermanentAbility(observer, _id)
|
PermanentAbility(observer, _id)
|
||||||
|
|||||||
@@ -77,6 +77,81 @@ RECountersPrevention::~RECountersPrevention()
|
|||||||
{
|
{
|
||||||
SAFE_DELETE(TargetingCards);
|
SAFE_DELETE(TargetingCards);
|
||||||
}
|
}
|
||||||
|
////--draw replacement---------------------
|
||||||
|
REDrawReplacement::REDrawReplacement(MTGAbility * source, Player * Drawer, MTGAbility * replaceWith) :
|
||||||
|
source(source), DrawerOfCard(Drawer),replacementAbility(replaceWith)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
WEvent * REDrawReplacement::replace(WEvent *event)
|
||||||
|
{
|
||||||
|
if (!event) return event;
|
||||||
|
WEventDraw * e = dynamic_cast<WEventDraw*> (event);
|
||||||
|
if (!e) return event;
|
||||||
|
if (DrawerOfCard != e->player) return event;
|
||||||
|
if(!replacementAbility) return event;
|
||||||
|
//check for dredge
|
||||||
|
TargetChooserFactory tf(e->player->getObserver());
|
||||||
|
TargetChooser * tcb = NULL;
|
||||||
|
tcb = tf.createTargetChooser("dredgeable",source->source);
|
||||||
|
tcb->targetter = NULL;
|
||||||
|
if(tcb->validTargetsExist())
|
||||||
|
{
|
||||||
|
if(e->player == DrawerOfCard && e->player == source->source->controller())
|
||||||
|
{
|
||||||
|
SAFE_DELETE(tcb);
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SAFE_DELETE(tcb);
|
||||||
|
|
||||||
|
vector<MTGAbility*>selection;
|
||||||
|
//look for other draw replacement effects
|
||||||
|
list<ReplacementEffect *>::iterator it;
|
||||||
|
GameObserver * game = source->source->getObserver();
|
||||||
|
if(replacementAbility->source->controller() == DrawerOfCard)
|
||||||
|
for (it = game->replacementEffects->modifiers.begin(); it != game->replacementEffects->modifiers.end(); it++)
|
||||||
|
{
|
||||||
|
ReplacementEffect *re = *it;
|
||||||
|
if(REDrawReplacement * DR = dynamic_cast<REDrawReplacement *>(*it))
|
||||||
|
{
|
||||||
|
MTGAbility * otherA = NULL;
|
||||||
|
if(DR->DrawerOfCard == e->player)
|
||||||
|
if(DR->replacementAbility->oneShot)
|
||||||
|
selection.push_back(DR->replacementAbility->clone());
|
||||||
|
else
|
||||||
|
{
|
||||||
|
otherA = NEW GenericAddToGame(game, game->mLayers->actionLayer()->getMaxId(), source->source,NULL,DR->replacementAbility->clone());
|
||||||
|
selection.push_back(otherA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for(int j = 0; j < e->nb_cards; j++)
|
||||||
|
{
|
||||||
|
if(e->player != DrawerOfCard || selection.size() < 2)
|
||||||
|
{
|
||||||
|
MTGAbility * toResolve = replacementAbility->clone();
|
||||||
|
if(replacementAbility->oneShot)
|
||||||
|
toResolve->resolve();
|
||||||
|
else
|
||||||
|
toResolve->addToGame();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MTGAbility * menuChoice = NEW MenuAbility(game, 1, source->source, source->source,true,selection,NULL,"Choose Draw Replacement");
|
||||||
|
menuChoice->addToGame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete event;
|
||||||
|
event = NULL;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
REDrawReplacement::~REDrawReplacement()
|
||||||
|
{
|
||||||
|
}
|
||||||
//////////////////////////////////////////////
|
//////////////////////////////////////////////
|
||||||
ReplacementEffects::ReplacementEffects()
|
ReplacementEffects::ReplacementEffects()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -32,6 +32,14 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
|
|||||||
return NEW pairableChooser(observer, card, maxtargets);
|
return NEW pairableChooser(observer, card, maxtargets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
found = s.find("dredgeable");
|
||||||
|
if (found != string::npos)
|
||||||
|
{
|
||||||
|
int maxtargets = 1;
|
||||||
|
zones[nbzones++] = MTGGameZone::MY_GRAVEYARD;
|
||||||
|
return NEW dredgeChooser(observer,zones,nbzones, card, maxtargets);
|
||||||
|
}
|
||||||
|
|
||||||
found = s.find("mytgt");
|
found = s.find("mytgt");
|
||||||
if (found == 0)
|
if (found == 0)
|
||||||
{
|
{
|
||||||
@@ -1601,6 +1609,35 @@ bool pairableChooser::equals(TargetChooser * tc)
|
|||||||
return TypeTargetChooser::equals(tc);
|
return TypeTargetChooser::equals(tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//*Dredge targetchooser*//
|
||||||
|
bool dredgeChooser::canTarget(Targetable * target,bool withoutProtections)
|
||||||
|
{
|
||||||
|
if (MTGCardInstance * card = dynamic_cast<MTGCardInstance*>(target))
|
||||||
|
{
|
||||||
|
if((card->data->dredgeAmount < 1) || (card->data->dredgeAmount > card->controller()->game->library->nb_cards))
|
||||||
|
return false;
|
||||||
|
if(card->currentZone == card->controller()->game->graveyard)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
dredgeChooser* dredgeChooser::clone() const
|
||||||
|
{
|
||||||
|
dredgeChooser * a = NEW dredgeChooser(*this);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dredgeChooser::equals(TargetChooser * tc)
|
||||||
|
{
|
||||||
|
|
||||||
|
dredgeChooser * dtc = dynamic_cast<dredgeChooser *> (tc);
|
||||||
|
if (!dtc)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return TypeTargetChooser::equals(tc);
|
||||||
|
}
|
||||||
|
//-----------
|
||||||
//-----------
|
//-----------
|
||||||
/*Proliferate Target */
|
/*Proliferate Target */
|
||||||
bool ProliferateChooser::canTarget(Targetable * target,bool withoutProtections)
|
bool ProliferateChooser::canTarget(Targetable * target,bool withoutProtections)
|
||||||
|
|||||||
@@ -91,6 +91,11 @@ WEventCardBlocked::WEventCardBlocked(MTGCardInstance * card,MTGCardInstance * op
|
|||||||
WEventcardDraw::WEventcardDraw(Player * player, int nb_cards) :
|
WEventcardDraw::WEventcardDraw(Player * player, int nb_cards) :
|
||||||
player(player), nb_cards(nb_cards)
|
player(player), nb_cards(nb_cards)
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
WEventDraw::WEventDraw(Player * player, int nb_cards,MTGAbility * cardDraw) ://happens at the call for drawfromlibrary
|
||||||
|
player(player), nb_cards(nb_cards),drawAbility(cardDraw)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
WEventCardSacrifice::WEventCardSacrifice(MTGCardInstance * card, MTGCardInstance * after) :
|
WEventCardSacrifice::WEventCardSacrifice(MTGCardInstance * card, MTGCardInstance * after) :
|
||||||
|
|||||||
Reference in New Issue
Block a user