From 3e75d70632677a76a4b97a1cfca0502dc8a63fdb Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Sat, 28 Jan 2017 13:23:30 +0800 Subject: [PATCH 1/4] revert this I introduce more bugs than helped. I think there's alternative method for this,,, --- projects/mtg/src/AllAbilities.cpp | 67 ++-------------------------- projects/mtg/src/GameObserver.cpp | 2 +- projects/mtg/src/MTGAbility.cpp | 9 +--- projects/mtg/src/MTGCardInstance.cpp | 7 +-- 4 files changed, 9 insertions(+), 76 deletions(-) diff --git a/projects/mtg/src/AllAbilities.cpp b/projects/mtg/src/AllAbilities.cpp index 01a99c442..4ac1fca45 100644 --- a/projects/mtg/src/AllAbilities.cpp +++ b/projects/mtg/src/AllAbilities.cpp @@ -1543,11 +1543,10 @@ AACopier::AACopier(GameObserver* observer, int _id, MTGCardInstance * _source, M int AACopier::resolve() { - bool tokencopied = false; - AbilityFactory af(game); MTGCardInstance * _target = (MTGCardInstance *) target; if (_target) { + bool tokencopied = false; if(_target->isToken || (_target->isACopier && _target->hasCopiedToken)) tokencopied = true; @@ -1557,38 +1556,6 @@ int AACopier::resolve() { source->copy(_target); } - //abilities - for(unsigned int i = 0;i < source->cardsAbilities.size();i++) - { - MTGAbility * a = dynamic_cast(source->cardsAbilities[i]); - - if(a) game->removeObserver(a); - } - source->cardsAbilities.clear(); - af.getAbilities(¤tAbilities, NULL, source); - for (size_t i = 0; i < currentAbilities.size(); ++i) - { - MTGAbility * a = currentAbilities[i]; - a->source = (MTGCardInstance *) source; - if (a) - { - if (a->oneShot) - { - a->resolve(); - SAFE_DELETE(a); - } - else - { - a->addToGame(); - MayAbility * dontAdd = dynamic_cast(a); - if(!dontAdd) - { - source->cardsAbilities.push_back(a); - } - } - } - } - // source->isACopier = true; source->hasCopiedToken = tokencopied; source->copiedID = _target->copiedID; @@ -1605,35 +1572,9 @@ int AACopier::resolve() source->basicAbilities.reset(); source->getManaCost()->resetCosts(); } - if(_target->TokenAndAbility) - {//the source copied a token with andAbility - MTGAbility * TokenandAbilityClone = _target->TokenAndAbility->clone(); - TokenandAbilityClone->target = source; - if(_target->TokenAndAbility->oneShot) - { - TokenandAbilityClone->resolve(); - SAFE_DELETE(TokenandAbilityClone); - } - else - { - TokenandAbilityClone->addToGame(); - } - } - if(andAbility) - { - MTGAbility * andAbilityClone = andAbility->clone(); - andAbilityClone->target = source; - if(andAbility->oneShot) - { - andAbilityClone->resolve(); - SAFE_DELETE(andAbilityClone); - } - else - { - andAbilityClone->addToGame(); - } - } - //source->mPropertiesChangedSinceLastUpdate = true; + //todo andAbility and tokenandAbility + // + // return 1; } return 0; diff --git a/projects/mtg/src/GameObserver.cpp b/projects/mtg/src/GameObserver.cpp index c9a4d8978..eb5381452 100644 --- a/projects/mtg/src/GameObserver.cpp +++ b/projects/mtg/src/GameObserver.cpp @@ -1069,7 +1069,7 @@ void GameObserver::checkLegendary(MTGCardInstance * card) { if(!foundlegendrule) return; - if(card->has(Constants::NOLEGEND)||card->controller()->opponent()->inPlay()->hasAbility(Constants::NOLEGENDRULE)||card->controller()->inPlay()->hasAbility(Constants::NOLEGENDRULE)) + if(card->isPhased||card->has(Constants::NOLEGEND)||card->controller()->opponent()->inPlay()->hasAbility(Constants::NOLEGENDRULE)||card->controller()->inPlay()->hasAbility(Constants::NOLEGENDRULE)) return; int destroy = 0; vectoroldCards; diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 3a4a582c7..3cd879795 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -1410,13 +1410,8 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG found = s.find("legendrule"); if(found != string::npos) { - //I replaced this rule since it broke cards with copy effects and with andability and other - //complex cards. So I moved it to gameobserver state based effects, if there are no more - //abilities that needs resolving then trigger this legend check... example bug: - //cast Phantasmal Image, then copy Vendilion Clique in play, after you choose target player - //there will be infinite menu for legendary rule that conflicts with Phantasmal andAbility - //observer->addObserver(NEW MTGLegendRule(observer, -1)); - observer->foundlegendrule = true; + observer->addObserver(NEW MTGLegendRule(observer, -1)); + //observer->foundlegendrule = true; return NULL; } //this handles the planeswalker named legend rule which is dramatically different from above. diff --git a/projects/mtg/src/MTGCardInstance.cpp b/projects/mtg/src/MTGCardInstance.cpp index e3226c544..0a2090804 100644 --- a/projects/mtg/src/MTGCardInstance.cpp +++ b/projects/mtg/src/MTGCardInstance.cpp @@ -139,11 +139,11 @@ void MTGCardInstance::copy(MTGCardInstance * card) int castMethodBackUP = this->castMethod; mtgid = source->getId(); MTGCardInstance * oldStored = this->storedSourceCard; - /*Spell * spell = NEW Spell(observer, this); + Spell * spell = NEW Spell(observer, this); observer = card->observer; AbilityFactory af(observer); af.addAbilities(observer->mLayers->actionLayer()->getMaxId(), spell); - delete spell;*/ + delete spell; if(observer->players[1]->playMode == Player::MODE_TEST_SUITE) mtgid = backupid; // there must be a way to get the token id... else @@ -151,14 +151,11 @@ void MTGCardInstance::copy(MTGCardInstance * card) mtgid = card->getMTGId(); /////////////////////////////////////////////////// setId = card->setId; // Copier/Cloner cards produces the same token...// rarity = card->getRarity(); /////////////////////////////////////////////////// - - setMTGId(card->copiedID); //**************sets copier image****************// } castMethod = castMethodBackUP; backupTargets = this->backupTargets; storedCard = oldStored; miracle = false; - mPropertiesChangedSinceLastUpdate = true; } MTGCardInstance::~MTGCardInstance() From e128d548f4eee21ec6e713b4bcd546efca1fe8d6 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Sun, 29 Jan 2017 10:27:18 +0800 Subject: [PATCH 2/4] disable andAbility for aacopier so it will not conflict with original legend rule... --- projects/mtg/src/AllAbilities.cpp | 53 ++++++++++++++++++++++++++-- projects/mtg/src/MTGCardInstance.cpp | 1 + 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/projects/mtg/src/AllAbilities.cpp b/projects/mtg/src/AllAbilities.cpp index 4ac1fca45..b86e88b63 100644 --- a/projects/mtg/src/AllAbilities.cpp +++ b/projects/mtg/src/AllAbilities.cpp @@ -1551,7 +1551,27 @@ int AACopier::resolve() tokencopied = true; if(tokencopied && !_target->isACopier) - source->copy(_target->clone()); + { + source->copy(_target); + //if the token doesn't have cda/dynamic pt then allow this... + if(!_target->isCDA) + { + if(_target->pbonus > 0) + source->power = _target->power - _target->pbonus; + else + source->power = _target->power + abs(_target->pbonus); + if(_target->tbonus > 0) + { + source->toughness = _target->toughness - _target->tbonus; + source->life = _target->toughness - _target->tbonus; + } + else + { + source->toughness = _target->toughness + abs(_target->tbonus); + source->life = _target->toughness + abs(_target->tbonus); + } + } + } else { source->copy(_target); @@ -1573,8 +1593,35 @@ int AACopier::resolve() source->getManaCost()->resetCosts(); } //todo andAbility and tokenandAbility - // - // + if(_target->TokenAndAbility) + {//the source copied a token with andAbility + MTGAbility * TokenandAbilityClone = _target->TokenAndAbility->clone(); + TokenandAbilityClone->target = source; + if(_target->TokenAndAbility->oneShot) + { + TokenandAbilityClone->resolve(); + SAFE_DELETE(TokenandAbilityClone); + } + else + { + TokenandAbilityClone->addToGame(); + } + }/* + if(andAbility) + { + MTGAbility * andAbilityClone = andAbility->clone(); + andAbilityClone->target = source; + if(andAbility->oneShot) + { + andAbilityClone->resolve(); + SAFE_DELETE(andAbilityClone); + } + else + { + andAbilityClone->addToGame(); + } + } + */ return 1; } return 0; diff --git a/projects/mtg/src/MTGCardInstance.cpp b/projects/mtg/src/MTGCardInstance.cpp index 0a2090804..76dadda37 100644 --- a/projects/mtg/src/MTGCardInstance.cpp +++ b/projects/mtg/src/MTGCardInstance.cpp @@ -133,6 +133,7 @@ void MTGCardInstance::copy(MTGCardInstance * card) AICustomCode = data->AICustomCode; origpower = card->origpower;//for flip origtoughness = card->origtoughness;//for flip + TokenAndAbility = card->TokenAndAbility;//token andAbility //Now this is dirty... int backupid = mtgid; From 348ada3f0d7e2d44c46bca70e7df9997780b92c6 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Sun, 29 Jan 2017 16:09:49 +0800 Subject: [PATCH 3/4] revised aacopier I think we still need to change legend to a trigger once it detects multiple legends in play then trigger it at once with targetchooser to select which cards to sacrifice as state based... vector of unique names or id or mtgcardinstance? --- projects/mtg/bin/Res/sets/primitives/mtg.txt | 19 ++++++++++++------- projects/mtg/src/AllAbilities.cpp | 18 +----------------- projects/mtg/src/MTGAbility.cpp | 7 +++++++ 3 files changed, 20 insertions(+), 24 deletions(-) diff --git a/projects/mtg/bin/Res/sets/primitives/mtg.txt b/projects/mtg/bin/Res/sets/primitives/mtg.txt index 5568eb5a0..d0df067b8 100644 --- a/projects/mtg/bin/Res/sets/primitives/mtg.txt +++ b/projects/mtg/bin/Res/sets/primitives/mtg.txt @@ -36781,7 +36781,8 @@ subtype=Aura [/card] [card] name=Evil Twin -auto=may copy NotATarget(creature) and!( transforms((,newability[{U}{B}{T}:destroy target(creature[share!name!])])) forever )! +auto=may copy NotATarget(creature) +auto=while(restriction{copiedacard}) transforms((,newability[{U}{B}{T}:destroy target(creature[share!name!])])) forever text=You may have Evil Twin enter the battlefield as a copy of any creature on the battlefield except it gains "{U}{B}, {T}: Destroy target creature with the same name as this creature." mana={2}{U}{B} type=Creature @@ -45551,7 +45552,8 @@ toughness=1 [/card] [card] name=Gigantoplasm -auto=may copy NotATarget(creature) and!( {X}:name(Base X) transforms((,setpower=X,settoughness=X)) ueot )! +auto=may copy NotATarget(creature) +auto=while(restriction{copiedacard}) {X}:name(Base X) transforms((,setpower=X,settoughness=X)) ueot text=You may have Gigantoplasm enter the battlefield as a copy of any creature on the battlefield except it gains "{X}: This creature has base power and toughness X/X." mana={3}{U} type=Creature @@ -71283,7 +71285,8 @@ toughness=2 [/card] [card] name=Mercurial Pretender -auto=may copy NotATarget(creature) and!( transforms((,newability[{2}{U}{U}:moveto(ownerhand)])) forever )! +auto=may copy NotATarget(creature) +auto=while(restriction{copiedacard}) transforms((,newability[{2}{U}{U}:moveto(ownerhand)])) forever text=You may have Mercurial Pretender enter the battlefield as a copy of any creature you control except it gains "{2}{U}{U}: Return this creature to its owner's hand." mana={4}{U} type=Creature @@ -83959,8 +83962,8 @@ toughness=1 [/card] [card] name=Phantasmal Image -auto=may copy NotATarget(creature) and!( transforms((Illusion)) forever )! -auto=@targeted(this):sacrifice +auto=may copy NotATarget(creature) +auto=while(restriction{copiedacard}) transforms((Illusion,newability[@targeted(this):sacrifice])) forever text=You may have Phantasmal Image enter the battlefield as a copy of any creature on the battlefield, except it's an Illusion in addition to its other types and it gains "When this creature becomes the target of a spell or ability, sacrifice it." mana={1}{U} type=Creature @@ -87229,7 +87232,8 @@ type=Sorcery [/card] [card] name=Progenitor Mimic -auto=may copy NotATarget(creature) and!( transforms((,newability[@each my upkeep:all(this) ifnot cantargetcard(*[token]) then clone])) forever )! +auto=may copy NotATarget(creature) +auto=while(restriction{copiedacard}) transforms((,newability[@each my upkeep:all(this) ifnot cantargetcard(*[token]) then clone])) forever text=You may have Progenitor Mimic enter the battlefield as a copy of any creature on the battlefield except it gains "At the beginning of your upkeep, if this creature isn't a token, put a token onto the battlefield that's a copy of this creature." mana={4}{G}{U} type=Creature @@ -125696,7 +125700,8 @@ toughness=4 [/card] [card] name=Vesuva -auto=may copy notatarget(land) and!( tap(noevent) )! +auto=may copy notatarget(land) +auto=while(restriction{copiedacard}) tap(noevent) text=You may have Vesuva enter the battlefield tapped as a copy of any land on the battlefield. type=Land [/card] diff --git a/projects/mtg/src/AllAbilities.cpp b/projects/mtg/src/AllAbilities.cpp index b1848ab5e..424f3776c 100644 --- a/projects/mtg/src/AllAbilities.cpp +++ b/projects/mtg/src/AllAbilities.cpp @@ -1592,9 +1592,8 @@ int AACopier::resolve() source->basicAbilities.reset(); source->getManaCost()->resetCosts(); } - //todo andAbility and tokenandAbility if(_target->TokenAndAbility) - {//the source copied a token with andAbility + {//the source copied a token with tokenandAbility MTGAbility * TokenandAbilityClone = _target->TokenAndAbility->clone(); TokenandAbilityClone->target = source; if(_target->TokenAndAbility->oneShot) @@ -1606,22 +1605,7 @@ int AACopier::resolve() { TokenandAbilityClone->addToGame(); } - }/* - if(andAbility) - { - MTGAbility * andAbilityClone = andAbility->clone(); - andAbilityClone->target = source; - if(andAbility->oneShot) - { - andAbilityClone->resolve(); - SAFE_DELETE(andAbilityClone); - } - else - { - andAbilityClone->addToGame(); - } } - */ return 1; } return 0; diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 7182617f1..2e8095bd6 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -537,6 +537,13 @@ int AbilityFactory::parseCastRestrictions(MTGCardInstance * card, Player * playe return 0; } + check = restriction[i].find("copiedacard"); + if(check != string::npos) + { + if(!card->isACopier) + return 0; + } + check = restriction[i].find("geared"); if (check != string::npos) { From 166526dbbeca875194d422a115a3f23cd7e2b5c7 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Sun, 29 Jan 2017 16:30:13 +0800 Subject: [PATCH 4/4] Fix Legend Rule Should fix the the move to graveyard effect with targetchooser ability... --- projects/mtg/include/GameObserver.h | 2 -- projects/mtg/src/GameObserver.cpp | 47 ----------------------------- projects/mtg/src/MTGAbility.cpp | 1 - projects/mtg/src/MTGRules.cpp | 12 ++++++++ 4 files changed, 12 insertions(+), 50 deletions(-) diff --git a/projects/mtg/include/GameObserver.h b/projects/mtg/include/GameObserver.h index 48ae903e4..2f520043c 100644 --- a/projects/mtg/include/GameObserver.h +++ b/projects/mtg/include/GameObserver.h @@ -125,8 +125,6 @@ class GameObserver{ void enchantmentStatus(); void Affinity(); bool AffinityNeedsUpdate; - bool foundlegendrule; - void checkLegendary(MTGCardInstance * card); void addObserver(MTGAbility * observer); bool removeObserver(ActionElement * observer); void startGame(GameType, Rules * rules); diff --git a/projects/mtg/src/GameObserver.cpp b/projects/mtg/src/GameObserver.cpp index eb5381452..292eb3d08 100644 --- a/projects/mtg/src/GameObserver.cpp +++ b/projects/mtg/src/GameObserver.cpp @@ -110,7 +110,6 @@ GameObserver::GameObserver(WResourceManager *output, JGE* input) mLayers = NULL; mTrash = new Trash(); mDeckManager = new DeckManager(); - foundlegendrule = false; } GamePhase GameObserver::getCurrentGamePhase() @@ -889,7 +888,6 @@ void GameObserver::gameStateBasedEffects() if(card->life < 1 && !card->has(Constants::INDESTRUCTIBLE)) card->destroy();//manor gargoyle... recheck } - checkLegendary(card); //legendary rule as state based effect } if(card->childrenCards.size()) @@ -1065,51 +1063,6 @@ void GameObserver::gameStateBasedEffects() } } -void GameObserver::checkLegendary(MTGCardInstance * card) -{ - if(!foundlegendrule) - return; - if(card->isPhased||card->has(Constants::NOLEGEND)||card->controller()->opponent()->inPlay()->hasAbility(Constants::NOLEGENDRULE)||card->controller()->inPlay()->hasAbility(Constants::NOLEGENDRULE)) - return; - int destroy = 0; - vectoroldCards; - - MTGGameZone * z = card->controller()->game->inPlay; - int nbcards = z->nb_cards-1; - - for (int r = 0; r < nbcards; r++) - { - MTGCardInstance * comparison = z->cards[r]; - if (comparison != card && comparison->hasType("legendary") && !(comparison->getName().compare(card->getName()))) - { - oldCards.push_back(comparison); - destroy = 1; - } - } - - if(destroy) - { - vectorselection; - MultiAbility * multi = NEW MultiAbility(this, this->mLayers->actionLayer()->getMaxId(), card, card, NULL); - for(unsigned int i = 0;i < oldCards.size();i++) - { - AAMover *a = NEW AAMover(this, this->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(this, this->mLayers->actionLayer()->getMaxId(), card, card,"ownergraveyard","Keep Old"); - b->oneShot = true; - MTGAbility * b1 = b; - selection.push_back(b1); - MTGAbility * menuChoice = NEW MenuAbility(this, this->mLayers->actionLayer()->getMaxId(), card, card,true,selection,card->controller(),"Legendary Rule"); - menuChoice->addToGame(); - } - return; -} - void GameObserver::enchantmentStatus() { for (int i = 0; i < 2; i++) diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 2e8095bd6..b93383c0f 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -1418,7 +1418,6 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG if(found != string::npos) { observer->addObserver(NEW MTGLegendRule(observer, -1)); - //observer->foundlegendrule = true; return NULL; } //this handles the planeswalker named legend rule which is dramatically different from above. diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index e78f1f4b6..bbd92a56f 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -3239,6 +3239,12 @@ int MTGLegendRule::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; @@ -3313,6 +3319,12 @@ 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;