this commit adds AVRs new ability soulbond.
it requires an update to your mtg rules txt...
the coding is as follows
[card]
name=Arbor Elf
mana={g}
auto=soulbond 1/3
auto=soulbond {t}:add{g}
abilities=soulbond
type=Creature
subtype=Elf Druid
power=1
toughness=1
[/card]
auto=soulbond *any ability supported by wagic*
abilities=soulbond
the above arbor elf gives itself and its soulbond creature a 1/3 bonus and the ability to tap for green mana.
This commit is contained in:
@@ -1958,6 +1958,11 @@ public:
|
|||||||
MTGAbility * toAdd = ability->clone();
|
MTGAbility * toAdd = ability->clone();
|
||||||
toAdd->forceDestroy = -1;
|
toAdd->forceDestroy = -1;
|
||||||
toAdd->target = target;
|
toAdd->target = target;
|
||||||
|
if(toAdd->getActionTc())
|
||||||
|
{
|
||||||
|
toAdd->reactToTargetClick(source);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
toAdd->addToGame();
|
toAdd->addToGame();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -1979,7 +1984,48 @@ public:
|
|||||||
SAFE_DELETE(ability);
|
SAFE_DELETE(ability);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
//generic addtogame
|
||||||
|
class GenericAddToGame: public InstantAbility, public NestedAbility
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GenericAddToGame(GameObserver* observer, int _id, MTGCardInstance * _source, Damageable * _target, MTGAbility * ability) :
|
||||||
|
InstantAbility(observer, _id, _source,_target), NestedAbility(ability)
|
||||||
|
{
|
||||||
|
ability->target = _target;
|
||||||
|
}
|
||||||
|
|
||||||
|
int addToGame()
|
||||||
|
{
|
||||||
|
InstantAbility::addToGame();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int resolve()
|
||||||
|
{
|
||||||
|
MTGAbility * toAdd = ability->clone();
|
||||||
|
toAdd->target = target;
|
||||||
|
if(toAdd->getActionTc())
|
||||||
|
return toAdd->reactToTargetClick(source);
|
||||||
|
return toAdd->addToGame();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * getMenuText()
|
||||||
|
{
|
||||||
|
return ability->getMenuText();
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericAddToGame * clone() const
|
||||||
|
{
|
||||||
|
GenericAddToGame * a = NEW GenericAddToGame(*this);
|
||||||
|
a->ability = ability->clone();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
~GenericAddToGame()
|
||||||
|
{
|
||||||
|
SAFE_DELETE(ability);
|
||||||
|
}
|
||||||
|
};
|
||||||
//Circle of Protections
|
//Circle of Protections
|
||||||
class ACircleOfProtection: public TargetAbility
|
class ACircleOfProtection: public TargetAbility
|
||||||
{
|
{
|
||||||
@@ -2233,7 +2279,7 @@ public:
|
|||||||
if (a->oneShot)
|
if (a->oneShot)
|
||||||
{
|
{
|
||||||
a->resolve();
|
a->resolve();
|
||||||
delete (a);
|
SAFE_DELETE(a);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2344,7 +2390,7 @@ public:
|
|||||||
if (a->oneShot)
|
if (a->oneShot)
|
||||||
{
|
{
|
||||||
a->resolve();
|
a->resolve();
|
||||||
delete (a);
|
SAFE_DELETE(a);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2463,8 +2509,11 @@ public:
|
|||||||
if (skills.find(card) != skills.end())
|
if (skills.find(card) != skills.end())
|
||||||
{
|
{
|
||||||
if(!game->removeObserver(skills[card]))
|
if(!game->removeObserver(skills[card]))
|
||||||
|
{
|
||||||
skills[card]->destroy();
|
skills[card]->destroy();
|
||||||
skills.erase(card);
|
}
|
||||||
|
if(skills[card])
|
||||||
|
skills.erase(card);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -2489,7 +2538,7 @@ public:
|
|||||||
if (a->oneShot)
|
if (a->oneShot)
|
||||||
{
|
{
|
||||||
a->resolve();
|
a->resolve();
|
||||||
delete (a);
|
SAFE_DELETE(a);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2534,6 +2583,15 @@ public:
|
|||||||
AABlock * clone() const;
|
AABlock * clone() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* assign a creature as a pair to target */
|
||||||
|
class PairCard: public InstantAbility
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PairCard(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target, ManaCost * _cost = NULL);
|
||||||
|
int resolve();
|
||||||
|
PairCard * clone() const;
|
||||||
|
};
|
||||||
|
|
||||||
/* create a parent child association between cards */
|
/* create a parent child association between cards */
|
||||||
class AAConnect: public InstantAbility
|
class AAConnect: public InstantAbility
|
||||||
{
|
{
|
||||||
@@ -2990,6 +3048,101 @@ public:
|
|||||||
|
|
||||||
};
|
};
|
||||||
///
|
///
|
||||||
|
//a paired lord
|
||||||
|
class APaired: public MTGAbility, public NestedAbility
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MTGAbility * a;
|
||||||
|
MTGAbility * b;
|
||||||
|
APaired(GameObserver* observer, int _id, MTGCardInstance * _source, Damageable * _target, MTGAbility * ability) :
|
||||||
|
MTGAbility(observer, _id, _source, _target), NestedAbility(ability)
|
||||||
|
{
|
||||||
|
ability->source = source;
|
||||||
|
ability->target = target;
|
||||||
|
a = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int removeFromGame()
|
||||||
|
{
|
||||||
|
return removeAbilityFromGame();
|
||||||
|
}
|
||||||
|
|
||||||
|
int addToGame()
|
||||||
|
{
|
||||||
|
return MTGAbility::addToGame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update(float dt)
|
||||||
|
{
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
int resolve()
|
||||||
|
{
|
||||||
|
if (source->myPair)
|
||||||
|
{
|
||||||
|
addAbilityToGame();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
removeAbilityFromGame();
|
||||||
|
}
|
||||||
|
if (ability->oneShot) a = NULL; //allows to call the effect several times
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int addAbilityToGame()
|
||||||
|
{
|
||||||
|
if (a && b) return 0;
|
||||||
|
a = ability->clone();
|
||||||
|
b = ability->clone();
|
||||||
|
a->source = source;
|
||||||
|
a->target = source;
|
||||||
|
b->source = source->myPair;
|
||||||
|
b->target = source->myPair;
|
||||||
|
if (a->oneShot)
|
||||||
|
{
|
||||||
|
a->resolve();
|
||||||
|
b->resolve();
|
||||||
|
SAFE_DELETE(a);
|
||||||
|
SAFE_DELETE(b);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
a->addToGame();
|
||||||
|
b->addToGame();
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int destroy()
|
||||||
|
{
|
||||||
|
return removeAbilityFromGame();
|
||||||
|
}
|
||||||
|
|
||||||
|
int removeAbilityFromGame()
|
||||||
|
{
|
||||||
|
if (!a && !b) return 0;
|
||||||
|
game->removeObserver(a);
|
||||||
|
a = NULL;
|
||||||
|
game->removeObserver(b);
|
||||||
|
b = NULL;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
~APaired()
|
||||||
|
{
|
||||||
|
SAFE_DELETE(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
APaired * clone() const
|
||||||
|
{
|
||||||
|
APaired * a = NEW APaired(*this);
|
||||||
|
a->ability = ability->clone();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//Foreach (plague rats...)
|
//Foreach (plague rats...)
|
||||||
class AForeach: public ListMaintainerAbility, public NestedAbility
|
class AForeach: public ListMaintainerAbility, public NestedAbility
|
||||||
{
|
{
|
||||||
@@ -3028,7 +3181,7 @@ public:
|
|||||||
if (a->oneShot)
|
if (a->oneShot)
|
||||||
{
|
{
|
||||||
a->resolve();
|
a->resolve();
|
||||||
delete (a);
|
SAFE_DELETE(a);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -3138,7 +3291,7 @@ public:
|
|||||||
if (a->oneShot)
|
if (a->oneShot)
|
||||||
{
|
{
|
||||||
a->resolve();
|
a->resolve();
|
||||||
delete (a);
|
SAFE_DELETE(a);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -3229,7 +3382,7 @@ public:
|
|||||||
if (a->oneShot)
|
if (a->oneShot)
|
||||||
{
|
{
|
||||||
a->resolve();
|
a->resolve();
|
||||||
delete (a);
|
SAFE_DELETE(a);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -155,6 +155,7 @@ public:
|
|||||||
int isAttacker();
|
int isAttacker();
|
||||||
Targetable * isAttacking;
|
Targetable * isAttacking;
|
||||||
MTGCardInstance * storedCard;
|
MTGCardInstance * storedCard;
|
||||||
|
MTGCardInstance * myPair;
|
||||||
MTGCardInstance * createSnapShot();
|
MTGCardInstance * createSnapShot();
|
||||||
MTGCardInstance * storedSourceCard;
|
MTGCardInstance * storedSourceCard;
|
||||||
MTGCardInstance * isDefenser();
|
MTGCardInstance * isDefenser();
|
||||||
|
|||||||
@@ -218,8 +218,9 @@ class Constants
|
|||||||
NOMANA = 97,
|
NOMANA = 97,
|
||||||
ONLYMANA = 98,
|
ONLYMANA = 98,
|
||||||
POISONDAMAGER = 99,
|
POISONDAMAGER = 99,
|
||||||
|
soulbond = 100,
|
||||||
|
|
||||||
NB_BASIC_ABILITIES = 100,
|
NB_BASIC_ABILITIES = 101,
|
||||||
|
|
||||||
|
|
||||||
RARITY_S = 'S', //Special Rarity
|
RARITY_S = 'S', //Special Rarity
|
||||||
|
|||||||
@@ -255,7 +255,24 @@ public:
|
|||||||
virtual MTGBlockRule * clone() const;
|
virtual MTGBlockRule * clone() const;
|
||||||
~MTGBlockRule();
|
~MTGBlockRule();
|
||||||
};
|
};
|
||||||
|
//soulbond rule
|
||||||
|
class MTGSoulbondRule: public PermanentAbility
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
vector<MTGCardInstance*>soulbonders;
|
||||||
|
TargetChooser * tcb;
|
||||||
|
MTGAbility * pairAbility;
|
||||||
|
MTGAbility * targetAbility;
|
||||||
|
MTGAbility * targetAbility1;
|
||||||
|
MTGAbility * mod;
|
||||||
|
MTGAbility * activatePairing;
|
||||||
|
vector<MTGAbility*>pairing;
|
||||||
|
MTGSoulbondRule(GameObserver* observer, int _id);
|
||||||
|
int receiveEvent(WEvent * event);
|
||||||
|
virtual ostream& toString(ostream& out) const;
|
||||||
|
virtual MTGSoulbondRule * clone() const;
|
||||||
|
~MTGSoulbondRule();
|
||||||
|
};
|
||||||
/* Persist Rule */
|
/* Persist Rule */
|
||||||
class MTGPersistRule: public PermanentAbility
|
class MTGPersistRule: public PermanentAbility
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -279,6 +279,25 @@ public:
|
|||||||
virtual bool equals(TargetChooser * tc);
|
virtual bool equals(TargetChooser * tc);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class pairableChooser: public TypeTargetChooser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool withoutProtections;
|
||||||
|
pairableChooser(GameObserver *observer, int * _zones, int _nbzones, MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false, bool targetMin = false) :
|
||||||
|
TypeTargetChooser(observer, "creature|mybattlefield",_zones, _nbzones, card, _maxtargets, other, targetMin)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
;
|
||||||
|
pairableChooser(GameObserver *observer, MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false,bool targetMin = false) :
|
||||||
|
TypeTargetChooser(observer, "creature|mybattlefield", card, _maxtargets, other,targetMin)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
;
|
||||||
|
virtual bool canTarget(Targetable * target, bool withoutProtections = false);
|
||||||
|
virtual pairableChooser * clone() const;
|
||||||
|
virtual bool equals(TargetChooser * tc);
|
||||||
|
};
|
||||||
|
|
||||||
class myCursesChooser: public TypeTargetChooser
|
class myCursesChooser: public TypeTargetChooser
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -3161,9 +3161,9 @@ int MenuAbility::resolve()
|
|||||||
|
|
||||||
const char * MenuAbility::getMenuText()
|
const char * MenuAbility::getMenuText()
|
||||||
{
|
{
|
||||||
if(abilities.size())
|
if((abilities.size() > 1 && must)||(abilities.size() > 2 && !must))
|
||||||
return "choose one";
|
return "choose one";
|
||||||
return ability->getMenuText();
|
return "Action";
|
||||||
}
|
}
|
||||||
|
|
||||||
int MenuAbility::testDestroy()
|
int MenuAbility::testDestroy()
|
||||||
@@ -3198,7 +3198,11 @@ int MenuAbility::reactToChoiceClick(Targetable * object,int choice,int control)
|
|||||||
// abilities[i]->clone();//all get cloned for clean up purposes. EDIT:removed, cause memleaks.
|
// abilities[i]->clone();//all get cloned for clean up purposes. EDIT:removed, cause memleaks.
|
||||||
}
|
}
|
||||||
if(!mClone)
|
if(!mClone)
|
||||||
|
{
|
||||||
|
if (source->controller() == game->isInterrupting)
|
||||||
|
game->mLayers->stackLayer()->cancelInterruptOffer(ActionStack::DONT_INTERRUPT, false);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
mClone->target = abilities[choice]->target;
|
mClone->target = abilities[choice]->target;
|
||||||
mClone->oneShot = true;
|
mClone->oneShot = true;
|
||||||
mClone->forceDestroy = 1;
|
mClone->forceDestroy = 1;
|
||||||
@@ -4853,6 +4857,32 @@ AABlock * AABlock::clone() const
|
|||||||
return NEW AABlock(*this);
|
return NEW AABlock(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// target becomes pair of source
|
||||||
|
PairCard::PairCard(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target, ManaCost * _cost) :
|
||||||
|
InstantAbility(observer, id, card, target)
|
||||||
|
{
|
||||||
|
target = _target;
|
||||||
|
oneShot = true;
|
||||||
|
forceDestroy = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PairCard::resolve()
|
||||||
|
{
|
||||||
|
MTGCardInstance * _target = (MTGCardInstance *) target;
|
||||||
|
source = (MTGCardInstance*)source;
|
||||||
|
if (_target && !_target->myPair && source)
|
||||||
|
{
|
||||||
|
source->myPair = _target;
|
||||||
|
_target->myPair = source;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PairCard * PairCard::clone() const
|
||||||
|
{
|
||||||
|
return NEW PairCard(*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) :
|
||||||
|
|||||||
@@ -598,6 +598,11 @@ void GameObserver::gameStateBasedEffects()
|
|||||||
card->mPropertiesChangedSinceLastUpdate = false;
|
card->mPropertiesChangedSinceLastUpdate = false;
|
||||||
if(card->hasType(Subtypes::TYPE_PLANESWALKER) && (!card->counters||!card->counters->hasCounter("loyalty",0,0)))
|
if(card->hasType(Subtypes::TYPE_PLANESWALKER) && (!card->counters||!card->counters->hasCounter("loyalty",0,0)))
|
||||||
players[i]->game->putInGraveyard(card);
|
players[i]->game->putInGraveyard(card);
|
||||||
|
if(card->myPair && !isInPlay(card->myPair))
|
||||||
|
{
|
||||||
|
card->myPair->myPair = NULL;
|
||||||
|
card->myPair = NULL;
|
||||||
|
}
|
||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
//Remove auras that don't have a valid target anymore//
|
//Remove auras that don't have a valid target anymore//
|
||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
|
|||||||
@@ -910,6 +910,13 @@ 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
|
||||||
|
found = s.find("soulbondrule");
|
||||||
|
if(found != string::npos)
|
||||||
|
{
|
||||||
|
observer->addObserver(NEW MTGSoulbondRule(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)
|
||||||
@@ -1625,6 +1632,17 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//soulbond lord style ability.
|
||||||
|
found = s.find("soulbond ");
|
||||||
|
if (found != string::npos)
|
||||||
|
{
|
||||||
|
string s1 = s.substr(found + 9);
|
||||||
|
MTGAbility * a = parseMagicLine(s1, id, spell, card, false, activated);
|
||||||
|
if(a)
|
||||||
|
return NEW APaired(observer,id, card,card->myPair,a);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!activated && tc)
|
if (!activated && tc)
|
||||||
{
|
{
|
||||||
MTGAbility * a = parseMagicLine(sWithoutTc, id, spell, card);
|
MTGAbility * a = parseMagicLine(sWithoutTc, id, spell, card);
|
||||||
|
|||||||
@@ -169,6 +169,7 @@ void MTGCardInstance::initMTGCI()
|
|||||||
isAttacking = NULL;
|
isAttacking = NULL;
|
||||||
storedCard = NULL;
|
storedCard = NULL;
|
||||||
storedSourceCard = NULL;
|
storedSourceCard = NULL;
|
||||||
|
myPair = NULL;
|
||||||
|
|
||||||
for (int i = 0; i < ManaCost::MANA_PAID_WITH_RETRACE +1; i++)
|
for (int i = 0; i < ManaCost::MANA_PAID_WITH_RETRACE +1; i++)
|
||||||
alternateCostPaid[i] = 0;
|
alternateCostPaid[i] = 0;
|
||||||
|
|||||||
@@ -128,7 +128,8 @@ const char* Constants::MTGBasicAbilities[] = {
|
|||||||
"notapability",
|
"notapability",
|
||||||
"nomanaability",
|
"nomanaability",
|
||||||
"onlymanaability",
|
"onlymanaability",
|
||||||
"poisondamager"//deals damage to players as poison counters.
|
"poisondamager",//deals damage to players as poison counters.
|
||||||
|
"soulbond"
|
||||||
};
|
};
|
||||||
|
|
||||||
map<string,int> Constants::MTGBasicAbilitiesMap;
|
map<string,int> Constants::MTGBasicAbilitiesMap;
|
||||||
|
|||||||
@@ -1981,6 +1981,114 @@ HUDDisplay * HUDDisplay::clone() const
|
|||||||
return NEW HUDDisplay(*this);
|
return NEW HUDDisplay(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* soulbond */
|
||||||
|
MTGSoulbondRule::MTGSoulbondRule(GameObserver* observer, int _id) :
|
||||||
|
PermanentAbility(observer, _id)
|
||||||
|
{
|
||||||
|
tcb = NULL;
|
||||||
|
pairAbility = NULL;
|
||||||
|
targetAbility = NULL;
|
||||||
|
mod = NULL;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
int MTGSoulbondRule::receiveEvent(WEvent * event)
|
||||||
|
{
|
||||||
|
if (event->type == WEvent::CHANGE_ZONE)
|
||||||
|
{
|
||||||
|
WEventZoneChange * e = (WEventZoneChange *) event;
|
||||||
|
MTGCardInstance * card = e->card;
|
||||||
|
if (!card || !card->isCreature()) return 0;
|
||||||
|
int ok = 0;
|
||||||
|
if(card->basicAbilities[(int)Constants::soulbond] || soulbonders.size())
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
Player * p = game->players[i];
|
||||||
|
if (e->to == p->game->inPlay)
|
||||||
|
{
|
||||||
|
ok = 1;
|
||||||
|
if(card->basicAbilities[(int)Constants::soulbond])
|
||||||
|
soulbonders.push_back(e->card);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!soulbonders.size())
|
||||||
|
ok = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MTGCardInstance * pairable = NULL;
|
||||||
|
for(unsigned int k = 0;k < soulbonders.size();k++)
|
||||||
|
{
|
||||||
|
MTGCardInstance * check = soulbonders[k];
|
||||||
|
if(check->controller() == e->card->controller())
|
||||||
|
{
|
||||||
|
if(!check->myPair)
|
||||||
|
{
|
||||||
|
if(check != card)
|
||||||
|
pairable = check;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MTGInPlay * zone = check->controller()->game->battlefield;
|
||||||
|
for(unsigned int d = 0;d < zone->cards.size();++d)
|
||||||
|
{
|
||||||
|
if(zone->cards[d]->isCreature() && !zone->cards[d]->myPair && zone->cards[d] != check)
|
||||||
|
{
|
||||||
|
pairable = check;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if(!pairable)
|
||||||
|
ok = 0;
|
||||||
|
}
|
||||||
|
if (!ok)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
Player * p = game->players[i];
|
||||||
|
if (e->to == p->game->inPlay)
|
||||||
|
{
|
||||||
|
TargetChooserFactory tf(card->getObserver());
|
||||||
|
tcb = tf.createTargetChooser("pairable",card);
|
||||||
|
tcb->targetter = NULL;
|
||||||
|
pairAbility = NEW PairCard(game, game->mLayers->actionLayer()->getMaxId(), card,NULL);
|
||||||
|
targetAbility = NEW GenericTargetAbility(game, "Pair Creature","",game->mLayers->actionLayer()->getMaxId(), card,tcb,pairAbility);
|
||||||
|
targetAbility1 = NEW MayAbility(game,game->mLayers->actionLayer()->getMaxId(),targetAbility,card,false);
|
||||||
|
activatePairing = NEW GenericAddToGame(game, game->mLayers->actionLayer()->getMaxId(), card,NULL,targetAbility1);
|
||||||
|
//this next line is ugly, but fixes a long running memleak which seems to be unfixable while maintaining the same order of activation.
|
||||||
|
game->mLayers->actionLayer()->garbage.push_back(activatePairing);
|
||||||
|
activatePairing->fireAbility();
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ostream& MTGSoulbondRule::toString(ostream& out) const
|
||||||
|
{
|
||||||
|
out << "MTGSoulbondRule ::: (";
|
||||||
|
return MTGAbility::toString(out) << ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
MTGSoulbondRule * MTGSoulbondRule::clone() const
|
||||||
|
{
|
||||||
|
return NEW MTGSoulbondRule(*this);
|
||||||
|
}
|
||||||
|
MTGSoulbondRule::~MTGSoulbondRule()
|
||||||
|
{
|
||||||
|
for(size_t k = pairing.size()-1;k > 0; k--)
|
||||||
|
{
|
||||||
|
//SAFE_DELETE(pairing[k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
/* Persist */
|
/* Persist */
|
||||||
MTGPersistRule::MTGPersistRule(GameObserver* observer, int _id) :
|
MTGPersistRule::MTGPersistRule(GameObserver* observer, int _id) :
|
||||||
PermanentAbility(observer, _id)
|
PermanentAbility(observer, _id)
|
||||||
|
|||||||
@@ -25,6 +25,13 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
|
|||||||
return NEW BlockableChooser(observer, card, maxtargets);
|
return NEW BlockableChooser(observer, card, maxtargets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
found = s.find("pairable");
|
||||||
|
if (found != string::npos)
|
||||||
|
{
|
||||||
|
int maxtargets = 1;
|
||||||
|
return NEW pairableChooser(observer, card, maxtargets);
|
||||||
|
}
|
||||||
|
|
||||||
found = s.find("mytgt");
|
found = s.find("mytgt");
|
||||||
if (found == 0)
|
if (found == 0)
|
||||||
{
|
{
|
||||||
@@ -1548,6 +1555,40 @@ bool BlockableChooser::equals(TargetChooser * tc)
|
|||||||
return TypeTargetChooser::equals(tc);
|
return TypeTargetChooser::equals(tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*display cards pairable by source */
|
||||||
|
bool pairableChooser::canTarget(Targetable * target,bool withoutProtections)
|
||||||
|
{
|
||||||
|
if (MTGCardInstance * card = dynamic_cast<MTGCardInstance*>(target))
|
||||||
|
{
|
||||||
|
if(card->myPair || card == source)
|
||||||
|
return false;
|
||||||
|
if(!card->isCreature() || !card->isInPlay(observer))
|
||||||
|
return false;
|
||||||
|
if(card->controller() != source->controller())
|
||||||
|
return false;
|
||||||
|
if(!card->has(Constants::soulbond) && !source->has(Constants::soulbond))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pairableChooser* pairableChooser::clone() const
|
||||||
|
{
|
||||||
|
pairableChooser * a = NEW pairableChooser(*this);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pairableChooser::equals(TargetChooser * tc)
|
||||||
|
{
|
||||||
|
|
||||||
|
pairableChooser * dtc = dynamic_cast<pairableChooser *> (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)
|
||||||
|
|||||||
Reference in New Issue
Block a user