From fbcb1feb88072988dfe81b33d4e88e1e0f54563c Mon Sep 17 00:00:00 2001 From: Vittorio Alfieri Date: Wed, 13 Oct 2021 17:39:48 +0200 Subject: [PATCH] Fixed primitives, fixed "proliferate" target chooser, improved "cycled" and "discarded" triggers, added new keywords "pcycledcount" and "ocycledcount" to calculate how may cards have been cycled this turn from a specific player, added new menu choices to instantly select/deselect and confirm all the possible targets (in any zone) during the target selection of an ability (e.g. Proliferation ability can target a lot of permanents and players so using that menu choice all the targets will be instantly chosen and then the current player will be able to remove any of them or confirm the entire selection). --- CHANGELOG.md | 5 +- .../bin/Res/sets/primitives/borderline.txt | 30 ++++++----- projects/mtg/include/AllAbilities.h | 7 ++- projects/mtg/include/GameStateDuel.h | 3 +- projects/mtg/include/Player.h | 1 + projects/mtg/include/TargetChooser.h | 1 + projects/mtg/src/AIPlayer.cpp | 4 +- projects/mtg/src/AIPlayerBaka.cpp | 1 + projects/mtg/src/ActionLayer.cpp | 2 +- projects/mtg/src/AllAbilities.cpp | 2 + projects/mtg/src/ExtraCost.cpp | 1 + projects/mtg/src/GameObserver.cpp | 7 ++- projects/mtg/src/GameStateDuel.cpp | 53 +++++++++++++------ projects/mtg/src/MTGAbility.cpp | 4 +- projects/mtg/src/Player.cpp | 1 + projects/mtg/src/TargetChooser.cpp | 7 ++- projects/mtg/src/WParsedInt.cpp | 4 ++ 17 files changed, 96 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b81b288a7..4d65b2fa3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,11 @@ ## [master] (https://github.com/WagicProject/wagic/tree/master) +### 13/10/21 +- *Committed:* Fixed primitives, fixed "proliferate" target chooser, improved "cycled" and "discarded" triggers, added new keywords "pcycledcount" and "ocycledcount" to calculate how may cards have been cycled this turn from a specific player, added new menu choices to instantly select/deselect and confirm all the possible targets (in any zone) during the target selection of an ability (e.g. Proliferation ability can target a lot of permanents and players so using that menu choice all the targets will be instantly chosen and then the current player will be able to remove any of them or confirm the entire selection). ([Vitty85](https://github.com/Vitty85)) + ### 12/10/21 -- *Committed:* Fixed and improved the Deck Importer (from MTGO) in Android application. ([Vitty85](https://github.com/Vitty85)) +- *Committed:* Fixed and improved the Deck Importer (from MTGO) in Android application. https://github.com/WagicProject/wagic/commit/371d4c9f857f39b3998872dc2de99c9a3ad52a56 ([Vitty85](https://github.com/Vitty85)) - *Committed:* Added a new menu choice to instantly choose all the possible targets (on battlefield) of an ability during its target selection (e.g. Proliferation ability can target a lot of permanents and players so using that menu choice all the targets will be instantly chosen and then the current player will be able to remove any of them or confirm the entire selection). https://github.com/WagicProject/wagic/commit/c1f391329564a962907c9179c8b6c9b382c6bafb ([Vitty85](https://github.com/Vitty85)) diff --git a/projects/mtg/bin/Res/sets/primitives/borderline.txt b/projects/mtg/bin/Res/sets/primitives/borderline.txt index 672a62a75..b87ae3bf6 100644 --- a/projects/mtg/bin/Res/sets/primitives/borderline.txt +++ b/projects/mtg/bin/Res/sets/primitives/borderline.txt @@ -8691,8 +8691,11 @@ toughness=2 [card] name=Brutal Expulsion abilities=devoid -auto=ability$!name(Choose one) choice name(Return creature) target(creature) moveto(ownerhand) _ choice name(Return spell) target(*|stack) fizzleto(hand) _ choice name(Don't return anything) donothing!$ controller -auto=ability$!may name(Deal 2 damage) target(creature,planeswalker) transforms((,newability[exiledeath],newability[damage:2])) ueot!$ controller +restriction=compare(type:*[creature;planeswalker]:battlefieldplustype:*:stackplusend)~morethan~0 +auto=if type(creature|battlefield)~morethan~0 then choice name(Return creature) name(Return creature) target(creature) moveto(ownerhand) and!( ability$!may name(Deal 2 damage) name(Deal 2 damage) target(*[creature;planeswalker]|battlefield) transforms((,newability[exiledeath],newability[damage:2])) ueot!$ controller )! +auto=if type(*|opponentstack)~morethan~0 then choice name(Return opponent spell) name(Return opponent spell) target(*|opponentstack) transforms((,newability[-nofizzle],newability[-nofizzlealternative],newability[fizzleto(hand)],newability[ability$!may name(Deal 2 damage) name(Deal 2 damage) target(*[creature;planeswalker]|battlefield) transforms((,newability[exiledeath],newability[damage:2])) ueot!$ opponent])) oneshot +auto=if type(*|mystack)~morethan~1 then choice name(Return your spell) name(Return your spell) target(*|mystack) transforms((,newability[-nofizzle],newability[-nofizzlealternative],newability[fizzleto(hand)],newability[ability$!may name(Deal 2 damage) name(Deal 2 damage) target(*[creature;planeswalker]|battlefield) transforms((,newability[exiledeath],newability[damage:2])) ueot!$ controller])) oneshot +auto=if type(*[creature;planeswalker]|battlefield)~morethan~0 then choice name(Don't return and deal 2 damage) name(Don't return and deal 2 damage) target(*[creature;planeswalker]|battlefield) transforms((,newability[exiledeath])) ueot && damage:2 text=Devoid (This card has no color.) -- Choose one or both -- Return target spell or creature to its owner's hand. -- Brutal Expulsion deals 2 damage to target creature or planeswalker. If that permanent would be put into a graveyard this turn, exile it instead. mana={2}{U}{R} type=Instant @@ -17881,9 +17884,10 @@ type=Sorcery [/card] [card] name=Divide by Zero -target=*[manacost>=1]|battlefield -auto=moveto(ownerhand) -auto=name(Learn) transforms((,newability[if type(*[lesson]|mysideboard)~morethan~0 then choice name(Put lesson in hand) name(Put lesson in hand) target(*[lesson]|mysideboard) moveto(myhand)],newability[if type(*|myhand)~morethan~0 then choice name(Discard and draw) name(Discard and draw) target(*|myhand) reject and!(draw:1)!],newability[if type(Retriever Phoenix|mygraveyard)~morethan~0 then choice name(Return a Retriever Phoenix) name(Return a Retriever Phoenix) target(Retriever Phoenix|mygraveyard) moveto(myBattlefield)],newability[choice name(Don't learn) donothing])) oneshot +restriction=compare(type:*:battlefieldplustype:*:stackplusend)~morethan~0 +auto=if type(*[manacost>=1]|battlefield)~morethan~0 then choice name(Return permanent) name(Return permanent) target(*[manacost>=1]|battlefield) moveto(ownerhand) and!( ability$!name(Learn) name(Learn) transforms((,newability[if type(*[lesson]|mysideboard)~morethan~0 then choice name(Put lesson in hand) name(Put lesson in hand) target(*[lesson]|mysideboard) moveto(myhand)],newability[if type(*|myhand)~morethan~0 then choice name(Discard and draw) name(Discard and draw) target(*|myhand) reject and!(draw:1)!],newability[if type(Retriever Phoenix|mygraveyard)~morethan~0 then choice name(Return a Retriever Phoenix) name(Return a Retriever Phoenix) target(Retriever Phoenix|mygraveyard) moveto(myBattlefield)],newability[choice name(Don't learn) donothing])) oneshot!$ controller )! +auto=if type(*|opponentstack)~morethan~0 then choice name(Return opponent spell) name(Return opponent spell) target(*|opponentstack) transforms((,newability[-nofizzle],newability[-nofizzlealternative],newability[fizzleto(hand)],newability[ability$!name(Learn) name(Learn) transforms((,newability[if type(*[lesson]|mysideboard)~morethan~0 then choice name(Put lesson in hand) name(Put lesson in hand) target(*[lesson]|mysideboard) moveto(myhand)],newability[if type(*|myhand)~morethan~0 then choice name(Discard and draw) name(Discard and draw) target(*|myhand) reject and!(draw:1)!],newability[if type(Retriever Phoenix|mygraveyard)~morethan~0 then choice name(Return a Retriever Phoenix) name(Return a Retriever Phoenix) target(Retriever Phoenix|mygraveyard) moveto(myBattlefield)],newability[choice name(Don't learn) donothing])) oneshot!$ opponent])) oneshot +auto=if type(*|mystack)~morethan~1 then choice name(Return your spell) name(Return your spell) target(*|mystack) transforms((,newability[-nofizzle],newability[-nofizzlealternative],newability[fizzleto(hand)],newability[ability$!name(Learn) name(Learn) transforms((,newability[if type(*[lesson]|mysideboard)~morethan~0 then choice name(Put lesson in hand) name(Put lesson in hand) target(*[lesson]|mysideboard) moveto(myhand)],newability[if type(*|myhand)~morethan~0 then choice name(Discard and draw) name(Discard and draw) target(*|myhand) reject and!(draw:1)!],newability[if type(Retriever Phoenix|mygraveyard)~morethan~0 then choice name(Return a Retriever Phoenix) name(Return a Retriever Phoenix) target(Retriever Phoenix|mygraveyard) moveto(myBattlefield)],newability[choice name(Don't learn) donothing])) oneshot!$ controller])) oneshot text=Return target spell or permanent with mana value 1 or greater to its owner's hand. -- Learn. (You may reveal a Lesson card you own from outside the game and put it into your hand, or discard a card to draw a card.) mana={2}{U} type=Instant @@ -22613,7 +22617,7 @@ toughness=2 [/card] [card] name=Failure // Comply -auto=ifnot paid(alternative) then target(*|stack) fizzleto(hand) +auto=ifnot paid(alternative) then target(*|stack) transforms((,newability[-nofizzle],newability[-nofizzlealternative],newability[fizzleto(hand)])) oneshot auto=if paid(alternative) then chooseanameopp maxcast(*[chosenname])0 opponent ueot && phaseaction[upkeep once] maxcast(*[lastnamechosen])0 opponent ueot chooseend nonland autograveyard={W}{E}:name(Comply) activate castcard(alternative) asSorcery text=Return target spell to its owner's hand. -- Aftermath (Cast this spell only from your graveyard. Then exile it.) Choose a card name. Until your next turn, your opponents can't cast spells with the chosen name. @@ -64456,9 +64460,9 @@ toughness=4 [/card] [card] name=Spellpyre Phoenix -abilities=flying,cycling -auto=moveTo(myHand) target(*[instant;sorcery;cycling]|myGraveyard) -autograveyard=if type(@cycled(*|myHand)~morethan~2 then moveTo(myhand) target(Spellpyre Phoenix|myGraveyard)) +abilities=flying +auto=may name(Return instant or sorcery) target(*[instant;sorcery;cycling]|myGraveyard) moveTo(myHand) +autograveyard=@each end restriction{compare(pcycledcount)~morethan~1}:name(Return to hand) moveTo(myhand) text=Flying -- When Spellpyre Phoenix enters the battlefield, you may return target instant or sorcery card with a cycling ability from your graveyard to your hand. -- At the beginning of each end step, if you cycled two or more cards this turn, return Spellpyre Phoenix from your graveyard to your hand. mana={3}{R}{R} type=Creature @@ -73804,8 +73808,9 @@ type=Instant [/card] [card] name=Unsubstantiate -auto=choice name(Return target creature) target(creature|battlefield) moveTo(ownerHand) -auto=choice name(Return target spell) target(*|stack) fizzleto(hand) +restriction=compare(type:creature:battlefieldplustype:*:stackplusend)~morethan~0 +auto=if type(creature|battlefield)~morethan~0 then choice name(Return target creature) name(Return target creature) target(creature|battlefield) moveTo(ownerHand) +auto=if type(*|stack)~morethan~1 then choice name(Return target spell) name(Return target spell) target(*|stack) transforms((,newability[-nofizzle],newability[-nofizzlealternative],newability[fizzleto(hand)])) oneshot text=Return target spell or creature to its owner's hand. mana={1}{U} type=Instant @@ -75014,7 +75019,8 @@ type=Instant [card] name=Venser, Shaper Savant abilities=flash -auto=target(*) moveto(ownerhand) +auto=if type(*|battlefield)~morethan~0 then choice name(Return target permanent) name(Return target permanent) target(*|battlefield) moveTo(ownerHand) +auto=if type(*|stack)~morethan~0 then choice name(Return target spell) name(Return target spell) target(*|stack) transforms((,newability[-nofizzle],newability[-nofizzlealternative],newability[fizzleto(hand)])) oneshot text=Flash (You may cast this spell any time you could cast an instant.) -- When Venser, Shaper Savant enters the battlefield, return target spell or permanent to its owner's hand. mana={2}{U}{U} type=Legendary Creature diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index 2b6c8c769..ff1c4ac11 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -955,8 +955,10 @@ public: class TrCardDiscarded: public Trigger { public: + bool limitOnceATurn; + int triggeredTurn; bool cycledTrigger; - TrCardDiscarded(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc, bool once = false, bool cycledTrigger = false) : + TrCardDiscarded(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc, bool once = false, bool limitOnceATurn = false, bool cycledTrigger = false) : Trigger(observer, id, source, once, tc),cycledTrigger(cycledTrigger) { } @@ -964,6 +966,8 @@ public: int triggerOnEventImpl(WEvent * event) { MTGCardInstance * targetCard = NULL; + if (limitOnceATurn && triggeredTurn == game->turn) + return 0; if(cycledTrigger) { WEventCardCycle * c = dynamic_cast (event); @@ -977,6 +981,7 @@ public: targetCard = e->card; } if (!targetCard || !tc->canTarget(targetCard)) return 0; + triggeredTurn = game->turn; return 1; } diff --git a/projects/mtg/include/GameStateDuel.h b/projects/mtg/include/GameStateDuel.h index 8c744f6a3..c9541166c 100644 --- a/projects/mtg/include/GameStateDuel.h +++ b/projects/mtg/include/GameStateDuel.h @@ -283,7 +283,8 @@ public: /////// End Tournament Mod /////////// MENUITEM_TOGGLEATTACK_ALL_CREATURES = -32, MENUITEM_TASKBOARD = -33, - MENUITEM_SELECT_ALL = -34, + MENUITEM_TOGGLE_SELECT_ALL = -34, + MENUITEM_CONFIRM_SELECT_ALL = -35, MENUITEM_MORE_INFO = kInfoMenuID }; diff --git a/projects/mtg/include/Player.h b/projects/mtg/include/Player.h index 04d82fcf5..b9409ab66 100644 --- a/projects/mtg/include/Player.h +++ b/projects/mtg/include/Player.h @@ -56,6 +56,7 @@ public: int dealsdamagebycombat; int initLife; int raidcount; + int cycledCount; int handmodifier; int snowManaG; int snowManaR; diff --git a/projects/mtg/include/TargetChooser.h b/projects/mtg/include/TargetChooser.h index b1f48f29e..23df152ae 100644 --- a/projects/mtg/include/TargetChooser.h +++ b/projects/mtg/include/TargetChooser.h @@ -44,6 +44,7 @@ public: MTGCardInstance * targetter; //Optional, usually equals source, used for protection from... int maxtargets; bool done; + bool autoChoice; // added to allow choice from game menu. bool targetMin; bool validTargetsExist(int maxTarget = 1); int attemptsToFill; diff --git a/projects/mtg/src/AIPlayer.cpp b/projects/mtg/src/AIPlayer.cpp index dc2c8689f..2c0fb2761 100644 --- a/projects/mtg/src/AIPlayer.cpp +++ b/projects/mtg/src/AIPlayer.cpp @@ -109,8 +109,10 @@ int AIAction::clickMultiAct(vector& actionTargets) { if (MTGCardInstance * card = dynamic_cast(actionTargets[k])) { - if(k+1 == int(actionTargets.size())) + if(k+1 == int(actionTargets.size())){ tc->done = true; + tc->autoChoice = false; + } g->cardClick(card); } } diff --git a/projects/mtg/src/AIPlayerBaka.cpp b/projects/mtg/src/AIPlayerBaka.cpp index 08ddae0f6..29a6cc0b9 100644 --- a/projects/mtg/src/AIPlayerBaka.cpp +++ b/projects/mtg/src/AIPlayerBaka.cpp @@ -1972,6 +1972,7 @@ int AIPlayerBaka::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, Rank if(a->getActionTc()->getNbTargets() && a->getActionTc()->attemptsToFill > 4) { a->getActionTc()->done = true; + a->getActionTc()->autoChoice = false; return 0; } while(potentialTargets.size()) diff --git a/projects/mtg/src/ActionLayer.cpp b/projects/mtg/src/ActionLayer.cpp index dffe260c6..84549bdb4 100644 --- a/projects/mtg/src/ActionLayer.cpp +++ b/projects/mtg/src/ActionLayer.cpp @@ -191,7 +191,7 @@ void ActionLayer::Update(float dt) without this, the game locks into a freeze state while you try to select the targets and dont have enough to fill the maxtargets list. */ - if (int(ae->getActionTc()->getNbTargets()) == countTargets)//if the amount of targets is equal the all we can target + if (int(ae->getActionTc()->getNbTargets()) == countTargets && !ae->getActionTc()->autoChoice)//if the amount of targets is equal the all we can target { ae->getActionTc()->done = true;//were done ae->getActionTc()->source->getObserver()->cardClick(ae->getActionTc()->source, 0, false);//click source. diff --git a/projects/mtg/src/AllAbilities.cpp b/projects/mtg/src/AllAbilities.cpp index 873264f7f..6dd4e6e82 100644 --- a/projects/mtg/src/AllAbilities.cpp +++ b/projects/mtg/src/AllAbilities.cpp @@ -441,6 +441,7 @@ bool MTGRevealingCards::CheckUserInput(JButton key) if (tc && (tc->targetMin == false || tc->maxtargets == TargetChooser::UNLITMITED_TARGETS)) { tc->done = true; + tc->autoChoice = false; tc->forceTargetListReadyByPlayer = 1; //this is for when we have targets but only want to move Y targets, it allows us to //tell the targetchooser we are done. @@ -749,6 +750,7 @@ bool MTGScryCards::CheckUserInput(JButton key) if (tc && (tc->targetMin == false || tc->maxtargets == TargetChooser::UNLITMITED_TARGETS)) { tc->done = true; + tc->autoChoice = false; tc->forceTargetListReadyByPlayer = 1; if (!abilitySecond && !tc->getNbTargets() && tc->source) { diff --git a/projects/mtg/src/ExtraCost.cpp b/projects/mtg/src/ExtraCost.cpp index 4d3b64a35..66261a796 100644 --- a/projects/mtg/src/ExtraCost.cpp +++ b/projects/mtg/src/ExtraCost.cpp @@ -513,6 +513,7 @@ int CycleCost::doPay() WEvent * e2 = NEW WEventCardCycle(_source); game->receiveEvent(e2); _source->controller()->game->putInGraveyard(_source); + _source->controller()->cycledCount++; if (tc) tc->initTargets(); return 1; diff --git a/projects/mtg/src/GameObserver.cpp b/projects/mtg/src/GameObserver.cpp index 0eac4a0d7..26e106ca2 100644 --- a/projects/mtg/src/GameObserver.cpp +++ b/projects/mtg/src/GameObserver.cpp @@ -215,8 +215,10 @@ void GameObserver::nextGamePhase() currentPlayer->nonCombatDamage = 0; currentPlayer->drawCounter = 0; currentPlayer->raidcount = 0; + currentPlayer->cycledCount = 0; currentPlayer->dealsdamagebycombat = 0; //clear check for restriction currentPlayer->opponent()->raidcount = 0; + currentPlayer->opponent()->cycledCount = 0; currentPlayer->prowledTypes.clear(); currentPlayer->opponent()->damageCount = 0; //added to clear odcount currentPlayer->opponent()->nonCombatDamage = 0; @@ -322,6 +324,7 @@ void GameObserver::userRequestNextGamePhase(bool allowInterrupt, bool log) if(getCurrentTargetChooser() && getCurrentTargetChooser()->maxtargets == 1000) { getCurrentTargetChooser()->done = true; + getCurrentTargetChooser()->autoChoice = false; if(getCurrentTargetChooser()->source) cardClick(getCurrentTargetChooser()->source, 0, false); } @@ -613,8 +616,10 @@ void GameObserver::Update(float dt) //Handles game state based effects void GameObserver::gameStateBasedEffects() { - if(getCurrentTargetChooser() && int(getCurrentTargetChooser()->getNbTargets()) == getCurrentTargetChooser()->maxtargets) + if(getCurrentTargetChooser() && int(getCurrentTargetChooser()->getNbTargets()) == getCurrentTargetChooser()->maxtargets){ getCurrentTargetChooser()->done = true; + getCurrentTargetChooser()->autoChoice = false; + } ///////////////////////////////////// for (int d = 0; d < 2; d++) { diff --git a/projects/mtg/src/GameStateDuel.cpp b/projects/mtg/src/GameStateDuel.cpp index 454e7e0ad..1d21fe150 100644 --- a/projects/mtg/src/GameStateDuel.cpp +++ b/projects/mtg/src/GameStateDuel.cpp @@ -959,8 +959,14 @@ void GameStateDuel::Update(float dt) if(game->getCurrentGamePhase() == MTG_PHASE_COMBATATTACKERS && game->currentlyActing() == (Player*)game->currentPlayer){ // During attack phase it shows a button to toggle all creatures to attack mode menu->Add(MENUITEM_TOGGLEATTACK_ALL_CREATURES, "Toggle Attack all Creatures"); } - if(game->getCurrentTargetChooser() && game->getCurrentTargetChooser()->source->controller() == game->currentlyActing()) - menu->Add(MENUITEM_SELECT_ALL, "Select all possible targets"); + if(game->getCurrentTargetChooser() && game->getCurrentTargetChooser()->source->controller() == game->currentlyActing()){ + if(game->getCurrentTargetChooser()->getNbTargets() < 1) + menu->Add(MENUITEM_TOGGLE_SELECT_ALL, "Select all Targets"); + else { + menu->Add(MENUITEM_TOGGLE_SELECT_ALL, "Remove Selection"); + menu->Add(MENUITEM_CONFIRM_SELECT_ALL, "Confirm Selection"); + } + } menu->Add(MENUITEM_MAIN_MENU, "Back to main menu"); #ifdef TESTSUITE menu->Add(MENUITEM_UNDO, "Undo"); @@ -1712,20 +1718,37 @@ void GameStateDuel::ButtonPressed(int controllerId, int controlId) menu->Close(); setGamePhase(DUEL_STATE_CANCEL); break; - case MENUITEM_SELECT_ALL: - if(game->getCurrentTargetChooser() && game->getCurrentTargetChooser()->source && game->getCurrentTargetChooser()->source->isInPlay(game) && game->getCurrentTargetChooser()->canTarget(game->getCurrentTargetChooser()->source)) - game->cardClick(game->getCurrentTargetChooser()->source, game->getCurrentTargetChooser()->source); - if(game->getCurrentTargetChooser() && game->getCurrentTargetChooser()->canTarget(game->players[0])) - game->cardClick(NULL, game->players[0]); - if(game->getCurrentTargetChooser() && game->getCurrentTargetChooser()->canTarget(game->players[1])) - game->cardClick(NULL, game->players[1]); - for(unsigned int i = 0; i < game->players[1]->inPlay()->cards.size(); i++){ - if(game->getCurrentTargetChooser() && game->getCurrentTargetChooser()->canTarget(game->players[1]->inPlay()->cards[i])) - game->cardClick(game->players[1]->inPlay()->cards[i], game->players[1]->inPlay()->cards[i]); + case MENUITEM_TOGGLE_SELECT_ALL: + if(game->getCurrentTargetChooser() && game->getCurrentTargetChooser()->getNbTargets() < 1){ + for (int j = 0; j < 2; ++j){ + if(game->getCurrentTargetChooser()->canTarget(game->players[j]) && game->getCurrentTargetChooser()->getNbTargets() < (unsigned int) game->getCurrentTargetChooser()->maxtargets) + game->getCurrentTargetChooser()->addTarget(game->players[j]); + MTGGameZone * zones[] = { game->players[j]->game->inPlay, game->players[j]->game->graveyard, game->players[j]->game->hand, game->players[j]->game->library, game->players[j]->game->exile, game->players[j]->game->stack, game->players[j]->game->commandzone, game->players[j]->game->sideboard, game->players[j]->game->reveal }; + for (int k = 0; k < 9; k++){ + for(unsigned int i = 0; i < zones[k]->cards.size(); i++){ + if(game->getCurrentTargetChooser()->canTarget(zones[k]->cards[i]) && game->getCurrentTargetChooser()->getNbTargets() < (unsigned int) game->getCurrentTargetChooser()->maxtargets) + game->getCurrentTargetChooser()->addTarget(zones[k]->cards[i]); + } + } + } + if(game->getCurrentTargetChooser()){ + game->getCurrentTargetChooser()->done = false; + game->getCurrentTargetChooser()->autoChoice = true; + } + } else if(game->getCurrentTargetChooser()){ + game->getCurrentTargetChooser()->initTargets(); + game->getCurrentTargetChooser()->done = false; + game->getCurrentTargetChooser()->autoChoice = false; } - for(unsigned int i = 0; i < game->players[0]->inPlay()->cards.size(); i++){ - if(game->getCurrentTargetChooser() && game->getCurrentTargetChooser()->source != game->players[0]->inPlay()->cards[i] && game->getCurrentTargetChooser()->canTarget(game->players[0]->inPlay()->cards[i])) - game->cardClick(game->players[0]->inPlay()->cards[i], game->players[0]->inPlay()->cards[i]); + menu->Close(); + setGamePhase(DUEL_STATE_CANCEL); + break; + case MENUITEM_CONFIRM_SELECT_ALL: + if(game->getCurrentTargetChooser()){ + game->getCurrentTargetChooser()->done = true; + game->getCurrentTargetChooser()->autoChoice = false; + if(game->getCurrentTargetChooser()->source) + game->cardClick(game->getCurrentTargetChooser()->source, game->getCurrentTargetChooser()->source); } menu->Close(); setGamePhase(DUEL_STATE_CANCEL); diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 4f5fbd789..60a8f1b1a 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -1353,11 +1353,11 @@ TriggeredAbility * AbilityFactory::parseTrigger(string s, string, int id, Spell //Card is Discarded if (TargetChooser * tc = parseSimpleTC(s, "discarded", card)) - return NEW TrCardDiscarded(observer, id, card, tc, once); + return NEW TrCardDiscarded(observer, id, card, tc, once, limitOnceATurn); //Card is cycled if (TargetChooser * tc = parseSimpleTC(s, "cycled", card)) - return NEW TrCardDiscarded(observer, id, card, tc, once, true); + return NEW TrCardDiscarded(observer, id, card, tc, once, limitOnceATurn, true); //Card Damaging non combat current controller if (TargetChooser * tc = parseSimpleTC(s, "noncombatdamageof", card)) diff --git a/projects/mtg/src/Player.cpp b/projects/mtg/src/Player.cpp index c5583a51e..2ae7f23f2 100644 --- a/projects/mtg/src/Player.cpp +++ b/projects/mtg/src/Player.cpp @@ -47,6 +47,7 @@ Player::Player(GameObserver *observer, string file, string fileSmall, MTGDeck * forcefield = 0; dealsdamagebycombat = 0; raidcount = 0; + cycledCount = 0; handmodifier = 0; snowManaG = 0; snowManaR = 0; diff --git a/projects/mtg/src/TargetChooser.cpp b/projects/mtg/src/TargetChooser.cpp index 7e918d8a0..7db6076f4 100644 --- a/projects/mtg/src/TargetChooser.cpp +++ b/projects/mtg/src/TargetChooser.cpp @@ -1241,6 +1241,7 @@ TargetChooser::TargetChooser(GameObserver *observer, MTGCardInstance * card, int other = _other; targetMin = _targetMin; done = false; + autoChoice = false; attemptsToFill = 0; if(source) Owner = source->controller(); @@ -2201,7 +2202,9 @@ bool ProliferateChooser::canTarget(Targetable * target, bool withoutProtections) } else if (MTGCardInstance * card = dynamic_cast(target)) { - if (source && card->isInPlay(observer) && !withoutProtections) + if(!observer || !card->isInPlay(observer)) + return false; + if (source && !withoutProtections) { if (card->has(Constants::SHROUD)) return source->bypassTC; if (card->protectedAgainst(source)) return source->bypassTC; @@ -2212,7 +2215,7 @@ bool ProliferateChooser::canTarget(Targetable * target, bool withoutProtections) return source->bypassTC; } } - if(card->counters && card->counters->counters.empty()) + if(!card->counters || (card->counters && card->counters->counters.empty())) return false; return true; } diff --git a/projects/mtg/src/WParsedInt.cpp b/projects/mtg/src/WParsedInt.cpp index 9bfec825a..6019320dc 100644 --- a/projects/mtg/src/WParsedInt.cpp +++ b/projects/mtg/src/WParsedInt.cpp @@ -1157,6 +1157,10 @@ void WParsedInt::init(string s, Spell * spell, MTGCardInstance * card) intValue++; } } + else if (s == "pcycledcount" || s == "ocycledcount") //return how may cards have been cycled this turn from a specific player. + { + intValue = (s == "pcycledcount")?card->controller()->cycledCount:card->controller()->opponent()->cycledCount; + } else //Continue parsing in another method to avoid compiler C1061 error. { extendedParse(s, spell, card);