From c265ce8222b975301e16419575aceeafea6b16f5 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Thu, 2 Feb 2017 09:58:38 +0800 Subject: [PATCH 1/3] Bug Correction PermanentAbility to ListMaintainerAbility in Legend Rule, it seems It's finally fixed even with a lot of targetchooser and copy effects. --- projects/mtg/bin/Res/sets/primitives/mtg.txt | 3 +- projects/mtg/include/MTGRules.h | 7 +- projects/mtg/src/MTGRules.cpp | 101 ++++++++++--------- 3 files changed, 62 insertions(+), 49 deletions(-) diff --git a/projects/mtg/bin/Res/sets/primitives/mtg.txt b/projects/mtg/bin/Res/sets/primitives/mtg.txt index c36d6fc5e..7999d925a 100644 --- a/projects/mtg/bin/Res/sets/primitives/mtg.txt +++ b/projects/mtg/bin/Res/sets/primitives/mtg.txt @@ -25239,8 +25239,7 @@ type=Sorcery name=Dark Depths auto=counter(0/0,10,Ice) auto={3}:counter(0/0,-1,Ice) all(this) -auto=this(counter{0/0.1.Ice}<1)while sacrifice -auto=this(counter{0/0.1.Ice}<1)while token(Marit Lage,legendary creature avatar, 20/20,flying,indestructible,black) +auto=this(counter{0/0.1.Ice}<1)while sacrifice and!( token(Marit Lage,legendary creature avatar, 20/20,flying,indestructible,black) )! text=Dark Depths enters the battlefield with ten ice counters on it. -- {3}: Remove an ice counter from Dark Depths. -- When Dark Depths has no ice counters on it, sacrifice it. If you do, put a legendary 20/20 black Avatar creature token with flying and "This creature is indestructible" named Marit Lage onto the battlefield. type=Legendary Snow Land [/card] diff --git a/projects/mtg/include/MTGRules.h b/projects/mtg/include/MTGRules.h index ecb6fde33..689c8913c 100644 --- a/projects/mtg/include/MTGRules.h +++ b/projects/mtg/include/MTGRules.h @@ -427,7 +427,7 @@ public: * that player chooses one of them, and the rest are put into their owners’ graveyards. * This is called the “legend rule.” */ -class MTGLegendRule: public PermanentAbility +class MTGLegendRule: public ListMaintainerAbility { public: TargetChooser * tcL; @@ -435,7 +435,10 @@ public: MTGAbility * LegendruleAbility; MTGAbility * LegendruleGeneric; MTGLegendRule(GameObserver* observer, int _id); - int receiveEvent(WEvent * event); + int canBeInList(MTGCardInstance * card); + int added(MTGCardInstance * card); + int removed(MTGCardInstance * card); + int testDestroy(); virtual ostream& toString(ostream& out) const; virtual MTGLegendRule * clone() const; }; diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index 0ab307b21..8f8922384 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -3205,7 +3205,7 @@ MTGTokensCleanup * MTGTokensCleanup::clone() const /* Legend Rule */ MTGLegendRule::MTGLegendRule(GameObserver* observer, int _id) : -PermanentAbility(observer, _id) +ListMaintainerAbility(observer, _id) { tcL = NULL; Legendrule = NULL; @@ -3214,50 +3214,67 @@ PermanentAbility(observer, _id) } ; -int MTGLegendRule::receiveEvent(WEvent * event) +int MTGLegendRule::canBeInList(MTGCardInstance * card) { - WEventGameStateBasedChecked * e = dynamic_cast (event); - if (e) + if(card->isPhased) + return 0; + if (card->hasType(Subtypes::TYPE_LEGENDARY) && card->controller()->game->inPlay->hasCard(card)) { - for (int i = 0; i < 2; i++) - { - MTGGameZone * zone = game->players[i]->game->inPlay; - for (int k = zone->nb_cards - 1; k >= 0; k--) - { - MTGCardInstance * card = zone->cards[k]; - if (card && card->hasType(Subtypes::TYPE_LEGENDARY) && !card->isPhased) - { - bool condition = (card->has(Constants::NOLEGEND)||card->controller()->opponent()->inPlay()->hasAbility(Constants::NOLEGENDRULE)||card->controller()->inPlay()->hasAbility(Constants::NOLEGENDRULE))?false:true; - if(condition && card->countDuplicateCardNames() > 1) - { - vectorselection; - TargetChooserFactory tfL(game); - tcL = tfL.createTargetChooser("*[share!name!]|mybattlefield",card); - tcL->targetter = NULL; - tcL->maxtargets = card->countDuplicateCardNames()-1; - Legendrule = NEW AAMover(game, game->mLayers->actionLayer()->getMaxId(), card, NULL,"ownergraveyard","Put in Graveyard"); - Legendrule->oneShot = true; - Legendrule->canBeInterrupted = false; - LegendruleAbility = NEW GenericTargetAbility(game, "","",game->mLayers->actionLayer()->getMaxId(), card,tcL, Legendrule->clone()); - SAFE_DELETE(Legendrule); - LegendruleAbility->oneShot = true; - LegendruleAbility->canBeInterrupted = false; - LegendruleGeneric = NEW GenericAddToGame(game, game->mLayers->actionLayer()->getMaxId(), card,NULL,LegendruleAbility->clone()); - SAFE_DELETE(LegendruleAbility); - LegendruleGeneric->oneShot = true; - selection.push_back(LegendruleGeneric->clone()); - SAFE_DELETE(LegendruleGeneric); - MTGAbility * menuChoice = NEW MenuAbility(game, game->mLayers->actionLayer()->getMaxId(), card, card,true,selection,card->controller(),"Legendary Rule"); - menuChoice->addToGame(); - return 1; - } - } - } - } + if(card->has(Constants::NOLEGEND)||card->controller()->opponent()->inPlay()->hasAbility(Constants::NOLEGENDRULE)||card->controller()->inPlay()->hasAbility(Constants::NOLEGENDRULE)) + return 0; + else + return 1; } return 0; } +int MTGLegendRule::added(MTGCardInstance * card) +{ + map::iterator it; + int destroy = 0; + + for (it = cards.begin(); it != cards.end(); it++) + { + MTGCardInstance * comparison = (*it).first; + if (comparison != card && comparison->controller() == card->controller() && !(comparison->getName().compare(card->getName()))) + destroy = 1; + } + if(destroy) + { + vectorselection; + MTGCardInstance * myClone = NEW MTGCardInstance(card, card->controller()->game); + TargetChooserFactory tfL(game); + tcL = tfL.createTargetChooser("*[share!name!]|mybattlefield",myClone); + tcL->targetter = NULL; + tcL->maxtargets = 1; + Legendrule = NEW AAMover(game, game->mLayers->actionLayer()->getMaxId(), myClone, NULL,"ownergraveyard","Put in Graveyard"); + Legendrule->oneShot = true; + Legendrule->canBeInterrupted = false; + LegendruleAbility = NEW GenericTargetAbility(game, "","",game->mLayers->actionLayer()->getMaxId(), myClone,tcL, Legendrule->clone()); + SAFE_DELETE(Legendrule); + LegendruleAbility->oneShot = true; + LegendruleAbility->canBeInterrupted = false; + LegendruleGeneric = NEW GenericAddToGame(game, game->mLayers->actionLayer()->getMaxId(), myClone,NULL,LegendruleAbility->clone()); + SAFE_DELETE(LegendruleAbility); + LegendruleGeneric->oneShot = true; + selection.push_back(LegendruleGeneric->clone()); + SAFE_DELETE(LegendruleGeneric); + MTGAbility * menuChoice = NEW MenuAbility(game, game->mLayers->actionLayer()->getMaxId(), NULL, myClone,true,selection,card->controller(),"Legendary Rule"); + menuChoice->addToGame(); + } + return 1; +} + +int MTGLegendRule::removed(MTGCardInstance *) +{ + return 0; +} + +int MTGLegendRule::testDestroy() +{ + return 0; +} + ostream& MTGLegendRule::toString(ostream& out) const { return out << "MTGLegendRule :::"; @@ -3299,12 +3316,6 @@ int MTGPlaneWalkerRule::added(MTGCardInstance * card) destroy = 1; } } - if (game->mLayers->stackLayer()->count(0, NOT_RESOLVED) != 0) - destroy = 0; - if (game->mLayers->actionLayer()->menuObject) - destroy = 0; - if (game->getCurrentTargetChooser() || game->mLayers->actionLayer()->isWaitingForAnswer()) - destroy = 0; if (destroy) { vectorselection; From c535d033ecfa807c71f41d8763cd2d3be0a2144b Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Thu, 2 Feb 2017 11:08:17 +0800 Subject: [PATCH 2/3] fix Dark Depths there should a window for the triggered sacrifice and legend rule. --- projects/mtg/bin/Res/sets/primitives/mtg.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/mtg/bin/Res/sets/primitives/mtg.txt b/projects/mtg/bin/Res/sets/primitives/mtg.txt index 7999d925a..5c84d17ab 100644 --- a/projects/mtg/bin/Res/sets/primitives/mtg.txt +++ b/projects/mtg/bin/Res/sets/primitives/mtg.txt @@ -25239,7 +25239,7 @@ type=Sorcery name=Dark Depths auto=counter(0/0,10,Ice) auto={3}:counter(0/0,-1,Ice) all(this) -auto=this(counter{0/0.1.Ice}<1)while sacrifice and!( token(Marit Lage,legendary creature avatar, 20/20,flying,indestructible,black) )! +auto=this(counter{0/0.1.Ice}<1)while sacrifice and!( token(Marit Lage,legendary creature avatar, 20/20,flying,indestructible,black) )! notatarget(this) text=Dark Depths enters the battlefield with ten ice counters on it. -- {3}: Remove an ice counter from Dark Depths. -- When Dark Depths has no ice counters on it, sacrifice it. If you do, put a legendary 20/20 black Avatar creature token with flying and "This creature is indestructible" named Marit Lage onto the battlefield. type=Legendary Snow Land [/card] From 6354d8ccca30dde88ea6a4ee30ddb2fb8bbd498f Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Thu, 2 Feb 2017 11:58:51 +0800 Subject: [PATCH 3/3] revised pw rule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit also fixed where planeswalker can use its ability after it was transformed/flipped by activation ex. Garruk Relentless... You can’t activate a loyalty ability of Garruk Relentless and later that turn after he transforms activate a loyalty ability of Garruk, the Veil-Cursed. --- projects/mtg/include/MTGRules.h | 4 +++ projects/mtg/src/AllAbilities.cpp | 25 +++++++++++++++++++ projects/mtg/src/MTGRules.cpp | 41 +++++++++++++++++-------------- 3 files changed, 51 insertions(+), 19 deletions(-) diff --git a/projects/mtg/include/MTGRules.h b/projects/mtg/include/MTGRules.h index 689c8913c..aa22e9295 100644 --- a/projects/mtg/include/MTGRules.h +++ b/projects/mtg/include/MTGRules.h @@ -445,6 +445,10 @@ public: class MTGPlaneWalkerRule: public ListMaintainerAbility { public: + TargetChooser * tcP; + MTGAbility * PWrule; + MTGAbility * PWruleAbility; + MTGAbility * PWruleGeneric; MTGPlaneWalkerRule(GameObserver* observer, int _id); int canBeInList(MTGCardInstance * card); int added(MTGCardInstance * card); diff --git a/projects/mtg/src/AllAbilities.cpp b/projects/mtg/src/AllAbilities.cpp index 35801dff9..2de381334 100644 --- a/projects/mtg/src/AllAbilities.cpp +++ b/projects/mtg/src/AllAbilities.cpp @@ -3347,6 +3347,7 @@ InstantAbility(observer, id, card, _target),flipStats(flipStats),isflipcard(isfl int AAFlip::resolve() { int cdaDamage = 0; + int activatedanyability = 0; MTGCardInstance * Flipper = (MTGCardInstance*)source; this->oneShot = true; if(Flipper->isFlipped) @@ -3397,6 +3398,17 @@ int AAFlip::resolve() _target->setMTGId(myFlip->getMTGId()); _target->setId = myFlip->setId; } + //check pw + if(_target->hasType(Subtypes::TYPE_PLANESWALKER)) + { + for(unsigned int k = 0;k < _target->cardsAbilities.size();++k) + { + ActivatedAbility * check = dynamic_cast(_target->cardsAbilities[k]); + if(check && check->counters) + activatedanyability++; + } + } + // for(unsigned int i = 0;i < _target->cardsAbilities.size();i++) { MTGAbility * a = dynamic_cast(_target->cardsAbilities[i]); @@ -3428,6 +3440,19 @@ int AAFlip::resolve() } } } + //limit pw abi + if(activatedanyability) + { + if(_target->hasType(Subtypes::TYPE_PLANESWALKER)) + { + for(unsigned int k = 0;k < _target->cardsAbilities.size();++k) + { + ActivatedAbility * check = dynamic_cast(_target->cardsAbilities[k]); + if(check)//is there a better way? + check->counters++; + } + } + } //power int powerMod = 0; int toughMod = 0; diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index 8f8922384..45e005961 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -3288,6 +3288,10 @@ MTGLegendRule * MTGLegendRule::clone() const MTGPlaneWalkerRule::MTGPlaneWalkerRule(GameObserver* observer, int _id) : ListMaintainerAbility(observer, _id) { + tcP = NULL; + PWrule = NULL; + PWruleAbility = NULL; + PWruleGeneric = NULL; } ; @@ -3311,30 +3315,29 @@ int MTGPlaneWalkerRule::added(MTGCardInstance * card) { MTGCardInstance * comparison = (*it).first; if (comparison != card && comparison->types == card->types && comparison->controller() == card->controller()) - { - oldCards.push_back(comparison); destroy = 1; - } } if (destroy) { vectorselection; - - MultiAbility * multi = NEW MultiAbility(game,game->mLayers->actionLayer()->getMaxId(), card, card, NULL); - for(unsigned int i = 0;i < oldCards.size();i++) - { - AAMover *a = NEW AAMover(game, game->mLayers->actionLayer()->getMaxId(), card, oldCards[i],"ownergraveyard","Keep New"); - a->oneShot = true; - multi->Add(a); - } - multi->oneShot = 1; - MTGAbility * a1 = multi; - selection.push_back(a1); - AAMover *b = NEW AAMover(game, game->mLayers->actionLayer()->getMaxId(), card, card,"ownergraveyard","Keep Old"); - b->oneShot = true; - MTGAbility * b1 = b; - selection.push_back(b1); - MTGAbility * menuChoice = NEW MenuAbility(game, game->mLayers->actionLayer()->getMaxId(), card, card,true,selection,card->controller(),"Planeswalker Rule"); + MTGCardInstance * myClone = NEW MTGCardInstance(card, card->controller()->game); + TargetChooserFactory tfL(game); + tcP = tfL.createTargetChooser("planeswalker[share!types!]|mybattlefield",myClone); + tcP->targetter = NULL; + tcP->maxtargets = 1; + PWrule = NEW AAMover(game, game->mLayers->actionLayer()->getMaxId(), myClone, NULL,"ownergraveyard","Put in Graveyard"); + PWrule->oneShot = true; + PWrule->canBeInterrupted = false; + PWruleAbility = NEW GenericTargetAbility(game, "","",game->mLayers->actionLayer()->getMaxId(), myClone,tcP, PWrule->clone()); + SAFE_DELETE(PWrule); + PWruleAbility->oneShot = true; + PWruleAbility->canBeInterrupted = false; + PWruleGeneric = NEW GenericAddToGame(game, game->mLayers->actionLayer()->getMaxId(), myClone,NULL,PWruleAbility->clone()); + SAFE_DELETE(PWruleAbility); + PWruleGeneric->oneShot = true; + selection.push_back(PWruleGeneric->clone()); + SAFE_DELETE(PWruleGeneric); + MTGAbility * menuChoice = NEW MenuAbility(game, game->mLayers->actionLayer()->getMaxId(), NULL, myClone,true,selection,card->controller(),"Planeswalker Uniqueness Rule"); menuChoice->addToGame(); } return 1;