From d6a0b0493041924f6ef93d874b30268d80b57bf4 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Mon, 13 Mar 2017 13:32:43 +0800 Subject: [PATCH 1/3] Partial fix for Cards with Bestow missing was to seperate the mode as aura enchantment or enchantment creature when cast and update the cost --- projects/mtg/bin/Res/sets/primitives/mtg.txt | 15 ++-- projects/mtg/include/AllAbilities.h | 17 +++++ projects/mtg/include/MTGCardInstance.h | 2 +- projects/mtg/include/Player.h | 2 + projects/mtg/src/AllAbilities.cpp | 74 ++++++++++++++++++++ projects/mtg/src/GameObserver.cpp | 6 +- projects/mtg/src/MTGAbility.cpp | 20 ++++++ projects/mtg/src/MTGCardInstance.cpp | 9 ++- projects/mtg/src/MTGRules.cpp | 6 +- projects/mtg/src/Player.cpp | 4 ++ 10 files changed, 142 insertions(+), 13 deletions(-) diff --git a/projects/mtg/bin/Res/sets/primitives/mtg.txt b/projects/mtg/bin/Res/sets/primitives/mtg.txt index b2cc56edf..8a1145d40 100644 --- a/projects/mtg/bin/Res/sets/primitives/mtg.txt +++ b/projects/mtg/bin/Res/sets/primitives/mtg.txt @@ -48698,11 +48698,11 @@ type=Legendary Land [card] name=Gods Willing target=creature|mybattlefield -auto=choice name(green) transforms((,newability[protection from green],newability[scry:1 scrycore delayed dontshow donothing scrycoreend scryend])) ueot -auto=choice name(red) transforms((,newability[protection from red],newability[scry:1 scrycore delayed dontshow donothing scrycoreend scryend])) ueot -auto=choice name(blue) transforms((,newability[protection from blue],newability[scry:1 scrycore delayed dontshow donothing scrycoreend scryend])) ueot -auto=choice name(black) transforms((,newability[protection from black],newability[scry:1 scrycore delayed dontshow donothing scrycoreend scryend])) ueot -auto=choice name(white) transforms((,newability[protection from white],newability[scry:1 scrycore delayed dontshow donothing scrycoreend scryend])) ueot +auto=choice name(green) transforms((,newability[protection from green],newability[choice scry:1 scrycore delayed dontshow donothing scrycoreend scryend])) ueot +auto=choice name(red) transforms((,newability[protection from red],newability[choice scry:1 scrycore delayed dontshow donothing scrycoreend scryend])) ueot +auto=choice name(blue) transforms((,newability[protection from blue],newability[choice scry:1 scrycore delayed dontshow donothing scrycoreend scryend])) ueot +auto=choice name(black) transforms((,newability[protection from black],newability[choice scry:1 scrycore delayed dontshow donothing scrycoreend scryend])) ueot +auto=choice name(white) transforms((,newability[protection from white],newability[choice scry:1 scrycore delayed dontshow donothing scrycoreend scryend])) ueot text=Target creature you control gains protection from the color of your choice until end of turn. Scry 1. (Look at the top card of your library. You may put that card on the bottom of your library.) mana={W} type=Instant @@ -54244,6 +54244,7 @@ toughness=3 [card] name=Hero of Iroas auto=lord(aura|mycastingzone) altercost(colorless,-1) +auto=modbenchant(colorless:-1) controller auto=@targeted(this) from(*[instant;sorcery;enchantment]|mycastingzone):counter(1/1,1) text=Aura spells you cast cost 1 less to cast. -- Heroic -- Whenever you cast a spell that targets Hero of Iroas, put a +1/+1 counter on Hero of Iroas. mana={1}{W} @@ -80336,7 +80337,7 @@ subtype=Nissa name=Nissa, Vastwood Seer aicode=activate target(forest[basic]|mylibrary) moveto(myhand) auto=name(search card) Reveal:type:*:mylibrary revealzone(mylibrary) optionone name(choose card) target(<1>forest[basic]|reveal) transforms((,newability[all(other *|reveal) moveto(mylibrary) and!(shuffle)!],newability[moveto(myhand)])) optiononeend optiontwo name(shuffle) bottomoflibrary target(<1>*|reveal) and!( all(*|reveal) bottomoflibrary and!(shuffle)! )! optiontwoend revealend -auto=@movedto(land|mybattlefield):moveto(exile) and!( moveto(ownerbattlefield) and!(flip(Nissa, Sage Animist) && counter(0/0,3,loyalty))! )! +auto=@movedto(land|mybattlefield) restriction{type(land|mybattlefield)~morethan~6}:moveto(exile) and!( moveto(ownerbattlefield) and!(flip(Nissa, Sage Animist) && counter(0/0,3,loyalty))! )! text=When Nissa, Vastwood Seer enters the battlefield, you may search your library for a basic Forest card, reveal it, put it into your hand, then shuffle your library. -- Whenever a land enters the battlefield under your control, if you control seven or more lands, exile Nissa, then return her to the battlefield transformed under her owner's control. mana={2}{G} type=Legendary Creature @@ -92319,7 +92320,7 @@ toughness=6 [/card] [card] name=Raven Familiar -abilities=hiddenface +abilities=flying,hiddenface auto=upcost[{2}{u};next upkeep] sacrifice aicode=activate transforms((,newability[moveto(myhand) all(*[zpos=1]|mylibrary) && bottomoflibrary all(*[zpos<=2]|mylibrary)])) ueot auto=reveal:3 optionone name(Get a card) target(<1>*|reveal) moveto(myhand) optiononeend optiontwo name(put on bottom) target(<3>*|reveal) bottomoflibrary optiontwoend revealend diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index 136e62143..fafcad398 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -4539,6 +4539,23 @@ public: } }; +//Extra for Bestow cards +class AAuraIncreaseReduce: public AbilityTP +{ +public: + MTGCardInstance * manaReducer; + int amount; + int color; + AAuraIncreaseReduce(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, int amount, int color, int who = TargetChooser::UNSET); + int addToGame(); + int destroy(); + int testDestroy(); + const string getMenuText(); + AAuraIncreaseReduce * clone() const; + //~AAuraIncreaseReduce(); + +}; + //Modify Hand class AModifyHand: public AbilityTP { diff --git a/projects/mtg/include/MTGCardInstance.h b/projects/mtg/include/MTGCardInstance.h index afaa2e261..ca19ab858 100644 --- a/projects/mtg/include/MTGCardInstance.h +++ b/projects/mtg/include/MTGCardInstance.h @@ -276,7 +276,7 @@ public: int forcedBorderA; int forcedBorderB; int myconvertedcost; - ManaCost * computeNewCost(MTGCardInstance * card,ManaCost * oldCost, ManaCost * refCost,bool noTrinisphere = false); + ManaCost * computeNewCost(MTGCardInstance * card,ManaCost * oldCost, ManaCost * refCost,bool noTrinisphere = false, bool bestow = false); int countTrini; bool anymanareplacement; vectorimprintedCards; diff --git a/projects/mtg/include/Player.h b/projects/mtg/include/Player.h index b69619f2c..9369ea79a 100644 --- a/projects/mtg/include/Player.h +++ b/projects/mtg/include/Player.h @@ -87,6 +87,8 @@ public: bool DeadLifeState(bool check = false); ManaCost * doesntEmpty; ManaCost * poolDoesntEmpty; + ManaCost * AuraIncreased; + ManaCost * AuraReduced; void cleanupPhase(); virtual int Act(float) { diff --git a/projects/mtg/src/AllAbilities.cpp b/projects/mtg/src/AllAbilities.cpp index a15499006..89b6a2b15 100644 --- a/projects/mtg/src/AllAbilities.cpp +++ b/projects/mtg/src/AllAbilities.cpp @@ -4044,6 +4044,80 @@ AALifer * AALifer::clone() const return NEW AALifer(*this); } +//Extra for Bestow ... partial fix since there's no update when react to click for bestow cards... +//There should be no problem if the bestow cards has chosen mode then update its bestow code on react to click but +//I cant find alternate way... This Ability is general for enchantments since aura is an enchantment type however +//it can't target card specific attributes... This one adds on the players side... +AAuraIncreaseReduce::AAuraIncreaseReduce(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, int amount, int color, int who) : + AbilityTP(observer, _id, _source, _target, who), amount(amount), color(color) +{ + manaReducer = source; +} + +int AAuraIncreaseReduce::addToGame() +{ + Damageable * _target = (Damageable *) getTarget(); + Player * p = getPlayerFromDamageable(_target); + + if (!p) + return 0; + + if (amount > 0) + { + p->AuraIncreased->add(color,amount); + } + else + { + p->AuraReduced->add(color,abs(amount)); + } + + return MTGAbility::addToGame(); +} + +int AAuraIncreaseReduce::destroy() +{ + Damageable * _target = (Damageable *) getTarget(); + Player * p = getPlayerFromDamageable(_target); + + if (!p) + return 0; + + if(!this->manaReducer->isInPlay(game)) + { + if (amount > 0) + { + p->AuraIncreased->remove(color,amount); + } + else + { + p->AuraReduced->remove(color,abs(amount)); + } + return MTGAbility::testDestroy(); + } + + return 0; +} + +int AAuraIncreaseReduce::testDestroy() +{ + if(!this->manaReducer->isInPlay(game)) + { + return MTGAbility::testDestroy(); + } + + return 0; +} + +const string AAuraIncreaseReduce::getMenuText() +{ + return "Aura Increaser/Reducer"; +} + +AAuraIncreaseReduce * AAuraIncreaseReduce::clone() const +{ + return NEW AAuraIncreaseReduce(*this); +} + //players modify hand size AModifyHand::AModifyHand(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, string hand, int who) : AbilityTP(observer, _id, _source, _target, who), hand(hand) diff --git a/projects/mtg/src/GameObserver.cpp b/projects/mtg/src/GameObserver.cpp index a7809ce97..fdb9b1864 100644 --- a/projects/mtg/src/GameObserver.cpp +++ b/projects/mtg/src/GameObserver.cpp @@ -1244,6 +1244,8 @@ void GameObserver::Affinity() card->has(Constants::AFFINITYPLAINS) || card->has(Constants::AFFINITYSWAMP) || card->has(Constants::CONDUITED) || + card->controller()->AuraIncreased->getConvertedCost() || + card->controller()->AuraReduced->getConvertedCost() || card->getIncreasedManaCost()->getConvertedCost() || card->getReducedManaCost()->getConvertedCost() || NewAffinityFound) @@ -1272,10 +1274,10 @@ void GameObserver::Affinity() SAFE_DELETE(newCost); } if (card->getManaCost()->getBestow()) - { + {//NOTE: there should be a limitation when the spell is cast with bestow its not both creature and aura... card->getManaCost()->getBestow()->resetCosts(); ManaCost * newCost = NEW ManaCost(); - newCost->changeCostTo(card->computeNewCost(card, card->getManaCost()->getBestow(), card->model->data->getManaCost()->getBestow())); + newCost->changeCostTo(card->computeNewCost(card, card->getManaCost()->getBestow(), card->model->data->getManaCost()->getBestow(), false, true)); card->getManaCost()->getBestow()->changeCostTo(newCost); SAFE_DELETE(newCost); } diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index c60f27e76..5e057a329 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -3196,6 +3196,26 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG return a; } + //Extra for Bestow + vector splitAuraIncreaseReduce = parseBetween(s, "modbenchant(", ")", true); + if(splitAuraIncreaseReduce.size()) + { + if(splitAuraIncreaseReduce[1].size()) + { + Damageable * t = spell ? spell->getNextDamageableTarget() : NULL; + vector ccParameters = split( splitAuraIncreaseReduce[1], ':'); + int amount = atoi(ccParameters[1].c_str()); + int color = Constants::GetColorStringIndex(ccParameters[0]); + if(ccParameters[0] == "colorless") + color = 0; + if(ccParameters[0].size() && ccParameters[1].size()) + { + MTGAbility * a = NEW AAuraIncreaseReduce(observer, id, card, t, amount, color, who); + return a; + } + } + } + //set hand size vector splitSetHand = parseBetween(s, "sethand:", " ", false); if (splitSetHand.size()) diff --git a/projects/mtg/src/MTGCardInstance.cpp b/projects/mtg/src/MTGCardInstance.cpp index 4aac767b7..e1ec1a352 100644 --- a/projects/mtg/src/MTGCardInstance.cpp +++ b/projects/mtg/src/MTGCardInstance.cpp @@ -1059,7 +1059,7 @@ JQuadPtr MTGCardInstance::getIcon() return WResourceManager::Instance()->RetrieveCard(this, CACHE_THUMB); } -ManaCost * MTGCardInstance::computeNewCost(MTGCardInstance * card,ManaCost * Cost, ManaCost * Data, bool noTrinisphere) +ManaCost * MTGCardInstance::computeNewCost(MTGCardInstance * card,ManaCost * Cost, ManaCost * Data, bool noTrinisphere, bool bestow) { int color = 0; string type = ""; @@ -1074,10 +1074,13 @@ ManaCost * MTGCardInstance::computeNewCost(MTGCardInstance * card,ManaCost * Cos Cost->extraCosts->costs[i]->setSource(card); } } - if (card->getIncreasedManaCost()->getConvertedCost() || card->getReducedManaCost()->getConvertedCost()) + if (card->getIncreasedManaCost()->getConvertedCost() || card->getReducedManaCost()->getConvertedCost() + || card->controller()->AuraReduced->getConvertedCost() || card->controller()->AuraIncreased->getConvertedCost()) {//start1 if (card->getIncreasedManaCost()->getConvertedCost()) original->add(card->getIncreasedManaCost()); + if(bestow && card->controller()->AuraIncreased->getConvertedCost()) + original->add(card->controller()->AuraIncreased); //before removing get the diff for excess if(card->getReducedManaCost()->getConvertedCost()) { @@ -1093,6 +1096,8 @@ ManaCost * MTGCardInstance::computeNewCost(MTGCardInstance * card,ManaCost * Cos //apply reduced if (card->getReducedManaCost()->getConvertedCost()) original->remove(card->getReducedManaCost()); + if(bestow && card->controller()->AuraReduced->getConvertedCost()) + original->remove(card->controller()->AuraReduced); //try to reduce hybrid if (excess->getConvertedCost()) { diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index eb78a8027..8c8fb423f 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -939,7 +939,11 @@ int MTGAlternativeCostRule::reactToClick(MTGCardInstance * card, ManaCost *alter copy->alternateCostPaid[alternateCostType] = 1; game->mLayers->stackLayer()->addSpell(copy, game->targetChooser, spellCost, alternateCostType, 0); game->targetChooser = NULL; - + if(alternateCostType == ManaCost::MANA_PAID_WITH_BESTOW) + { + copy->removeType("creature"); + copy->addType("aura"); + } if (card->has(Constants::STORM)) { int storm = player->game->stack->seenThisTurn("*", Constants::CAST_ALL) + player->opponent()->game->stack->seenThisTurn("*", Constants::CAST_ALL); diff --git a/projects/mtg/src/Player.cpp b/projects/mtg/src/Player.cpp index 29986408c..42ca1b60e 100644 --- a/projects/mtg/src/Player.cpp +++ b/projects/mtg/src/Player.cpp @@ -49,6 +49,8 @@ Player::Player(GameObserver *observer, string file, string fileSmall, MTGDeck * prowledTypes.clear(); doesntEmpty = NEW ManaCost(); poolDoesntEmpty = NEW ManaCost(); + AuraIncreased = NEW ManaCost(); + AuraReduced = NEW ManaCost(); if (deck != NULL) { game = NEW MTGPlayerCards(deck); @@ -82,6 +84,8 @@ Player::~Player() SAFE_DELETE(manaPool); SAFE_DELETE(doesntEmpty); SAFE_DELETE(poolDoesntEmpty); + SAFE_DELETE(AuraIncreased); + SAFE_DELETE(AuraReduced); SAFE_DELETE(game); if(mAvatarTex && observer->getResourceManager()) observer->getResourceManager()->Release(mAvatarTex); From bef1f6d8b80fb54e5e6b27c8c081ed5a74490d29 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Mon, 13 Mar 2017 18:16:22 +0800 Subject: [PATCH 2/3] aura parent --- projects/mtg/bin/Res/sets/primitives/mtg.txt | 4 +- projects/mtg/include/MTGCardInstance.h | 1 + projects/mtg/include/TargetChooser.h | 20 ++++++++ projects/mtg/src/GameObserver.cpp | 50 +++++++++----------- projects/mtg/src/MTGCardInstance.cpp | 1 + projects/mtg/src/TargetChooser.cpp | 46 ++++++++++++++++++ 6 files changed, 93 insertions(+), 29 deletions(-) diff --git a/projects/mtg/bin/Res/sets/primitives/mtg.txt b/projects/mtg/bin/Res/sets/primitives/mtg.txt index 8a1145d40..bcc0ab4a7 100644 --- a/projects/mtg/bin/Res/sets/primitives/mtg.txt +++ b/projects/mtg/bin/Res/sets/primitives/mtg.txt @@ -56038,7 +56038,7 @@ toughness=3 [card] name=Hubris target=creature|battlefield -auto=transforms((,newability[moveto(ownerhand) all(children[aura]],newability[moveto(ownerhand)])) forever +auto=transforms((,newability[moveto(ownerhand) all(mychild)],newability[moveto(ownerhand)])) forever text=Return target creature and all Auras attached to it to their owners' hands. mana={1}{U} type=Instant @@ -114622,7 +114622,7 @@ type=Instant [/card] [card] name=Street Sweeper -auto=@combat(attacking) source(this) restriction{type(land[enchanted]|battlefield)~morethan~0}:name(destroy auras) target(land[enchanted]|battlefield) transforms((,newability[destroy all(children[aura])])) +auto=@combat(attacking) source(this) restriction{type(land[enchanted]|battlefield)~morethan~0}:name(destroy auras) target(land[enchanted]|battlefield) transforms((,newability[destroy all(mychild)])) text=Whenever Street Sweeper attacks, destroy all Auras attached to target land. mana={6} type=Artifact Creature diff --git a/projects/mtg/include/MTGCardInstance.h b/projects/mtg/include/MTGCardInstance.h index ca19ab858..38a64ebb7 100644 --- a/projects/mtg/include/MTGCardInstance.h +++ b/projects/mtg/include/MTGCardInstance.h @@ -128,6 +128,7 @@ public: MTGCardInstance * tokCard; MTGCardInstance * previous; MTGCardInstance * next; + MTGCardInstance * auraParent; MTGAbility * TokenAndAbility; MTGAbility * GrantedAndAbility; int doDamageTest; diff --git a/projects/mtg/include/TargetChooser.h b/projects/mtg/include/TargetChooser.h index 497b2d5ae..1313a3b90 100644 --- a/projects/mtg/include/TargetChooser.h +++ b/projects/mtg/include/TargetChooser.h @@ -357,4 +357,24 @@ public: virtual bool equals(TargetChooser * tc); ~ParentChildChooser(); }; + +class ChildrenChooser: public TypeTargetChooser +{ +public: + bool withoutProtections; + ChildrenChooser(GameObserver *observer, int * _zones, int _nbzones, MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false, bool targetMin = false) : + TypeTargetChooser(observer, "*",_zones, _nbzones, card, _maxtargets, other, targetMin) + { + } + ; + ChildrenChooser(GameObserver *observer, MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false,bool targetMin = false) : + TypeTargetChooser(observer, "*", card, _maxtargets, other,targetMin) + { + } + ; + virtual bool canTarget(Targetable * target, bool withoutProtections = false); + virtual ChildrenChooser * clone() const; + virtual bool equals(TargetChooser * tc); + ~ChildrenChooser(); +}; #endif diff --git a/projects/mtg/src/GameObserver.cpp b/projects/mtg/src/GameObserver.cpp index fdb9b1864..2f311cd7e 100644 --- a/projects/mtg/src/GameObserver.cpp +++ b/projects/mtg/src/GameObserver.cpp @@ -1142,6 +1142,7 @@ void GameObserver::enchantmentStatus() { card->target->enchanted = true; card->target->auras += 1; + card->auraParent = card->target; } } } @@ -1161,6 +1162,7 @@ void GameObserver::Affinity() if (!card) continue; + bool checkAuraP = false; /////////////////////////// //reset extracost shadows// /////////////////////////// @@ -1185,6 +1187,10 @@ void GameObserver::Affinity() ///we handle trisnisphere seperately because its a desaster. if(card->getManaCost())//make sure we check, abiliy$!/token dont have a mancost object. { + if (card->controller()->AuraIncreased->getConvertedCost() || card->controller()->AuraReduced->getConvertedCost()) + if(card->model->data->getManaCost()->getBestow()) + checkAuraP = true; + //change cost to colorless for anytypeofmana ability if(card->has(Constants::ANYTYPEOFMANA)) { @@ -1244,11 +1250,9 @@ void GameObserver::Affinity() card->has(Constants::AFFINITYPLAINS) || card->has(Constants::AFFINITYSWAMP) || card->has(Constants::CONDUITED) || - card->controller()->AuraIncreased->getConvertedCost() || - card->controller()->AuraReduced->getConvertedCost() || card->getIncreasedManaCost()->getConvertedCost() || card->getReducedManaCost()->getConvertedCost() || - NewAffinityFound) + NewAffinityFound || checkAuraP) && AffinityNeedsUpdate ) @@ -1260,60 +1264,52 @@ void GameObserver::Affinity() //only do any of the following if a card with the stated ability is in your hand. //kicker is an addon to normal cost, suspend is not casting. add cost as needed EXACTLY as seen below. card->getManaCost()->resetCosts(); - ManaCost *newCost = NEW ManaCost(); - newCost->changeCostTo(card->computeNewCost(card, card->getManaCost(), card->model->data->getManaCost())); - + ManaCost *newCost = NEW ManaCost(card->computeNewCost(card, card->getManaCost(), card->model->data->getManaCost())); card->getManaCost()->changeCostTo(newCost); SAFE_DELETE(newCost); if (card->getManaCost()->getAlternative()) { card->getManaCost()->getAlternative()->resetCosts(); - ManaCost * newCost = NEW ManaCost(); - newCost->changeCostTo(card->computeNewCost(card, card->getManaCost()->getAlternative(), card->model->data->getManaCost()->getAlternative())); + ManaCost *newCost = NEW ManaCost(card->computeNewCost(card, card->getManaCost()->getAlternative(), card->model->data->getManaCost()->getAlternative())); card->getManaCost()->getAlternative()->changeCostTo(newCost); SAFE_DELETE(newCost); } if (card->getManaCost()->getBestow()) - {//NOTE: there should be a limitation when the spell is cast with bestow its not both creature and aura... - card->getManaCost()->getBestow()->resetCosts(); - ManaCost * newCost = NEW ManaCost(); - newCost->changeCostTo(card->computeNewCost(card, card->getManaCost()->getBestow(), card->model->data->getManaCost()->getBestow(), false, true)); - card->getManaCost()->getBestow()->changeCostTo(newCost); - SAFE_DELETE(newCost); - } - if (card->getManaCost()->getRetrace()) { - card->getManaCost()->getRetrace()->resetCosts(); - ManaCost * newCost = NEW ManaCost(); - newCost->changeCostTo(card->computeNewCost(card, card->getManaCost()->getRetrace(), card->model->data->getManaCost()->getRetrace())); - card->getManaCost()->getRetrace()->changeCostTo(newCost); + card->getManaCost()->getBestow()->resetCosts(); + ManaCost *newCost = NEW ManaCost(card->computeNewCost(card, card->getManaCost()->getBestow(), card->model->data->getManaCost()->getBestow(),false,true)); + card->getManaCost()->getBestow()->changeCostTo(newCost); SAFE_DELETE(newCost); } if (card->getManaCost()->getBuyback()) { card->getManaCost()->getBuyback()->resetCosts(); - ManaCost * newCost = NEW ManaCost(); - newCost->changeCostTo(card->computeNewCost(card, card->getManaCost()->getBuyback(), card->model->data->getManaCost()->getBuyback())); + ManaCost *newCost = NEW ManaCost(card->computeNewCost(card, card->getManaCost()->getBuyback(), card->model->data->getManaCost()->getBuyback())); card->getManaCost()->getBuyback()->changeCostTo(newCost); SAFE_DELETE(newCost); } if (card->getManaCost()->getFlashback()) { card->getManaCost()->getFlashback()->resetCosts(); - ManaCost * newCost = NEW ManaCost(); - newCost->changeCostTo(card->computeNewCost(card, card->getManaCost()->getFlashback(), card->model->data->getManaCost()->getFlashback())); + ManaCost *newCost = NEW ManaCost(card->computeNewCost(card, card->getManaCost()->getFlashback(), card->model->data->getManaCost()->getFlashback())); card->getManaCost()->getFlashback()->changeCostTo(newCost); SAFE_DELETE(newCost); } if (card->getManaCost()->getMorph()) { card->getManaCost()->getMorph()->resetCosts(); - ManaCost * newCost = NEW ManaCost(); - newCost->changeCostTo(card->computeNewCost(card, card->getManaCost()->getMorph(), card->model->data->getManaCost()->getMorph())); + ManaCost *newCost = NEW ManaCost(card->computeNewCost(card, card->getManaCost()->getMorph(), card->model->data->getManaCost()->getMorph())); card->getManaCost()->getMorph()->changeCostTo(newCost); SAFE_DELETE(newCost); } - + if (card->getManaCost()->getRetrace()) + { + card->getManaCost()->getRetrace()->resetCosts(); + ManaCost *newCost = NEW ManaCost(card->computeNewCost(card, card->getManaCost()->getRetrace(), card->model->data->getManaCost()->getRetrace())); + card->getManaCost()->getRetrace()->changeCostTo(newCost); + SAFE_DELETE(newCost); + } + }//end } } diff --git a/projects/mtg/src/MTGCardInstance.cpp b/projects/mtg/src/MTGCardInstance.cpp index e1ec1a352..754446146 100644 --- a/projects/mtg/src/MTGCardInstance.cpp +++ b/projects/mtg/src/MTGCardInstance.cpp @@ -303,6 +303,7 @@ void MTGCardInstance::initMTGCI() tokCard = NULL; previous = NULL; next = NULL; + auraParent = NULL; TokenAndAbility = NULL; GrantedAndAbility = NULL; lastController = NULL; diff --git a/projects/mtg/src/TargetChooser.cpp b/projects/mtg/src/TargetChooser.cpp index 2c9ae424e..91c966c1d 100644 --- a/projects/mtg/src/TargetChooser.cpp +++ b/projects/mtg/src/TargetChooser.cpp @@ -48,6 +48,13 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta return NEW CardTargetChooser(observer, target, card); }; + found = s.find("mychild"); + if (found == 0) + { + int maxtargets = 1; + return NEW ChildrenChooser(observer, card, maxtargets); + }; + found = s.find("targetedplayer"); if (found == 0) { @@ -2015,3 +2022,42 @@ ParentChildChooser::~ParentChildChooser() { SAFE_DELETE(deeperTargeting); } + +//child only +bool ChildrenChooser::canTarget(Targetable * target,bool withoutProtections) +{ + if (MTGCardInstance * card = dynamic_cast(target)) + { + if(card == source) + return false; + if(!card->isInPlay(observer)) + return false; + if(card->auraParent) + { + if(card->auraParent == source) + return true; + } + return false; + } + return false; +} + +ChildrenChooser* ChildrenChooser::clone() const +{ + ChildrenChooser * a = NEW ChildrenChooser(*this); + return a; +} + +bool ChildrenChooser::equals(TargetChooser * tc) +{ + + ChildrenChooser * dtc = dynamic_cast (tc); + if (!dtc) + return false; + + return TypeTargetChooser::equals(tc); +} + +ChildrenChooser::~ChildrenChooser() +{ +} From 0778b13e2b853f9f5134bb33a36f2bf3757ab1a7 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Tue, 14 Mar 2017 03:40:29 +0800 Subject: [PATCH 3/3] Totem Armor --- projects/mtg/bin/Res/sets/primitives/mtg.txt | 131 +++++++++++++++++- .../bin/Res/sets/primitives/unsupported.txt | 84 ----------- projects/mtg/include/AllAbilities.h | 84 +++++++++++ projects/mtg/include/MTGCardInstance.h | 5 +- projects/mtg/include/MTGDefinitions.h | 3 +- projects/mtg/include/TargetChooser.h | 20 +++ projects/mtg/src/AllAbilities.cpp | 12 +- projects/mtg/src/MTGCardInstance.cpp | 92 +++++++++++- projects/mtg/src/MTGDefinitions.cpp | 3 +- projects/mtg/src/MTGRules.cpp | 2 +- projects/mtg/src/TargetChooser.cpp | 47 +++++++ 11 files changed, 389 insertions(+), 94 deletions(-) diff --git a/projects/mtg/bin/Res/sets/primitives/mtg.txt b/projects/mtg/bin/Res/sets/primitives/mtg.txt index bcc0ab4a7..b293b3086 100644 --- a/projects/mtg/bin/Res/sets/primitives/mtg.txt +++ b/projects/mtg/bin/Res/sets/primitives/mtg.txt @@ -10070,6 +10070,17 @@ power=2 toughness=2 [/card] [card] +name=Bear Umbra +abilities=totemarmor +target=creature +auto=teach(creature) 2/2 +auto=teach(creature) transforms((,newability[@combat(attacking) source(this):untap all(land|mybattlefield)])) +text=Enchant creature -- Enchanted creature gets +2/+2 and has "Whenever this creature attacks, untap all lands you control." -- Totem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.) +mana={2}{G}{G} +type=Enchantment +subtype=Aura +[/card] +[card] name=Bearer of Overwhelming Truths auto=@movedto(*[-creature|mystack):1/1 ueot auto=@combatdamaged(player) from(this):token(Clue,Artifact Clue,0/0) and!( transforms((,newability[{S}{2}:draw:1])) forever )! controller @@ -12980,6 +12991,16 @@ power=3 toughness=3 [/card] [card] +name=Boar Umbra +abilities=totemarmor +target=creature +auto=teach(creature) 3/3 +text=Enchant creature -- Enchanted creature gets +3/+3. -- Totem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.) +mana={2}{G} +type=Enchantment +subtype=Aura +[/card] +[card] name=Boartusk Liege abilities=trample auto=lord(other creature[red]|myBattlefield) 1/1 @@ -23206,6 +23227,16 @@ power=6 toughness=6 [/card] [card] +name=Crab Umbra +abilities=totemarmor +target=creature +auto={2}{U}:untap(mytgt) +text=Enchant creature -- {2}{U}: Untap enchanted creature. -- Totem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.) +mana={U} +type=Enchantment +subtype=Aura +[/card] +[card] name=Crabapple Cohort auto=aslongas(other creature[green]|myBattlefield) 1/1 != 0 text=Crabapple Cohort gets +1/+1 as long as you control another green creature. @@ -31510,6 +31541,17 @@ power=1 toughness=3 [/card] [card] +name=Drake Umbra +abilities=totemarmor +target=creature +auto=teach(creature) 3/3 +auto=teach(creature) flying +text=Enchant creature -- Enchanted creature gets +3/+3 and has flying. -- Totem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.) +mana={4}{U} +type=Enchantment +subtype=Aura +[/card] +[card] name=Drake-Skull Cameo auto={T}:Add{U} auto={T}:Add{B} @@ -34000,6 +34042,16 @@ power=2 toughness=2 [/card] [card] +name=Eel Umbra +abilities=flash,totemarmor +target=creature +auto=teach(creature) 1/1 +text=Flash (You may cast this spell any time you could cast an instant.) -- Enchant creature -- Enchanted creature gets +1/+1. -- Totem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.) +mana={1}{U} +type=Enchantment +subtype=Aura +[/card] +[card] name=Eerie Interlude target=creature|mybattlefield auto=(blink) @@ -34180,6 +34232,16 @@ mana={G} type=Enchantment [/card] [card] +name=Eland Umbra +abilities=totemarmor +target=creature +auto=teach(creature) 0/4 +text=Enchant creature -- Enchanted creature gets +0/+4. -- Totem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.) +mana={1}{W} +type=Enchantment +subtype=Aura +[/card] +[card] name=Elbrus, the Binding Blade auto={1}:equip auto=teach(creature) 1/0 @@ -39643,6 +39705,17 @@ power=4 toughness=6 [/card] [card] +name=Felidar Umbra +abilities=totemarmor +target=creature +auto=teach(creature) lifelink +auto={1}{W}:rehook target(creature|mybattlefield) +text=Enchant creature -- Enchanted creature has lifelink. -- {1}{W}: Attach Felidar Umbra to target creature you control. -- Totem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.) +mana={1}{W} +type=Enchantment +subtype=Aura +[/card] +[card] name=Fell Shepherd auto=@combatdamaged(player) from(this):may name(Get All Creatures) moveto(myhand) all(creature[fresh]|mygraveyard) auto={b}{s(creature|mybattlefield)}:target(creature) -2/-2 ueot @@ -56591,6 +56664,17 @@ mana={U} type=Instant [/card] [card] +name=Hyena Umbra +abilities=totemarmor +target=creature +auto=teach(creature) 1/1 +auto=teach(creature) first strike +text=Enchant creature -- Enchanted creature gets +1/+1 and has first strike. -- Totem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.) +mana={W} +type=Enchantment +subtype=Aura +[/card] +[card] name=Hymn of Rebirth target=creature|graveyard auto=moveTo(myBattlefield) @@ -57941,6 +58025,18 @@ power=4 toughness=4 [/card] [card] +name=Indrik Umbra +abilities=totemarmor +target=creature +auto=teach(creature) 4/4 +auto=teach(creature) first strike +auto=teach(creature) lure +text=Enchant creature -- Enchanted creature gets +4/+4 and has first strike, and all creatures able to block it do so. -- Totem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.) +mana={4}{G}{W} +type=Enchantment +subtype=Aura +[/card] +[card] name=Induce Paranoia target=*|stack auto=if spent({B}) then transforms((,newability[deplete:manacost],newability[fizzle])) else fizzle @@ -70370,6 +70466,17 @@ type=Enchantment subtype=Aura [/card] [card] +name=Mammoth Umbra +abilities=totemarmor +target=creature +auto=teach(creature) 3/3 +auto=teach(creature) vigilance +text=Enchant creature -- Enchanted creature gets +3/+3 and has vigilance. -- Totem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.) +mana={4}{W} +type=Enchantment +subtype=Aura +[/card] +[card] name=Mana Bloom auto=counter(0/0,X,Charge) auto={C(0/0,-1,Charge)}:Add{G} limit:1 @@ -108618,6 +108725,17 @@ mana={3}{G} type=Enchantment [/card] [card] +name=Snake Umbra +abilities=totemarmor +target=creature +auto=teach(creature) 1/1 +auto=teach(creature) transforms((,newability[@damagefoeof(player) from(this):may draw:1 controller])) +text=Enchant creature -- Enchanted creature gets +1/+1 and has "Whenever this creature deals damage to an opponent, you may draw a card." -- Totem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.) +mana={2}{G} +type=Enchantment +subtype=Aura +[/card] +[card] name=Snakeform target=creature auto=ueot loseabilities @@ -110992,6 +111110,17 @@ mana={4}{G} type=Sorcery [/card] [card] +name=Spider Umbra +abilities=totemarmor +target=creature +auto=teach(creature) 1/1 +auto=teach(creature) reach +text=Enchant creature -- Enchanted creature gets +1/+1 and has reach. (It can block creatures with flying.) -- Totem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.) +mana={G} +type=Enchantment +subtype=Aura +[/card] +[card] name=Spidersilk Armor auto=lord(creature|myBattlefield) 0/1 auto=lord(creature|myBattlefield) reach @@ -122685,7 +122814,7 @@ toughness=5 [card] name=Tormented Hero auto=tap(noevent) -auto=@targeted(this) from(*|nonbattlezone):lifeleech:-1 opponent +auto=@targeted(this) from(*|mycastingzone):lifeleech:-1 opponent text=Tormented Hero enters the battlefield tapped. -- Heroic - Whenever you cast a spell that targets Tormented Hero, each opponent loses 1 life. You gain life equal to the life lost this way. mana={B} type=Creature diff --git a/projects/mtg/bin/Res/sets/primitives/unsupported.txt b/projects/mtg/bin/Res/sets/primitives/unsupported.txt index e2bd26d26..071d63df8 100644 --- a/projects/mtg/bin/Res/sets/primitives/unsupported.txt +++ b/projects/mtg/bin/Res/sets/primitives/unsupported.txt @@ -1018,13 +1018,6 @@ power=1 toughness=3 [/card] [card] -name=Bear Umbra -text=Enchant creature -- Enchanted creature gets +2/+2 and has "Whenever this creature attacks, untap all lands you control." -- Totem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.) -mana={2}{G}{G} -type=Enchantment -subtype=Aura -[/card] -[card] name=Bearer of Silence text=Devoid (This card has no color.) -- When you cast Bearer of Silence, you may pay {1}{C}. If you do, target opponent sacrifices a creature. ({C} represents colorless mana.) -- Flying -- Bearer of Silence can't block. mana={1}{B} @@ -1294,13 +1287,6 @@ mana={2}{R} type=Enchantment [/card] [card] -name=Boar Umbra -text=Enchant creature -- Enchanted creature gets +3/+3. -- Totem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.) -mana={2}{G} -type=Enchantment -subtype=Aura -[/card] -[card] name=Bog Hoodlums text=Bog Hoodlums can't block. -- When Bog Hoodlums enters the battlefield, clash with an opponent. If you win, put a +1/+1 counter on Bog Hoodlums. (Each clashing player reveals the top card of his or her library, then puts that card on the top or bottom. A player wins if his or her card had a higher converted mana cost.) mana={5}{B} @@ -2864,13 +2850,6 @@ type=Enchantment subtype=Aura [/card] [card] -name=Crab Umbra -text=Enchant creature -- {2}{U}: Untap enchanted creature. -- Totem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.) -mana={U} -type=Enchantment -subtype=Aura -[/card] -[card] name=Cragganwick Cremator text=When Cragganwick Cremator enters the battlefield, discard a card at random. If you discard a creature card this way, Cragganwick Cremator deals damage equal to that card's power to target player. mana={2}{R}{R} @@ -3978,13 +3957,6 @@ mana={U}{U} type=Sorcery [/card] [card] -name=Drake Umbra -text=Enchant creature -- Enchanted creature gets +3/+3 and has flying. -- Totem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.) -mana={4}{U} -type=Enchantment -subtype=Aura -[/card] -[card] name=Dralnu, Lich Lord text=If damage would be dealt to Dralnu, Lich Lord, sacrifice that many permanents instead. -- {T}: Target instant or sorcery card in your graveyard gains flashback until end of turn. The flashback cost is equal to its mana cost. (You may cast that card from your graveyard for its flashback cost. Then exile it.) mana={3}{U}{B} @@ -4162,20 +4134,6 @@ type=Plane subtype=Belenon [/card] [card] -name=Eel Umbra -text=Flash (You may cast this spell any time you could cast an instant.) -- Enchant creature -- Enchanted creature gets +1/+1. -- Totem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.) -mana={1}{U} -type=Enchantment -subtype=Aura -[/card] -[card] -name=Eland Umbra -text=Enchant creature -- Enchanted creature gets +0/+4. -- Totem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.) -mana={1}{W} -type=Enchantment -subtype=Aura -[/card] -[card] name=Elderwood Scion text=Trample, lifelink -- Spells you cast that target Elderwood Scion cost {2} less to cast. -- Spells your opponents cast that target Elderwood Scion cost {2} more to cast. mana={3}{G}{W} @@ -4803,13 +4761,6 @@ mana={R} type=Instant [/card] [card] -name=Felidar Umbra -text=Enchant creature -- Enchanted creature has lifelink. -- {1}{W}: Attach Felidar Umbra to target creature you control. -- Totem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.) -mana={1}{W} -type=Enchantment -subtype=Aura -[/card] -[card] name=Fell the Mighty text=Destroy all creatures with power greater than target creature's power. mana={4}{W} @@ -6943,13 +6894,6 @@ power=3 toughness=3 [/card] [card] -name=Hyena Umbra -text=Enchant creature -- Enchanted creature gets +1/+1 and has first strike. -- Totem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.) -mana={W} -type=Enchantment -subtype=Aura -[/card] -[card] name=Hymn of the Wilds text=(Start the game with this conspiracy face up in the command zone.) -- The first creature spell you cast each turn costs {1} less to cast. -- You can't cast instant or sorcery spells. type=Conspiracy @@ -7253,13 +7197,6 @@ mana={3}{G}{G} type=Sorcery [/card] [card] -name=Indrik Umbra -text=Enchant creature -- Enchanted creature gets +4/+4 and has first strike, and all creatures able to block it do so. -- Totem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.) -mana={4}{G}{W} -type=Enchantment -subtype=Aura -[/card] -[card] name=Induce Despair text=As an additional cost to cast Induce Despair, reveal a creature card from your hand. -- Target creature gets -X/-X until end of turn, where X is the revealed card's converted mana cost. mana={2}{B} @@ -8966,13 +8903,6 @@ power=* toughness=* [/card] [card] -name=Mammoth Umbra -text=Enchant creature -- Enchanted creature gets +3/+3 and has vigilance. -- Totem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.) -mana={4}{W} -type=Enchantment -subtype=Aura -[/card] -[card] name=Mana Cache text=At the beginning of each player's end step, put a charge counter on Mana Cache for each untapped land that player controls. -- Remove a charge counter from Mana Cache: Add {1} to your mana pool. Any player may activate this ability but only during his or her turn before the end step. mana={1}{R}{R} @@ -14358,13 +14288,6 @@ power=2 toughness=2 [/card] [card] -name=Snake Umbra -text=Enchant creature -- Enchanted creature gets +1/+1 and has "Whenever this creature deals damage to an opponent, you may draw a card." -- Totem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.) -mana={2}{G} -type=Enchantment -subtype=Aura -[/card] -[card] name=Snow Mercy text=Whenever a creature deals damage to you, put a globe counter on it. -- {T}, {untap}, {T}, {untap}, {T}: Tap all creatures with globe counters on them. mana={2}{W}{W} @@ -14811,13 +14734,6 @@ type=Enchantment subtype=Aura [/card] [card] -name=Spider Umbra -text=Enchant creature -- Enchanted creature gets +1/+1 and has reach. (It can block creatures with flying.) -- Totem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.) -mana={G} -type=Enchantment -subtype=Aura -[/card] -[card] name=Spike Cannibal text=Spike Cannibal enters the battlefield with a +1/+1 counter on it. -- When Spike Cannibal enters the battlefield, move all +1/+1 counters from all creatures onto it. mana={1}{B}{B} diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index fafcad398..d25fa0615 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -7253,6 +7253,90 @@ public: } }; //------------------ +//trigger regen +class ATriggerRegen: public InstantAbility +{ +public: + ATriggerRegen(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target) : + InstantAbility(observer, _id, _source) + { + target = _target; + } + + int resolve() + { + MTGCardInstance * card = (MTGCardInstance *) target; + if (card) + { + if (!card->regenerateTokens) + return 0; + if (card->has(Constants::CANTREGEN)) + return 0; + card->regenerateTokens--; + card->tap(); + if(card->isCreature()) + { + card->life = card->toughness; + card->initAttackersDefensers(); + if (card->life < 1) + return 0; //regeneration didn't work (wither ?) + } + } + return 1; + } + const string getMenuText() + { + return "Regenerate"; + } + virtual ostream& toString(ostream& out) const + { + out << "AATriggerRegen ::: ("; + return InstantAbility::toString(out) << ")"; + } + ATriggerRegen * clone() const + { + return NEW ATriggerRegen(*this); + } +}; +//trigger totem +class ATriggerTotem: public InstantAbility +{ +public: + ATriggerTotem(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target) : + InstantAbility(observer, _id, _source) + { + target = _target; + } + + int resolve() + { + MTGCardInstance * card = (MTGCardInstance *) target; + if (card) + { + card->destroy(); + if(source->isCreature()) + { + source->life = source->toughness; + if (source->life < 1) + return 0; //regeneration didn't work (wither ?) + } + } + return 1; + } + const string getMenuText() + { + return "Totem Armor"; + } + virtual ostream& toString(ostream& out) const + { + out << "AATriggerTotem ::: ("; + return InstantAbility::toString(out) << ")"; + } + ATriggerTotem * clone() const + { + return NEW ATriggerTotem(*this); + } +}; // utility functions void PopulateColorIndexVector(list& colors, const string& colorsString, char delimiter = ','); diff --git a/projects/mtg/include/MTGCardInstance.h b/projects/mtg/include/MTGCardInstance.h index 38a64ebb7..63beac0fb 100644 --- a/projects/mtg/include/MTGCardInstance.h +++ b/projects/mtg/include/MTGCardInstance.h @@ -139,6 +139,7 @@ public: ManaCost * getReducedManaCost(); ManaCost * getIncreasedManaCost(); bool matchesCastFilter(int castMethod); + bool hasTotemArmor(); // The recommended method to test for summoning Sickness ! int hasSummoningSickness(); @@ -203,8 +204,10 @@ public: Player * controller(); virtual ~MTGCardInstance(); - int bury(); + int totem( bool noregen = false ); + int toGrave( bool forced = false ); int destroy(); + int destroyNoRegen(); int addToToughness(int value); int setToughness(int value); diff --git a/projects/mtg/include/MTGDefinitions.h b/projects/mtg/include/MTGDefinitions.h index b1119ca81..4cd71346d 100644 --- a/projects/mtg/include/MTGDefinitions.h +++ b/projects/mtg/include/MTGDefinitions.h @@ -274,7 +274,8 @@ class Constants CANPLAYINSTANTSORCERYTOPLIBRARY = 152,//instantorsorcery SHOWFROMTOPLIBRARY = 153, SHOWOPPONENTTOPLIBRARY = 154, - NB_BASIC_ABILITIES = 155, + TOTEMARMOR = 155, + NB_BASIC_ABILITIES = 156, RARITY_S = 'S', //Special Rarity RARITY_M = 'M', //Mythics diff --git a/projects/mtg/include/TargetChooser.h b/projects/mtg/include/TargetChooser.h index 1313a3b90..b516b17bd 100644 --- a/projects/mtg/include/TargetChooser.h +++ b/projects/mtg/include/TargetChooser.h @@ -377,4 +377,24 @@ public: virtual bool equals(TargetChooser * tc); ~ChildrenChooser(); }; + +class TotemChooser: public TypeTargetChooser +{ +public: + bool withoutProtections; + TotemChooser(GameObserver *observer, int * _zones, int _nbzones, MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false, bool targetMin = false) : + TypeTargetChooser(observer, "*",_zones, _nbzones, card, _maxtargets, other, targetMin) + { + } + ; + TotemChooser(GameObserver *observer, MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false,bool targetMin = false) : + TypeTargetChooser(observer, "*", card, _maxtargets, other,targetMin) + { + } + ; + virtual bool canTarget(Targetable * target, bool withoutProtections = false); + virtual TotemChooser * clone() const; + virtual bool equals(TargetChooser * tc); + ~TotemChooser(); +}; #endif diff --git a/projects/mtg/src/AllAbilities.cpp b/projects/mtg/src/AllAbilities.cpp index 89b6a2b15..35551c229 100644 --- a/projects/mtg/src/AllAbilities.cpp +++ b/projects/mtg/src/AllAbilities.cpp @@ -2855,7 +2855,13 @@ int AABuryCard::resolve() MTGCardInstance * _target = (MTGCardInstance *) target; if (_target) { - _target->bury(); + //Bury (Obsolete) + //A term that meant “put [a permanent] into its owner’s graveyard.” + //In general, cards that were printed with the term “bury” have received errata + //in the Oracle card reference to read, “Destroy [a permanent]. It can’t be regenerated,” + //or “Sacrifice [a permanent].” + //_target->bury(); + _target->destroyNoRegen();//so totem armor will take effect on wrath effects since totem armor is not regeneration.. while(_target->next) _target = _target->next; if(andAbility) @@ -3221,6 +3227,10 @@ int AANewTarget::resolve() while (_target->next) _target = _target->next; } + if(_target->hasSubtype(Subtypes::TYPE_AURA)) + { + _target->target = source; + } if(_target->hasSubtype(Subtypes::TYPE_EQUIPMENT)) { for (size_t i = 1; i < game->mLayers->actionLayer()->mObjects.size(); i++) diff --git a/projects/mtg/src/MTGCardInstance.cpp b/projects/mtg/src/MTGCardInstance.cpp index 754446146..1b395a834 100644 --- a/projects/mtg/src/MTGCardInstance.cpp +++ b/projects/mtg/src/MTGCardInstance.cpp @@ -445,7 +445,51 @@ int MTGCardInstance::afterDamage() return 0; } -int MTGCardInstance::bury() +int MTGCardInstance::totem(bool noregen) +{ + int testToughness = toughness; + testToughness += tbonus; + if(testToughness < 1) + { + if(noregen) + return toGrave(); + else if (!triggerRegenerate()) + return toGrave(); + return 0; + } + bool canregen = (regenerateTokens && !has(Constants::CANTREGEN) && !noregen); + vectorselection; + TargetChooserFactory tf(getObserver()); + TargetChooser * tcb = tf.createTargetChooser("mytotem",this); + tcb->targetter = NULL; + tcb->maxtargets = 1; + MTGAbility * destroyTotem = NEW ATriggerTotem(getObserver(), getObserver()->mLayers->actionLayer()->getMaxId(),this,NULL); + destroyTotem->oneShot = true; + destroyTotem->canBeInterrupted = false; + MTGAbility * dtTarget = NEW GenericTargetAbility(getObserver(), "","",getObserver()->mLayers->actionLayer()->getMaxId(), this,tcb->clone(), destroyTotem->clone()); + SAFE_DELETE(destroyTotem); + dtTarget->oneShot = true; + dtTarget->canBeInterrupted = false; + MTGAbility * addTotemtoGame = NEW GenericAddToGame(getObserver(), getObserver()->mLayers->actionLayer()->getMaxId(), this,NULL,dtTarget->clone()); + SAFE_DELETE(dtTarget); + addTotemtoGame->oneShot = true; + addTotemtoGame->canBeInterrupted = false; + selection.push_back(addTotemtoGame->clone()); + SAFE_DELETE(addTotemtoGame); + SAFE_DELETE(tcb); + if(canregen) + { + MTGAbility * triggerRegen = NEW ATriggerRegen(getObserver(), getObserver()->mLayers->actionLayer()->getMaxId(), this, this); + triggerRegen->oneShot = true; + triggerRegen->canBeInterrupted = false; + selection.push_back(triggerRegen->clone()); + SAFE_DELETE(triggerRegen); + } + MTGAbility * menuChoice = NEW MenuAbility(getObserver(), getObserver()->mLayers->actionLayer()->getMaxId(), NULL, this,true,selection,this->controller(),""); + menuChoice->addToGame(); + return 1; +} +int MTGCardInstance::toGrave( bool forced ) { Player * p = controller(); if (basicAbilities[(int)Constants::EXILEDEATH]) @@ -458,15 +502,29 @@ int MTGCardInstance::bury() p->game->putInZone(this, p->game->inPlay, owner->game->graveyard); return 1; } + if (forced) + { + p->game->putInZone(this, p->game->inPlay, owner->game->graveyard); + return 1; + } return 0; } int MTGCardInstance::destroy() { - if (!triggerRegenerate()) - return bury(); + if (hasTotemArmor()) + return totem(); + else if (!triggerRegenerate()) + return toGrave(); + return 0; +} +int MTGCardInstance::destroyNoRegen() +{ + if (hasTotemArmor()) + return totem(true); + else + return toGrave(); return 0; } - MTGGameZone * MTGCardInstance::getCurrentZone() { return currentZone; @@ -1525,6 +1583,32 @@ bool MTGCardInstance::matchesCastFilter(int castFilter) { return (castFilter == castMethod); }; +bool MTGCardInstance::hasTotemArmor() +{ + int count = 0; + if(observer) + { + for (int i = 0; i < 2; i++) + { + int nb_cards = observer->players[i]->game->battlefield->nb_cards; + for(int x = 0; x < nb_cards; x++) + { + if(observer->players[i]->game->battlefield->cards[x]->auraParent) + { + if(observer->players[i]->game->battlefield->cards[x]->auraParent == this && + observer->players[i]->game->battlefield->cards[x]->has(Constants::TOTEMARMOR)) + count+=1; + } + } + } + } + + if(count) + return true; + + return false; +} + int MTGCardInstance::addProtection(TargetChooser * tc) { tc->targetter = NULL; diff --git a/projects/mtg/src/MTGDefinitions.cpp b/projects/mtg/src/MTGDefinitions.cpp index 9a3284af9..507032e8b 100644 --- a/projects/mtg/src/MTGDefinitions.cpp +++ b/projects/mtg/src/MTGDefinitions.cpp @@ -185,7 +185,8 @@ const char* Constants::MTGBasicAbilities[] = { "canplayartifactlibrarytop",//artifact "canplayinstantsorcerylibrarytop",//instant or sorcery "showfromtoplibrary", - "showopponenttoplibrary" + "showopponenttoplibrary", + "totemarmor" }; map Constants::MTGBasicAbilitiesMap; diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index 8c8fb423f..a4930645c 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -3741,7 +3741,7 @@ int MTGPlaneswalkerDamage::receiveEvent(WEvent * event) if(removel->removed && removel->targetCard && removel->targetCard->hasType(Subtypes::TYPE_PLANESWALKER)) if(!removel->targetCard->counters->hasCounter("loyalty",0,0)) { - removel->targetCard->bury(); + removel->targetCard->toGrave(true); return 1; } diff --git a/projects/mtg/src/TargetChooser.cpp b/projects/mtg/src/TargetChooser.cpp index 91c966c1d..951722a5f 100644 --- a/projects/mtg/src/TargetChooser.cpp +++ b/projects/mtg/src/TargetChooser.cpp @@ -55,6 +55,13 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta return NEW ChildrenChooser(observer, card, maxtargets); }; + found = s.find("mytotem"); + if (found == 0) + { + int maxtargets = 1; + return NEW TotemChooser(observer, card, maxtargets); + }; + found = s.find("targetedplayer"); if (found == 0) { @@ -220,6 +227,7 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta zones[nbzones++] = MTGGameZone::MY_LIBRARY; zones[nbzones++] = MTGGameZone::MY_HAND; zones[nbzones++] = MTGGameZone::MY_EXILE; + zones[nbzones++] = MTGGameZone::MY_SIDEBOARD; } else if (zoneName.compare("opponentcastingzone") == 0) { @@ -2061,3 +2069,42 @@ bool ChildrenChooser::equals(TargetChooser * tc) ChildrenChooser::~ChildrenChooser() { } + +//totem armor chooser +bool TotemChooser::canTarget(Targetable * target,bool withoutProtections) +{ + if (MTGCardInstance * card = dynamic_cast(target)) + { + if(card == source) + return false; + if(!card->isInPlay(observer)) + return false; + if(card->auraParent) + { + if((card->auraParent) == source && (card->has(Constants::TOTEMARMOR))) + return true; + } + return false; + } + return false; +} + +TotemChooser* TotemChooser::clone() const +{ + TotemChooser * a = NEW TotemChooser(*this); + return a; +} + +bool TotemChooser::equals(TargetChooser * tc) +{ + + TotemChooser * dtc = dynamic_cast (tc); + if (!dtc) + return false; + + return TypeTargetChooser::equals(tc); +} + +TotemChooser::~TotemChooser() +{ +}