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:
omegablast2002@yahoo.com
2012-07-16 14:59:46 +00:00
parent 7024d195fa
commit 0dbcd86b89
12 changed files with 407 additions and 12 deletions
+32 -2
View File
@@ -3161,9 +3161,9 @@ int MenuAbility::resolve()
const char * MenuAbility::getMenuText()
{
if(abilities.size())
if((abilities.size() > 1 && must)||(abilities.size() > 2 && !must))
return "choose one";
return ability->getMenuText();
return "Action";
}
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.
}
if(!mClone)
{
if (source->controller() == game->isInterrupting)
game->mLayers->stackLayer()->cancelInterruptOffer(ActionStack::DONT_INTERRUPT, false);
return 0;
}
mClone->target = abilities[choice]->target;
mClone->oneShot = true;
mClone->forceDestroy = 1;
@@ -4853,6 +4857,32 @@ AABlock * AABlock::clone() const
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)
AAConnect::AAConnect(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target, ManaCost * _cost) :
+5
View File
@@ -598,6 +598,11 @@ void GameObserver::gameStateBasedEffects()
card->mPropertiesChangedSinceLastUpdate = false;
if(card->hasType(Subtypes::TYPE_PLANESWALKER) && (!card->counters||!card->counters->hasCounter("loyalty",0,0)))
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//
///////////////////////////////////////////////////////
+18
View File
@@ -910,6 +910,13 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
observer->addObserver(NEW MTGBlockRule(observer, -1));
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.
found = s.find("combattriggerrule");
if(found != string::npos)
@@ -1625,6 +1632,17 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
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)
{
MTGAbility * a = parseMagicLine(sWithoutTc, id, spell, card);
+1
View File
@@ -169,6 +169,7 @@ void MTGCardInstance::initMTGCI()
isAttacking = NULL;
storedCard = NULL;
storedSourceCard = NULL;
myPair = NULL;
for (int i = 0; i < ManaCost::MANA_PAID_WITH_RETRACE +1; i++)
alternateCostPaid[i] = 0;
+2 -1
View File
@@ -128,7 +128,8 @@ const char* Constants::MTGBasicAbilities[] = {
"notapability",
"nomanaability",
"onlymanaability",
"poisondamager"//deals damage to players as poison counters.
"poisondamager",//deals damage to players as poison counters.
"soulbond"
};
map<string,int> Constants::MTGBasicAbilitiesMap;
+108
View File
@@ -1981,6 +1981,114 @@ HUDDisplay * HUDDisplay::clone() const
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 */
MTGPersistRule::MTGPersistRule(GameObserver* observer, int _id) :
PermanentAbility(observer, _id)
+41
View File
@@ -25,6 +25,13 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
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");
if (found == 0)
{
@@ -1548,6 +1555,40 @@ bool BlockableChooser::equals(TargetChooser * 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 */
bool ProliferateChooser::canTarget(Targetable * target,bool withoutProtections)