From 33e1e03288bd2b42b7e8da444c28cc30dba7b69f Mon Sep 17 00:00:00 2001 From: cg5 Date: Sun, 18 Sep 2016 16:07:21 +0200 Subject: [PATCH 01/50] Fix Aetherborn Marauder's ability --- .../sets/kaladesh/AetherbornMarauder.java | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/Mage.Sets/src/mage/sets/kaladesh/AetherbornMarauder.java b/Mage.Sets/src/mage/sets/kaladesh/AetherbornMarauder.java index 3d76d931f36..3d1a8308e72 100644 --- a/Mage.Sets/src/mage/sets/kaladesh/AetherbornMarauder.java +++ b/Mage.Sets/src/mage/sets/kaladesh/AetherbornMarauder.java @@ -101,7 +101,7 @@ class AetherbornMarauderEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); Permanent sourceObject = game.getPermanent(source.getSourceId()); if (controller != null && sourceObject != null) { - FilterControlledPermanent filter = new FilterControlledPermanent("permanent you control from where you like to remove +1/+1 counters"); + FilterControlledPermanent filter = new FilterControlledPermanent("permanent you control to remove +1/+1 counters from"); filter.add(new AnotherPredicate()); filter.add(new CounterPredicate(CounterType.P1P1)); boolean firstRun = true; @@ -109,16 +109,19 @@ class AetherbornMarauderEffect extends OneShotEffect { if (controller.chooseUse(outcome, "Move " + (firstRun ? "any" : "more") + " +1/+1 counters from other permanents you control to " + sourceObject.getLogName() + "?", source, game)) { firstRun = false; TargetControlledPermanent target = new TargetControlledPermanent(filter); - Permanent fromPermanent = game.getPermanent(target.getFirstTarget()); - if (fromPermanent != null) { - int numberOfCounters = fromPermanent.getCounters(game).getCount(CounterType.P1P1); - int numberToMove = 1; - if (numberOfCounters > 1) { - numberToMove = controller.getAmount(0, numberOfCounters, "How many +1/+1 counters do you want to move?", game); - } - if (numberToMove > 0) { - fromPermanent.removeCounters(CounterType.P1P1.createInstance(numberToMove), game); - sourceObject.addCounters(CounterType.P1P1.createInstance(numberToMove), game); + target.setNotTarget(true); + if (target.choose(Outcome.Neutral, source.getControllerId(), source.getSourceId(), game)) { + Permanent fromPermanent = game.getPermanent(target.getFirstTarget()); + if (fromPermanent != null) { + int numberOfCounters = fromPermanent.getCounters(game).getCount(CounterType.P1P1); + int numberToMove = 1; + if (numberOfCounters > 1) { + numberToMove = controller.getAmount(0, numberOfCounters, "How many +1/+1 counters do you want to move?", game); + } + if (numberToMove > 0) { + fromPermanent.removeCounters(CounterType.P1P1.createInstance(numberToMove), game); + sourceObject.addCounters(CounterType.P1P1.createInstance(numberToMove), game); + } } } } else { From ed7378da6620781fe8b2a173835400ddf9b0a65a Mon Sep 17 00:00:00 2001 From: Get Date: Sun, 18 Sep 2016 17:10:54 +0300 Subject: [PATCH 02/50] Player Panel UI redesign (new icons, new colors, new buttons) --- .../mage/client/components/MageRoundPane.java | 2 +- .../main/java/mage/client/game/GamePanel.java | 12 +++++----- .../java/mage/client/game/PlayerPanelExt.java | 21 +++++++++--------- .../src/main/resources/buttons/blank.png | Bin 8378 -> 20512 bytes .../main/resources/buttons/cancel_skip.png | Bin 2536 -> 22467 bytes .../src/main/resources/buttons/concede.png | Bin 1968 -> 22315 bytes .../src/main/resources/buttons/skip_all.png | Bin 2351 -> 22318 bytes .../src/main/resources/buttons/skip_stack.png | Bin 2440 -> 22558 bytes .../main/resources/buttons/skip_to_end.png | Bin 2399 -> 22382 bytes .../main/resources/buttons/skip_to_main.png | Bin 2478 -> 22369 bytes .../buttons/skip_to_previous_end.png | Bin 2351 -> 22494 bytes .../src/main/resources/buttons/skip_turn.png | Bin 2321 -> 22331 bytes .../main/resources/buttons/stop_watching.png | Bin 2505 -> 23029 bytes .../main/resources/buttons/switch_hands.png | Bin 2363 -> 22913 bytes .../src/main/resources/info/command_zone.png | Bin 6247 -> 20510 bytes Mage.Client/src/main/resources/info/exile.png | Bin 19202 -> 21932 bytes Mage.Client/src/main/resources/info/grave.png | Bin 8911 -> 20434 bytes Mage.Client/src/main/resources/info/hand.png | Bin 926 -> 20409 bytes .../src/main/resources/info/library.png | Bin 5040 -> 21715 bytes Mage.Client/src/main/resources/info/life.png | Bin 721 -> 21491 bytes .../src/main/resources/info/poison.png | Bin 470 -> 21323 bytes 21 files changed, 17 insertions(+), 18 deletions(-) diff --git a/Mage.Client/src/main/java/mage/client/components/MageRoundPane.java b/Mage.Client/src/main/java/mage/client/components/MageRoundPane.java index da4afed58e1..65fda45f640 100644 --- a/Mage.Client/src/main/java/mage/client/components/MageRoundPane.java +++ b/Mage.Client/src/main/java/mage/client/components/MageRoundPane.java @@ -27,7 +27,7 @@ public class MageRoundPane extends JPanel { private int X_OFFSET = 30; private int Y_OFFSET = 30; - private final Color defaultBackgroundColor = new Color(255, 255, 255, 200); + private final Color defaultBackgroundColor = new Color(141, 130, 112, 200); private Color backgroundColor = defaultBackgroundColor; private final int alpha = 0; private static Map SHADOW_IMAGE_CACHE; diff --git a/Mage.Client/src/main/java/mage/client/game/GamePanel.java b/Mage.Client/src/main/java/mage/client/game/GamePanel.java index 3597ba0b40f..5d7ec878aac 100644 --- a/Mage.Client/src/main/java/mage/client/game/GamePanel.java +++ b/Mage.Client/src/main/java/mage/client/game/GamePanel.java @@ -916,33 +916,33 @@ public final class GamePanel extends javax.swing.JPanel { private void updateSkipButtons(boolean turn, boolean endOfTurn, boolean nextMain, boolean allTurns, boolean stack, boolean endStepBeforeYourStep) { if (turn) { //F4 - btnSkipToNextTurn.setBorder(new LineBorder(Color.red, BORDER_SIZE)); + btnSkipToNextTurn.setBorder(new LineBorder(Color.orange, BORDER_SIZE)); } else { btnSkipToNextTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); } if (endOfTurn) { // F5 - btnSkipToEndTurn.setBorder(new LineBorder(Color.red, BORDER_SIZE)); + btnSkipToEndTurn.setBorder(new LineBorder(Color.orange, BORDER_SIZE)); } else { btnSkipToEndTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); } if (nextMain) { // F7 - btnSkipToNextMain.setBorder(new LineBorder(Color.red, BORDER_SIZE)); + btnSkipToNextMain.setBorder(new LineBorder(Color.orange, BORDER_SIZE)); } else { btnSkipToNextMain.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); } if (stack) { // F8 - btnSkipStack.setBorder(new LineBorder(Color.red, BORDER_SIZE)); + btnSkipStack.setBorder(new LineBorder(Color.orange, BORDER_SIZE)); } else { btnSkipStack.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); } if (allTurns) { // F9 - btnSkipToYourTurn.setBorder(new LineBorder(Color.red, BORDER_SIZE)); + btnSkipToYourTurn.setBorder(new LineBorder(Color.orange, BORDER_SIZE)); } else { btnSkipToYourTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); } if (endStepBeforeYourStep) { // F11 - btnSkipToEndStepBeforeYourTurn.setBorder(new LineBorder(Color.red, BORDER_SIZE)); + btnSkipToEndStepBeforeYourTurn.setBorder(new LineBorder(Color.orange, BORDER_SIZE)); } else { btnSkipToEndStepBeforeYourTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); } diff --git a/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java b/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java index 67484a2f361..baf41b67ff2 100644 --- a/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java +++ b/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java @@ -110,11 +110,11 @@ public class PlayerPanelExt extends javax.swing.JPanel { private static final int PANEL_HEIGHT_SMALL = 212; private static final int MANA_LABEL_SIZE_HORIZONTAL = 20; - private static final Border GREEN_BORDER = new LineBorder(Color.green, 3); + private static final Border GREEN_BORDER = new LineBorder(Color.white, 3); private static final Border RED_BORDER = new LineBorder(Color.red, 2); private static final Border EMPTY_BORDER = BorderFactory.createEmptyBorder(0, 0, 0, 0); - private final Color greenBackgroundColor = new Color(180, 255, 180, 200); - private final Color deadBackgroundColor = new Color(200, 180, 180, 200); + private final Color greenBackgroundColor = new Color(206, 192, 174, 200); + private final Color deadBackgroundColor = new Color(131, 94, 83, 200); private int avatarId = -1; private String flagName; @@ -430,7 +430,7 @@ public class PlayerPanelExt extends javax.swing.JPanel { // Poison count poisonLabel.setText("0"); - r = new Rectangle(14, 14); + r = new Rectangle(18, 18); poisonLabel.setToolTipText("Poison"); Image imagePoison = ImageHelper.getImageFromResources("/info/poison.png"); BufferedImage resizedPoison = ImageHelper.getResizedImage(BufferedImageBuilder.bufferImage(imagePoison, BufferedImage.TYPE_INT_ARGB), r); @@ -650,8 +650,7 @@ public class PlayerPanelExt extends javax.swing.JPanel { .addGap(9) .addGroup(gl_panelBackground.createParallelGroup(Alignment.LEADING) .addGroup(gl_panelBackground.createSequentialGroup() - .addGap(3) - .addComponent(poison, GroupLayout.PREFERRED_SIZE, 14, GroupLayout.PREFERRED_SIZE)) + .addComponent(poison, GroupLayout.PREFERRED_SIZE, 18, GroupLayout.PREFERRED_SIZE)) .addGroup(gl_panelBackground.createSequentialGroup() .addGap(2) .addComponent(btnWhiteMana, GroupLayout.PREFERRED_SIZE, 15, GroupLayout.PREFERRED_SIZE)) @@ -720,7 +719,7 @@ public class PlayerPanelExt extends javax.swing.JPanel { .addComponent(avatar, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 80, Short.MAX_VALUE)) // .addGroup(gl_panelBackground.createSequentialGroup() // .addComponent(avatarFlag, GroupLayout.PREFERRED_SIZE, 16, GroupLayout.PREFERRED_SIZE)) - .addGap(14)) + .addGap(8)) .addGroup(gl_panelBackground.createSequentialGroup() .addGap(6) .addComponent(zonesPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE) @@ -734,7 +733,7 @@ public class PlayerPanelExt extends javax.swing.JPanel { .addPreferredGap(ComponentPlacement.RELATED) .addComponent(btnPlayer) .addComponent(timerLabel) - .addGap(1) + .addGap(2) // Life & Hand .addGroup(gl_panelBackground.createParallelGroup(Alignment.LEADING) .addGroup(gl_panelBackground.createSequentialGroup() @@ -749,15 +748,15 @@ public class PlayerPanelExt extends javax.swing.JPanel { // Poison .addGroup(gl_panelBackground.createParallelGroup(Alignment.LEADING) .addGroup(gl_panelBackground.createSequentialGroup() - .addGap(4) - .addComponent(poison, GroupLayout.PREFERRED_SIZE, 14, GroupLayout.PREFERRED_SIZE) + .addGap(2) + .addComponent(poison, GroupLayout.PREFERRED_SIZE, 18, GroupLayout.PREFERRED_SIZE) .addGap(4) .addComponent(btnWhiteMana, GroupLayout.PREFERRED_SIZE, 15, GroupLayout.PREFERRED_SIZE) .addGap(2) .addComponent(btnBlueMana, GroupLayout.PREFERRED_SIZE, 15, GroupLayout.PREFERRED_SIZE) .addGap(2) .addComponent(btnBlackMana, GroupLayout.PREFERRED_SIZE, 15, GroupLayout.PREFERRED_SIZE) - .addGap(5) + .addGap(3) .addComponent(grave, GroupLayout.PREFERRED_SIZE, 21, GroupLayout.PREFERRED_SIZE) ) .addGroup(gl_panelBackground.createSequentialGroup() diff --git a/Mage.Client/src/main/resources/buttons/blank.png b/Mage.Client/src/main/resources/buttons/blank.png index 3dcfd353236bc59642c052f2812751951767e704..d61587dfe5d149dbc422c20b54b5c11577270287 100644 GIT binary patch literal 20512 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 literal 8378 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 delta 1948 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 delta 2334 zcmV+(3E}pxt^uzSkSl)MP0uiS*Z0B{{gT}B$dj^w*)Yl8RAcm1T4 zP~Jq|k%3r{3E2jj1P#Vy{%_e+=R1{Y8KB~o56&@1VQ+t3C+St+ATTnM45*Aljl#I+ zX-!%ojhBoW4>?tzP;7DNW{TOr;s*I2whgJyP&766C@~-lG7%dxK4Vj1RJ6_5n@5Y5 zb1IlDDSz!P3@|j{SdTRV#VtIgkn2kdavXTnehJMkz~! zE?dvv18(uB1ceqgL+Y^(1^KMqE=&L)ORBgcKzRivfJ6@F8=KW{e{l_zF$=$`X^ahj=#^9ti*{TTwD_${5P9G_#2@Z}gvw6RYil_3BUzJt?DaIxxb&qd z)b|ccr@q51A7M;i=^C2R7#z#TW-W`Q*o?&y)SuwCfckh$ti`wex0X}e%HEmA@e>fe z?>u=$&*)vuf^5i$tnwS8aQYiCM&7Yf*OY(n-Y9H^!89|FgVQmT2r<93k0_?4ZwdiB zFM{2y<+vzSfK(35(E|c=KL#T!d+N_yUkc-07IKq1I~XRU_B4|Ty{@(RnQgXtMtD8#2Oh!Bj>sV#rC zg{Yz{&#Z&{<2bCx$JUj0faPzdDb%r>KA&=)!RbQGP%@S~rt%yvpqkmQY)_w=p%n7?<8y} zl!2y>o)8;pYz`?E&Cr(z8Ie_d32-+--O05)U>&Uj0pBEau~jWi%f5 z8>+I|{dvGSD5Btd{Jb{YZJI#d3KYUBtThBdzO(a&-#~k*zmdaphWD+-FYz{v|x8~EQuD%ib zJHVFOBeb-kK-MYL8%+H1P;&#Kz;{g|tV!QbIf*q_b6Z&hq#wCNZ4G}-Z3PBoLq=p3 zKL#23qF{`!rDs;`p1LRRxBnCRYH1V)^zyV>P}}v0RC4ZfikVuBratDdzx}-iSQ(ST zJ*P+8z_yYaINtH#=_$KoAB=ODLhW_gB|<&ap4w(u9-U0eWb24?{PD!%{jA=cDNL%q zv6+w;Gawr>BCB{IBrJc08BJ?XSHGl=L!b6Q%^x2rXoVceak@J+-0me+G~J|_nRGPu zF^BzKRc9b@<2Gt9jo2uR=S^XIj^8S3Z`xfdn@C;oBji(Y?_{pGQsfDIhbq#5pT zq2~$dMB6QjscVdY=#1TS?vk;QNjmJ-ZEN>p$ z^ZdC9NGU2)sP{Zow{;6Our1CVYv}^%*l|LB;&czFYQ0O|kp-EMjTi^`IsEj62*XGi zbrTmS@9@f<)yjYsdPn1~6HSlazy3Ekefu#T;P-a{8vi;xgkI1SdP9%s6+NSO zWFVFyz7&5|d@ar}hODd@)sas6635r)1Z*q|*;>?;eBi_G9hK+qe!epeOW( z9?>g$Chr`B+W-E?2sd*^w02ffv0+qoo!C>#ol!TQ&B|+-Xf}C5Z|IR*=Nrkrzo37J zxLMR@rO(P(zLXqJGM0POmU~tHA^s!$#r`?^v)vZ{3rQEO`>Y?vRsaA107*qoM6N<$ Ef{&zzS^xk5 diff --git a/Mage.Client/src/main/resources/buttons/skip_stack.png b/Mage.Client/src/main/resources/buttons/skip_stack.png index 40597cfb64fed8491cb760927fa4098411ce4400..06816b1f3935511e136778c565c6b4140c031715 100644 GIT binary patch literal 22558 zcmeI42{@G7|GtYKu(m~55I%4C@_GqRV&?NTXA?!8hf+f^aA zO$(`8RKzVM?NX>z>Z&B$?;T6tq^5iO{r^3`=b3q)F~>RI@AsVV=bZC>zwddU=Z$xE zv{hD`sRV&Ql*xA1RN&Vf_`(#%1Aq7JS{DoaDDv$*gb>I?HSt#llAbXG0+GRSt*o4# zeR(3D(3i)Dk*%y?d;yQc^=CsMp|=YXi|zk(RyVKRysybwPcDcbnzCrov1i^D+3+RM zgEurU)o1Uu=c;;n-B=f!wPM2bkTd0%mhqi?Wc$s7o;5->H*Qqe{q*ji&4RPPHw5R= zQ|VB@8-c`YZzBoa=O?*9{!%=AJ@BXsq)9vR{n=JM*~YNCLSyB=ipXCVD?3EL2uzKG zEjI7B%$s?B26E%N{T6p+a*5oV<|dFFua^jO-HW}-i*#>xSVTfNwQnPlEfCDbD0yVC zC|_m`nMn01b%7s9W0OzqluI(1%O=ib3CvW~b}ZPRm1VHKe?mEJH>&>sRr_N}> zxGYmGH$w`N!nb1ka_zzeY?p9H8Z+FFNnmN2k(5kAiGYCswulZ34e$>X5<^Y32J8}n zvbY+d1sf0%`I%~2h&zP2Q=DN|JOLYKXn=z=Q79D5h+u#+#ADEg`Y<#SWr#o$5GW)Z zi6WwqL^KjM^wA>Z!uf+nhV59hg-ijLFXHk7VPd;<1}|7-s--3F=;LR|uK@nXjsk^4 z>;Q_0P&yxhGC(56QerVb>hOaF{sTi}F%fKkb^tq2Bn0$OW9k7&DU^?@V|Eu1Fs7zZ zv}7&d!4Q!#HHEY=J{v)03wgl;CVRYm+MHp0m6-VdBPUC zaRXVr5TULKVzkQ0!Wpr~wx)~NBtR1fM-t#D91VpfBJo6wkscC5L?S^(1|>(?pa7eQ zMHkUOwSuRi42fto5rYF;`9yZK9UhCz3Hv51Ba$E+EGCh|69mvjByIrRhmGI|`j{X_ zDnXJ1tCvU)6pHA9Og7n?1XLJsxhx`!#bFb$NCw;p$L7EZI4m1ZC*T-xBo>Wk)0r$Z zlE4|jL7{-vKQnF3V+M;i5MX*R*06X?!2HLBM8q?VaA-8z2yVn8(BUW)8waPeSxh(s zgJ*Ft977HpgCFh)WbCt!oCI7T6w>`cGGbp?Kxal+EW;3QNPsg~cmf=Q$I{^pBnyaI zcml?dj%6}f?2o>TVdk^0?6^W;-GzbHBd{t5f}IOH=+oNa27m5A(BjhtLbiBMn`#Yj z>W@+GV-OST48#T^ohc4?B&K+wvsosHPijYo^-*(3jr;j@ej9>8`yll%_YvaD4*c3i z88kH@^<^VM9!C^H7qBgSfEDsBdw9_5r)s0kn;^uO2Y>GW!9)n@Yrk(A@GL_^G!t0o zXhRMPjy1&M;dDG61vg?4=tvA5!(483M76~!z z*>J`G(##Qnc!V>equ^)`)(DPcVL5OHii3yaPz)v>!$BEwkc46X{>99FevOdM+)(i2 z1+HZa{z>=)f-D_KXW0TFi6h_z!03FwKbJ`thf>7aK-N$``0)w^6Y*f6%j6(;kd6Px zRmx%uxc?-=fJVt2#svEx^ZC1D>bGSogVQSAnS;5);5G8oY-Kpf`aHW4=f^;rXFa$& zZNz&@e2JBu%mDcaaHBy4Q6Ek(zcrkWQvYNx4p|2h%CBdb1P+eFLSZp*Bj65pFvBE> zQ&|QJOJLwoSSA_^q<@1$1sNNwFW&binS;HIVP>Sa;dubz2Bk74ALAC$is#Q0PKzQ-|ga8jr}+uDHdeMp=mVw zZXdsD><9VivXtx$IA~$D6lQ}04n)RU&7=2^c=wNz8yLL=TR+G{VE;H%$xhUP9chCC z?#D)rePG9atB(?`{Wvc@oR(9E_9JlX@|{k8)z}a6(aHk2QaHc{mYK~b*T{cy!T7qZ zALOA6&B+<&W{2ev$~O>GAQpZJ|y%H9ykOvLL-3>@UR8=45@;fN2_{# zT@~CsT6IKoc_3FrLJ##esv4vvKB6DYMqPl%Qfv~=&=3P8F{7(TYdCX5+5Yaz5J=A@l~X-F(faY;l37Leis(~ww};*y96EFi@NrXjH`#U&9DSU`#kOhaN> zic2CQuz(a7n1;l%6qiIqU;!yEFb#=iDK3eKzyeZSU>Xw3Qd|-dfd!T7patP+nIvH6_lgCN46mxH~yJFX8+^0 zIn;ut(hCtar>4ci-bWu!!^dmPHR#MRF?{2$TRgdCbJn|zb&mR{ngkWcj$W>sR^8Wq zHK4$6i+aO$#-mj2t*`6VYHXDu2BFukCu^e?I_`e_g0)>lH3#S=6+i{)6QoQ>1)mC$*q~Q8k6cDmRgaONsSqmVVjQk zsa1Ndk4mXeSW$PKQMWiBu61;8f5WoGH}3>%e79qZTMOi2<_d9CRo$t@!i>dk#Wh+v z*`5V=a}V6O{7jHz&2`QSKL5Ip^zOxry{c~I7Bfw_$;re`SCuxDdu&$TBX5^eb50>& zUEx)I(uZg$luN1c&EEdLF}~nJ&NNLqPx9>Tp0>Yhq%TutPNF9GQ_PhV&70u3;NKj0 zp*MM#wRZqsOjA`~q?7N;l#`9EBy`HG(sd(NHLGs4*(XZOvQ=@}pQ>2%NET}}wX5n5 zFVEdS*Qed!-OF2l2Hz~&&s$rCaXQrW%#ZN?**eGqN=9|<+SBKYy1PBrH7g}t;6TE? z?qA5|txL&3(duHC-|RPgh_SQPF&EH<$6!jaZ#~a^THqdy?Hmc>2_yfV|?E6 z?U?b?P1K0SPs{f1yc)p7fA~Q63h$G5z5iEKnnUS?$**2z?S$HFn4mMYCaxL_ecx!z zK1$t7Ep#r>PF<`se*A<(^-VE(s+Fhvqi!Br|A5rjQgh1L{_xwb7ykEqlrtz@?@Rr{ zPWYJh_7-*Au*Lm-ZYhGXtJ$oq8-FLHFS)n-U2#~4QNxG3haGmUlfmRV>Nx7F5sAMU zN6gLi>L--FE#P4y>h;4X&w2c)v+%;L)Ph>msuZW5>G#8-$zAO$FXsHR(qZ<()XR$Z z=DA!>{IlbB^FJubSeh@WSw_(hN_Wn8wWDqp z?)|B6kLY|u&Xo$Op)b;h(rrd>bw;A(q|%97&h68^ON z@&`NJTMv;MV-{v2wi7E8I`uiNMP4nJ^46E9wH`~tBwQyR?Ck06xI^H-f-XgzN`;zC zoTk4oRlEA6_hN$D>!#YiO)a@5+oJl(UdDnqchPaxhEDC3C(HvL#6lIKt1nu{99Ho& z#T~unt)QSdxwqTqaN-}>1vd!Ed3nDHPnL}mjlShxOG_03)E zn$sbF_;nhjd!}oc74CZds50et>Rzg%u3XUU`BPfc6rV*9qST^Ks+#` zRYHq_Q0+e?X0ld0O?E3NNx(ZosakS&I?ISFthki3k1sVl%(;-~FuOK$ZPEEn=Ii@W z*R(4pIIS_YR7g+XoO(caX_33liaWl6C!X3kDo;WSD;(Coe5r}A)tNXQwKD(jvIB0& zu%6J<9X^+6lse*-q6bIy+9upE%ohgu2{$nInrmkI@L#E0vNp=hxN*Ds*~=UHt0Faw zLtetj4A+8ZHue`z^*vFY+wclH9g$I+syN4__bzUMD3RXZw=wl6J@qXWxr)6D6X)lc zv)Xgi^H!ebYu;P`hibmuHnX?dIeS$@)<5T=ZX<)vX{ReCcpT;&7PhM3O#Vo+bPReJ zHyu^#C)?k(tG$?YiCTE7r8K+dT7O%a@G>?(E9G89#9#LH>X1#{jvP9MRid4?nq=ni zd`49RD$AG4ZTai$%^K%Rjm0%7+A0gp4>&~J51%aq*RHTzoc}0oR{xf96W(<^YF%xq z=dm+0E~EM!D{9p&lb|)l2Hx4)XjQ28(S}6mle)ZY`6SoSRMwQ*%4PR*waxm z^VeOJ%d*R|krn*g@~ij_*B|=BE_07iedC@y z+3~{YHOYH+q}u6TwO8Y&pbk7ZtfB4|)>2)veMR7z4oYUkbK{-2js;J&;rJg~Ssd9i zudMvZvVh3urTypoq9T$klgB$nbjt(%$Hi7v=VU8Hl>o_%Z2)ve8QYUrXg zCrHoR0;8mg9VdMpgw>uMS1k5FJntLf2_y+NO{;0Kv#hi<_vFxg3*xur@7m-4*D+Yaq+E{7>b_?cQ~o>^(i=13+apZXL?Vo2Y-zC;Ioe z>eE_TXEZ0eD5vc`dJXpW=^C2p4jaV{$b@kbA(+lp?eufm2BNZy$rqMR zxq#y<){@@JJ+d)0a@AI*$I3%xiScvtDaG+RiI4g_&|cZ-9fEg+a|?jaP17{$u_U4t_|rF z^w1O)Xeqx6bO;A0RNW}5Qfn%-H!R33FS$xNauhdZ$(aWeg-Pp{F7DY$S-Ql}qBLL6 zT7HS};pF#7RatVfKyc{%?)%J)nFp_T`>~6+GWrg3)podU+PVzi*2aE%oHtRsUbRw} z%vgA!rKQPvb{>vgr}w}PYJU0!?xhthI8mDt|LDzb$hJ1J%Srs9{vE;R_QkZ4@@8Ac z_#)?HU_dTBw8*(-s0B1K15zbPvng}l2@rg+5lX~T30ZQNfOKxt_$Xg z=rnjCJR*xQWASbzrdPBJ#fV-!r)+|@)gq8b_DY_~dn+13T`-#DCYZ-x6D(4oZl8`B zYmeZ>mG5xw=7WEBsgn)gA$DC2G(@lDS@ix5GZ0G)$9YGwE5(Yf`7gn0F|y2MbHT0uTyNyJav8 zEn&qKp2q5mE6tWiNDRb#LEp#>7K7|Kt);DtjIw%og~f49=hv^ZcJ>wP+ahgiZHu1w zHj#HF2QhyU8#7AF=1;o5j?jJlEcL#L&-+Dvf&nqRS@X7?L&n}K&6cILBSZEd?uyvV z9dHkg!?>6wSg@s*(^N+1=oQ;w;}!r1-$_`qqaM!wQ#oE#dJ5t5b2%Ltw;Y2Uy;w=P zpSH*ciM%U0h>6&Uky&3G3TmQ^R7|IRVKH_CoacWZk`-N8k7aurnyrcR^Pr-t%All9 zx_a=8NZ~TK&{>=}*vXIcH9B@eRK|8L(=#;YvgE=VxgM3jH`JNaM!g5L$OnnMH)bI= zVkA}tvwUa?oo$^p`@}r)Nj;2!Ri|VHWu8Xd=8KrWvjGdst~N_CIn@{uGz&(SHgZD* zCa!;lbMS0ACiNO*FJIHe(1i2i@{Y>&9Q~uYOiOGmiW7=XH0$}~l{}O8#w^4}jKr## z5asUQRnYfKG<8aQ`a!`Zv_@S``axAq11^)(IqqiKpUv9_B*A9%Oirt7c0!l#=A0fC zmBsaRx=B4CH2siVZ=ibwrsbW7rnb}olQMrlM{E5NBe62GVi?eb&_kRd*EmLO`p=w? zZ=f|AIX;ois;XyL}QB7tLvfLRDgF5+}&0}~{bH1L_?==HU7JrxyI z=$rJFhJb|?TI-EOjKs>!iph}1f{9wsz%71BWmvrXR;v}1oDVzSDH!550j{CRh%bLQ z#rcuT%Q&Vp#lMMIz;SeT6}+b{<@DUrui+As#L(8_^>m*R{xgug`AnO5BSvB+X5~CU z+eA}M)4w6O;u@bX#i_8t6ZseC6nz|R+)%SjJ&CK2h z@5yud+}8IdMq+K;06YYQu1@mVtjZhk znKBP^H`Q?5QbjEK+Bo>y4OF==D%U1U{!jhw?bQ)RF?e-amT5PwF<7eotw&uo~e3 z=dt0e73F7;v8x_-p5x^um3$P}Jw#C4QjR^sX0mu?Nm?m05hJlSo&=?3P^0@$OQ)C% z>#F~VkIp?|Id}*24Z555fop%j6vVA8M%m>bv81HB$$Cz4@XSSGFHw{8-nVte&Wn$+ z?%;X!FzX}dn_9k)yy~ln%h<&6gt%1rMo1f<(UG(H{*7g5EH%Kms1(Ge7hyr+e$F2i z5CJ`d9x!`vpzMM2ZCrgh&fIqvE6cy)^f0$E%tLI%NUV*QK|!%8=&gTi=9!haq3Y$X zEB^p#)A4WN=p7`k+Z|;9pNTWDt?o}4Xgg8@h@HnVokw{2V|~S!=s(n+%d+>JgpG@r z^oBNUN5ZNixQ-3Q@~xFfT3swHZ|0VKb_$~`tYwkRUcgPfu*Y5s|IraqWbnzM9x_%=WVaMDPNyju#@BR3wM8;+~;*4BYmV{n_G1O z8xLQWhOMVRh>6&U@l9Ld4vHTLy*ryarzWi1_xD4$pJRZH1K+@PTquHL=5X4)?*N>9 z@DhF#r%GGbW!We>c0qcZX1#Fe=0gk|E?t*<;22!|0;GD&vk{&!pBrb|yk%IFw^bUe zL174qmDc^(v`l}#e)surS+)27&G%H^i=O+sls=T@$yxavkDV%Rwmy(HWz$nvgP4d- z@%DAz^j&}^1Vcfsv(RxO;c@2Z@o%pSjhB!K*?94TM`3T6_TP^;~)e*P7 zYFM+Y60Tz;(4OYK;W<7`Jon-{zq@`Pc5WWf5Qh=fr8Ix#t=zVU>m+C9aBSMg5`C?P zpyu`?zQ0n|;xnmU@zJ^_`AUVy&uvnE>ig#y9X_3(M{*exjP&ibFNlfQnDGrihhKdV z5d>pF!_d*zFQ#nG{`wa+cVFVOdtjaV0XXwx`xbdr`X%qgKrF<>Y;XA>^6HZqt&!^8 z?5#(I=cj)aS3jw^_V`sJJOs}E6FC2@eTh7gH>FSVOx}rsSQP8NR&&1#(g(zzf{NBa zJrkSh!SSn(t=(7mY}duV;>evB{D9Bz1IPZ-K15!~6L}+#6;?0$}R+Sz9TlR0B(~sJN$P0NQZ{(4@l4tfVF{uCl ze~d^ir_X!m4yu-dny#(brA7%F2413k+KIf_6L}+#(mr2b;k}LiA(C2ATa=zC1I1Rd pJ;^}fOVNNjK4{M0JpyM8_#fQJj*5Z;$IvYC8Y^-`Dd!&&>0TS=M^rcdhrg)_V85*M6QI zz8}P*nl{W~N1M0)NH{T$YMpu<=u*UjSAMPz zIm}36zym9Jq%j8 zmrFdlpZR()VKCR-TyGz-kJ|zgiyv&xVDp)Pxg=Ns@`l04b`k-D6$pqCOu(PZvoUBb zxMYCfvTY2O5Zusi0!JW#>k=*myu#hRS>b^!BHO^uR*ftnfd+yBF#{n94&sSO5*vd) zyCkqItwtFj`b5NmHU{?64iP?Xo(M<25I_*jEs!h>27|C9nqvr7I4of<0*l5FP-r3w zgGQn;Bn+B_MI#122DWNoi7aGuNOTHypgZtC8-oC`SU^IdLPJB%LviMOp+5>kBoa|* zEDDQ7f)Yqk7*EWQAbFx${YD1uPyi82$Q6jWd>%q-m%-$Rh;0lEq#X@?2K)*Z40Xg4 z4X^_#q9hCf3S*8&ji$tA4e1C%gh72nW3x~|5D*OT#3E1+GpZhl)Xi;3b=2;HgGbdA ziJjJh9t;o}Ra4|0CIC=$K*SFbvH+*G;7DeTHh7Vk4h+Nn3R9r?sD=cCJ9hMO4K;rj zqnOM2%s`|qpH%}S+|Q^QvglR@evM9O+;cWyfJtZ+KPm;G(+P^Xf(t~zvKuTZr~b7X~xLw%lNbKY$YO{K=@{ zN{D3N>Lt;5A~A!<0%#Olu)>_nWs@v0L^K9%iA54I3^tNuiN_$BShgh+&#@%p(UurA zi)Gn|!_5t<{)uS{pA{nAK%nXVSi|PCK=VTjiG*b_aBKpeg|uW7nMe!q8h)5>eiipHn;TcFKnhi!R zD5B~{21^?5Y+2HU4zS6nk7|d9HKaM9#{G0UzYamaeTe$!`v?sHcwgEm z{igb)K5sE2EFuGm zC2%lEJOOWoWLQ~Ykd{m$1C3+gSZo4jaGL+qX#j%_4m%iWzTY$quVPjJgXa&hZBc`s z4OaYrnmJ1b){=qdFp(DER3X`TJOOD1SXv+f3oOJj&K$}Tq>;Jr8u@XyGME8m0|&+Z<$d)x<>v77mP34 z`c58td3$&wme_kcy3pL6!L06ER;mnJ-^;@#G|)SQi@iI=>l^+1lBIv)U4J(4af$;S znbcI@`hsRgWa;TQ2|Qc`54!s9L~X&i@=4ur;Ov+8kscBTh4dW)T4K@Q2YlE9eg;&b z%_CKpepwaTJW_R7a}kd#w#5$gHliA$B|W0=&qlq#$5Mc;1%ZGAlbDg!BQ-p^5+KNj z!Ud0qMbcwV3ot9_(;3+?s^ZdNMI1Q9VMR#8fMWlQK^`FWC8zzh;NvOq$rx(r(by+> zYkv~?U;aDn(SO-6)SSE%C=HoqIWC!qpaODSP#QAJa$GVIK?UTvpfqHb<+x-bf(poS zL21Y=%W=s>1Qn3ug3^##mgAC%2r3}Q1*IXgEXO4i5mZ2q3ra&~S&mC4BB+2I7nFv~ zvK*I8L{I@aE+`F|WjQXHh@b*;Tu>S^%W_;Y5kUpyxS%v-mgTr)B7zFYaY1RwEX#4p zLB$r|Bb@`ebPTOH{2SLk=6P#10w2pRI6c~tj z)WyH5N6%7rKX0aHKS8~9I(Ih~OAp&1cvhc!x75aSZhWoq=d`nbXFA2|SyI#O&UBrA zyN1QX(Cagcvv-%~C{Nou=g=6Ko>CR*x4FP7LBfgxm1>+IN~x&w&+U1vi;GNCHflMb z*H!(~dggR8pNmYn<2xmK7H)SmL82FPDJqv zfA1fDQ-0i<4U4Ou?<)ydz(ms=vZC$~*ly|<46mu`r$_u56(vrGlU-MrA^nVMm-s^Y-+B%~h$-W?Wo(SlO6$$Kh#W zU8O!t+c1%?5y2zpPQ4PgJT^cdPG=U*q25u9U98PY=w*@lGaOX2=*q3foh6xxin&uU z6l|mVn>CvCv#Q@eq?&CjIhd5Sc)q$ST%onwbw!@{oJFRGCj1a{Z%laj>DQG%T#9zz zSwbQq-H2}X-}V?>8rzdelmAK)3f^g14lTIqr)OP z4zwIxoQDP4*ew^j{Ej^^zO_4Y8?v?V`jxv2BepI`wMx8&D%k&L%lUmPy8qm}rb;KM zwJuUKpKgERZRPzvHtlm&-nKS$h4yUCP1_}D==edW?h&>1bnu7wP5wT@*TwTzHCL@% z+cKk6$3S_%==aiftM|@2rBmsftZh@?%d<(`I$j~$(1ZL2KmKWXc52Q)E!D;Em((5H z;H)=eS5AWO0i4qWugW`t!UBHv?6_dUyokD<(a%G58iju&+vKty-^SjxEuS9iF(m{)Y}ePohG zppA4w3k6o@n)6n-Xj}0nRjbBl z&-a(4T$CWK-*#w?=p9XKgf%P|;y8Ubg zJ$F&NZN+uiOvx+#^xj(1@(Gl^t!Mqn@2$q{@h zEp8EwW6$i$*12`mCoZJNc=@^N7{sb|eAJoVXEUkJzg*KsT-{Q*th20x*Wf?d&f$1M zMK0#jC3vyjz_0HA~aQD z@(gcgYh*JMGcuIKZhK1?Em^T+=eCxX2miczdrZ`^(qS>{^*vzudG@%CN*h0XNOU$a zQZZ>)NLen?_ab=!kLPF!dgj>OI2~*g(Q?9UkJa&wm~6#BzxBy+uU}rc6k@jB_IOmx zj9p7lzhjcDt;3qKLq2fZ*J;KouEL)xJzyC>^}vca?`Z$XuDMf;PKw^BpABDkM(En* zQ$}o@ex7t#_#k_}$*Cks^UI0VH&u%r5+A+nHa66CFKjqu4=3IxwW`mbb~`3*MuX0V zn?5x)zD=#Qac|N~RhGXB$aRUO(0*+Hac;Xr!FQY*RWDmI_AYI$tOv1hei@`^gQCTbiqgx?4vD=u;Oui9L+|EMOdb}Ky50biml z32qp>qw|lsPUH3OxE@TV1nx-KNpaN>9XUo&S1yqtl=299=HdE%S zH)Fk@VCgYNfPqHR!Gvd1ENHPm!kb7Tq?a#Q@nL?(+9y{Vj-@7KZr#;i{fQQQZvpL~nE0nZVHrW?esYayBM) z!}>NZtmj=BwdGRdBn_7CuT?LQ^I`)`+83ZOITx9~(JrdcnCOtnXM3+)j|(ph`$O+t zQ#{{U^~!_VTJ5w|HItmHJKME{e^_3;-EDVqmk`5c{}UvsI4yzF$4!|I|J4@AeyET?*zS4^6E$9I0#PGiG6 zzWV$AR=DSwNvN=?&uQ-6b`o3jyP?_`x1F<98_zcV6ez&ldqmG-UA3wrcWT#)rWu4> z4V$*yr95Ycs!8g_F`M843O|QuRnjxq?aZhojpqjJpk-!BafUCrhtsa4^gf;h<8{}V zu0Ax&C0Dnb`jd*Ms{v(~Ru0cay)DXkvu4PONe+}GxSN?THz7=2@X%t}qgq8wRK@aj z-M3#@qp$j{EHrIRS=9MzV|oN5HOhJV@wP3|2TSSkAzCTKd-(1RcBcbPv@Q4%xQ?G% zI?3;@jbG4Q=8*>vpWIJCHa-jp%UGsU`%p>wt(Y0P(> z>%jz~*%_Vzx+uNtMZzu0iO!VDN&*fPE zBglShMnqg(nD>BMh0iG5yoTl5Qw~#$>G8{cmDqOD$3=IGmRlE^Zuz4AmGQFoZ_)VW z!4>!8i)T&|anc^;o~&WSUM;v|rPljyWnwAuUd2wJ#k;b`*LF`%6;NevT^j%9sG8mh zyP3=*2SR-ARYY1}#hnj)EQv-Z3EB{TJJoO{O-Z?2C~*grXIZz198WDmQB z(htq(%ct{fT(0GAl^lXI&%yV1ANTG3y#P~E2QM!Cv3kRM9e>4FbxJTTBlM)3&0S8? P_qo!*mw)6ttcw00^S|ll delta 2382 zcmV-U39t^wZ?kSl)c zP>exP(O^Kq1qez-C1PA~2SgSN3CJQ*0nI~{#f3!>)X+cxA%ZLt1lJ&SK}C zO7ZLWLzPic*I-OnO=iqPK42_D^I23f7Gbpm1IUHtgxruLa^(ur55o1v>oev-8yU;+ z+l*xd=)4sRvjTD;Frf@0lBxy-f>Qj;+aMuYq-SK}tT)NXUAaUl#_Yl0h5j0q?$eHE-6=^^%ulby7vA0q%Tg|^S_6eXn zXAh)TwnM{}?w^vQvkFoP?=IA;%9%VSH)C0Mhq5N7&^P+oVxAj%cFua?$rDrf=Mc`GS5pJN6) zS3W;-=XIba)P@>KtK6fY#$vdt`Kt5QKAGSeQzw65U3MF6DZil*zs_zH3V=56cVD!D zdc0#pRe!^pd9{O4h=0G(9+c>+tO|##Y}C+(b&Yo7F0zdvT?qA ze&jB#1+}3@)GE;|9NNqvCs)l;L65!S8^CwRSpf?^J_jKO+9BpQHz2m;rVK*%d?AoV zoA-b7gu`-9!>W`rvW;1?^6TxVa|IY|VgX}ad<9_4)i0D{6Frx*uixX`Jhq_WY)-Vb z^$j4V_&PXw2hbSj^Lddgaz^gbT2LEmM6HqyQMmmL86)oqbC=Ce*X+Lv%ECXXuJ_qz zZQd_Z*Cby+`j@aEp@M8f(>MC8w{@OJF+6|E$0p2KPcc06*U=kd3QImdNw%i00nHol zxmuW~3}@7cT1m6yF~ALB7`sEJIWNooN7Ru{P!{XbTYC2Z*5>^VGnbHWxQzoCnc0#( zZEt1lnZM4Up=Pws#A+;!t?Z|Px~7gWPZ`dr5w((L$!33u z&w`oSi1`KH8%rRetV?M`9=rk$?(Y%M=KXOcoos6w4>pc&U^{6h_^cNzTtAof^XsLt zBB>k}Mdy)?XZ||Q^8#tz`phO6>+DVNk>tR6%5X-Fs1-Hy`vA6y=9=d7i~Qm$A?et6 zzi6OF)QXz<7MTj5KHNLYKfVHX*57|qh{)V#2uiJ>v!b}T_PbZE?JsPv?qWN;CZ4+R$<(K&`4#}zcfzLvY> z%RB!N#8uZ|ckNfSE=Fp;vWU*E5ybfh#tPWe^bM>|+)sYT>2u&$Yc~--*jEkmdQc;3 zmEHuo*Pw=pqm4_@mEHAU!=Zmmj|HsTnnQ_IMQUI-$rTo^kAuwP*P!J36L9lgCR6dm zgY~fWP$LzH_n{qspc?iz+@$f4VWyy^qstX_U^Z$D*UxXsfQ_m7TnA_SCgh*G&2@H~T98(82JGLS zPUDT@d^pzmOh8I;BPkElZkCFZtQcL&srEjF;9Q4A8>S;N!LSry6iNGzy^HSuY%{gZmwUv~iPAU*qiD zrVg%EHnS3RpeEFY8Wpv|Dv}=vBL|tg#)t1d`j@(IoN^6;p;^CQhgoap+qOf2j3W}yJmeuTB%IN`eQhjN@<=lGEZ)PkB&o8+&rr|7!? zZV1MV+8}$ocb0z^iOXAGG~ENJ>3jmtv**g(cFwcBp#JNJ@Z}?b_X0x&e__i-g88U7 z1RvUm&$dJ5wJxrQ*VSV;Qtk)RL|1n>_24PxQ3m^u_jaE0vHUMuWv)Bg!3m1nx&Sqx z7Sx2=NTY(E!@VCw7{-**Fm`tG4k}5jYYY_YHjJ9S6MIX!F&aZXSa?Pa5O@$Lz>% diff --git a/Mage.Client/src/main/resources/buttons/skip_to_main.png b/Mage.Client/src/main/resources/buttons/skip_to_main.png index 8aec79da18196423ce4617595a820d64aaed1644..0d1b2bf1155add4984b911375baee3ef472eab76 100644 GIT binary patch literal 22369 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 cp|2MI0-#o79^hI<{9 diff --git a/Mage.Client/src/main/resources/buttons/skip_to_previous_end.png b/Mage.Client/src/main/resources/buttons/skip_to_previous_end.png index f5f737d8f431fbf5c024c4fd8452c50b3d36eb96..2e93fd55bbb065bd3ea5dcc33421ef259e912a8a 100644 GIT binary patch literal 22494 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 LNkvXXu0mjfV%vYX diff --git a/Mage.Client/src/main/resources/buttons/skip_turn.png b/Mage.Client/src/main/resources/buttons/skip_turn.png index 4c35eda03e420e7f94a4224b3e469c7c61bfe5a2..c7c3bfe393b29c0ae1688410186e862c233ac141 100644 GIT binary patch literal 22331 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 MfZybiW97H%KShM$ZU6uP delta 2303 zcmV-P1Nl{jfRTK%R7>P>+tJJi% zrK#CUPisAC8hg~<&b{+yoF}W*=1|)?=YQr~?sw<^``$P6zBhl5Vg7$S)uAMpGAqdx zld{O)b3c?BB~>-XB+QTywS92l_+=<< zIyA5s^eHb&t!9qC9#jxx;}sMjts!9MN?>^(6Ei(Gwy?H^U|)^<|NWTbCoLSyV*R#6?t@_8nkV>GQx$pZru zbA>jC_#?!CEXYJ`$T-F!VI)!`_Th1Dx_uTH1lEvZDlR}?`wa+9Erk`UW5C+sO)@)8 zszr6wyA6LADF)9QcD@hE`#z-lXwow@5rEfc?1R+GQ$n4O$!!^c*t`#5zTDZLJn-hK8!){JO?r%8!>WUn(#s$7s(mf=z|ZLLK`PNcg`YyBcv!a7Lw&!-w^k_R}lWj^4#A z$cBu_DrXiB4My9}NqtV#J&*KL;Iq3|&|A3|Af~DxwtjFEQX2=sYXdg{ItHdxM+Ifp zQJcB7y+Vx5GG8Hv7mmX|93!(*{N%*_8ajW5Ak{M#v}s>Aq#WvJC(u-gUz1iPBj8Ie`~Kopk09y7x;Ugo&{`=68#z<7EiB%3azsc#~*1?QgyiK;rNsB3^r zL@^k@;y^KuYqyUWkK?d!<>rInzvC#4O>CkN$PactZ-2FS# zRH5Bx^M26K(xX0QWeM0g2SQ@qtr6pK9L5BuH&A`~+El?j)+36~f}zE$LYq{_00L6$ z!7sUngMW1q<+WPOJp*1@7-y9@9TEA}cY=ABK1@n5r229`sCTgp8)4 zXHsl=FS}F+pE=Lws>_t?X|J7Fb8XxhWJFeE=AQ$&O_Zt2d~5yF+93PbA6{r7BeEhh zzeT1AP@Uyj8kpV!`5j-q&_YIJ6;A-&0*s#HR-eTB2c_M^z-!HxVz75#J*t0p9c8z$ zJ;Oh!M)Q$ScKmS+>)Ag(7v{dc6oR&uftZCCG9s(^7T_L&S_@V$3CJ0){P@qnYst#B zV{U)*+ONaGPwxJp8qLT0%yOYWwxE&SkEl?)clb6Cvj|KqBeIGgg51}jn&JGpj#1Z& zI(`dvSMMn(;++agihJ$GUwnTn=#5oDBrHc}?W6KLb)6(EhotO*g)ZI@mR1N}q4Cs~ zvbPy*m%4)UTcJ?<$u|o5CK3;wS<^A1FTeE?Oq(u+*;cj`;~SMaf&U(=*Iy}jNY{-bL;*F576=pOn zT^$3`Zyvfb4DG+ZFDPyg2V^9(fX+J)1o1|&>>dzG<>cZT5|&@KT`0ujSZu568i1hq zbSj4=?NG>9*wiKD#C(6^KJoSJojt%kFcbo!lc?Qpxd%wtrN1Go2m&{zP>h4?DyU$8 za`Ozxglxz-+E!Re{sUpQw#+F#uBi2ICx8C{IzE3$N-E-jW|>*Q`Qb-`ctc%xzJn!h zUQ|vid!K}5&o%3WSR9LOO`rY_)~94~_b+=E=WDq5OB#dPR#Jbh&?mlL>CtY5c0Tu$ zLf_~gS&#|YXxmsV4XWMK-1o5SD*#kVNiDa0%`M>KT@YkwBICBj zI=Y}C)ui(FidqtFcZ1dmu{ajn+O7{lcq%smcoyfINIY2i&wCWwtIzaN8)|cI3Acg* z*Fn?3*W@2rkO_a;h;fvk!;fExFpLSKX0X`KGpezm?b5@}FCIbVnSKb}k_BQdQr|Bb>hT zkS_4i*8tt$ObwwI^n~8fBYH*8=p7k|Ws)yN6<>=pj6N%KMn%U?*TnY6?!ig5;h7bE z8CA!Jb~ksP{ZoGPg}YNh=mkBYH}r^J(KC7H7*zlLKSsEjn?ZYLCCOYyMazy|Qp*{& znQp8+rik3g6M93B+&+JX-1~F-hlra+DJxx8Gv!;!sic{5Z&JBe<^RNgg#WXDj=r$R ZzW{a6iy9t1MC$+m002ovPDHLkV1mjvX*vJ^ diff --git a/Mage.Client/src/main/resources/buttons/stop_watching.png b/Mage.Client/src/main/resources/buttons/stop_watching.png index 717de1f96ee0633a1accf1e4640ef73e160652e8..c45a5f639fda6004ffb2fe32799a076b76d1e5ee 100644 GIT binary patch literal 23029 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 QGynhq07*qoM6N<$g4gzaA^-pY diff --git a/Mage.Client/src/main/resources/info/command_zone.png b/Mage.Client/src/main/resources/info/command_zone.png index a992c555d5080a6a59fb2a172e0dbe130a4c1a1b..33dbba8c5d5d071a69b5ae0dd3272c6b2ee6b8a2 100644 GIT binary patch literal 20510 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 literal 6247 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 RV{!lh002ovPDHLkV1nTTp$`B6 diff --git a/Mage.Client/src/main/resources/info/exile.png b/Mage.Client/src/main/resources/info/exile.png index 6f0fe92cc396e3bde1e6c19eb7d257ef502b2d2e..1cf37dadf1e152dc34e06beef45e90b9909b2c1f 100644 GIT binary patch literal 21932 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 S{kgY+TAFP$EjISp`~LuFGu>wZ literal 19202 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 diff --git a/Mage.Client/src/main/resources/info/grave.png b/Mage.Client/src/main/resources/info/grave.png index b2678b09ca316fc61985d70175c8189ff3cf2543..71ea1f4b5ca899ace04c652054d0dec0ecbebceb 100644 GIT binary patch literal 20434 zcmeI4c{r5o`@n}#DUmih%0vq>W;0`Ennp6RoJ4ji88h!NmYHd0tl82+k`k3R$!?O0 zN{LVsIni>`DvnceI7QSUS$^+W@+N)fe3#$vcYUvG=DNn*p69;r=XpQR{oL>UynnoV ztv8q|$S;(K!C(sJW>g#Sca7*fO%D7kWNmu|{!HhZIrCvKJx$S9Dlo&)9|n`cvy6?c ztvxvc4&Rf*g_|22!?`>TljQ@zV1dui#a*@5gM?!%rc^FBLOwVfUvO{K~#O3)Z|euD85JN4hEKQQj(r!OD=Nl?v-4-mw#R z!&j~uTAQ`7LIt%mOlb5{DwD)|vW5)HaD9(lqg^$ipr!q!+b9Iatosy#dJDr=h03D* z1UXV(<|G@B5?jRCBY^q!6EgAS#Q)8-gF{E!;m6R4kUpNd;tLs9_Z`C=92sR18W5qPiGFcJ+2ce1pG8*_L79H)mz(9vi#+<>Tu#u2a>oGu)LLgSDqA`*>4 zpwJ{ViiAPIM?V@Ac~Bzr7)+84b=~N2;D4(%JOu(S35g5{2+#|_>T!4;NHmd1M4~WA z30=4*~P8S_I0_;enND`0WhaFJh{JI7D3T0=uL(AUrCb@_6?4#eh< zvI8k118H0&S`USs%!on%YQy#8`3z5uK}P~UfG@xn@IgEDq;?=uOUtjOlMd(WJEm$EQBW`6=uY&*VX&A%f6L3bCd3DWPGWL+zBB=a#Ub>uXab#p#nJIh z;xG~Rp!Deo07GOT@K}8V1WlhnKmceo zhQM&gFtBvm*btMr`EDpP79WheAV@rdQ8}FKY=LdxwvKi9u!fTsm&W4*qCLG@V{B7@ z&2nFpn8;>0H;`y_QM#khMS%`5$jEP6$EWqxa@36V{c`?21S9?-=06@Iz!PBqqm44+ zYFO*XPWT+AAb`dLj6A>y`8#`f#Ot?a6Wx=MqT7QH>wjS(_%#22Zy5j@9fd_1&=6QU z9*4jZ^|1&d4XuyB;|yKUEzp!%O-ym3L#;J_ib$r0`lAOD9@ z$^dw*eS7FU-K5pnB&9YS#lTv z1xrRw)(r7E-VHv9u^xF4Gg@%jn68CufroGcct)C3ZBjROK%ihfEl8AP$NNS1d{Jbq zrFneYI@a;emcirm86Il`nAa)B&}oi0e>02GD4$?1n)4*)!_5=TC$Az$TED$K=yWEf zLKdBTN#MZ(EOLkMLKHL^`CZ%i1V;3oLtK@}vppftqF5?o>tK@}vppftqF5?o>tK@}vppftqF5?o>tK@}vppftqF z5?o>tK@}vppftqF5?o>tK@}vppftqF5?o>tK@}vppftqF5?o>tK@}vppftqF5?o>t zK@}vppftqF5?o>tK@}vppftqF5?o>tK@}vppftqF5?o>tK@}vppftqF5?o>tK@}vp zpftqF5?o>tK@}vppftqF5?o>tK@}vppftqF5?o>tK@}vppftqF5?o>tK@}vppftqF z5?o>tK@}vppftqF5?o>tK@}vppftqF{}7k__^T!WHu!#t0PsZ;o>5_E!Ix0L>1H;T zFj(+17%XBZ4EA{l{B4E7Y^K4a<~hM&q@ys{0?rc`^@A|j41aT~kzL^PKaYoJ`#iC~ zW4OJ8U)x{QQ*!jEerl!6Y_AxX=nSLuXa~fDdK<6Xm)u-_N~eA>n7;{OGIw6TLcO*3 zz}X{}{d2Ofn0QlX>(1V|k(wyK$Fr~aT6GCFfLZ&@u)ga+H=X(Z#1~#T<86tOf!h0D zUKZ3n^FG(nm#4n{C;K;t$-3t|KMctSX6V4Z4PS=6c(eaTYtD+H*FPDRF6v!wKj32j zS>C=RRhZqjBbuCcxAg4YMqyh^=_iEZ;G^YF3Wjbjfn_c$x72FNSz#C|`-`TqONo14 z2ul%0Put&_9qHA*W$rwwUIX(FiYBjn8b5{_2KMILlr5kPQ8R^x?AXsiO%^)2(Fbib zc1Ne1t)G3kZ=iDFNk0`jX<3fEc6GO~KQg^{dt>*M0~MQGrNRe}-RZd3{U_Q!)K^E) zxr2uX@FzAN#=b33T|zyS&UQs2TR&}|Te8^X!HPP5Ec#OWKJ;LT@J9E$j)99qSMBGy z4YpaSZ$Ha_Kc_4%T3HxV{o9g+>KW@R=S23HP5GR#r$Fv#%g3(BQw@u{Ucshl!L|3> zepI~C9TompLE$0knPmx9{SUV1r}icZueMGpNSlr%52-~(MI{0zGcR9G$V}L6Fw0w^ zGUDP9jk;Dv)7U-6`D9}grN>IfA*~IDAI?}c$jhT(r$hf#e1%teN7ggn{BhpzACgME zx4L5%|4v^TpgIt?qlTZadrRfIa(IILA>~wy&Sc*Ez1s0a(<7_;1{Uuuk8mxGTDmOb z^;uzXji!44VZ+it_?K*$FT`6|8U?vB8w{kLl~8muas0*s?$ z75@tQ>lrfMrupvS8p5U-dfKN3eyhZ&%+v~&ojNsYeHK4bG1lMo9TwSQGFW~7T1y^h zusM8nLak1P3C8Hl`+$<)O_%-=dP7J!uGU%lBrhI_d*B(3%iQ~J!S!79=8|{vCdp`| zPG*9(wv79F8TI$!bv-vehn~}6+e*F7QV;7?uIxWqQ5Hh+;Bd}|rSPNMeh%C3Z_2nv z$DhWYu(!*|$|Y-OD25N6D5YQWm3{i9BfLRzw^H5_``e5Vv(CjwTe7Pv^Jx z9@4O|_@nmxpb#0}TdY-8Tix$quRe>Sl+e=D6rsycSHim%|M_PufuLsKoO)>K5{(X7 zigbl9ysW=AD!hx*^cWqqJYjnI6Us5FK^U>+LZwEkmY%SGB_+Jt^rZKQ1m)#n|?N zZ_C|+lZnbg3yZb68#@sZt90b^`B&Fl*#!GJ+skyAYyU=n&73(~YGcL1+>1TZ1AC?l zY~@j9dR&j#`21Wm^KIr=^or4Yl9XMQugveMiCE-Tq%D&q=k7?od~~IibMRav#+Oq- zi&|=mf^;k{vJKGHyT#_*dT@N>XOi>Hg?%QkaOADO6#lHfW^Vh; zlGLk9`fZhCFV=MV=qq}*MI8TZmEZp$q*mZ?uHQf9CYR9kkjrhpb*F$>@GQg`?snJn zDcu9*v@_z$J-wP~4cXE~_@r#5dVSK$4ppm6CvQg?bS37*Jt>usd4+AoUEaIS@BYcE z?f#9}Jw=93cNu9qc|Ti+NWp!)ysm6v>-N&kQf#=;C&!2^PG}S_aVLH zO^kg(ly!C)d!<)g|E-d=_KI`Hf!Q02bSmuaRJ_sk?h0F~bZ@nt#8BvxPjCJf;ODJgzwmz z{Aj*uq&u)(-rB?ge%gb5`-#1>ld;8YU)^W&sj1OxH$PYR4E>x=)Sh1AdJ%Ic>Z+HL zKu5lnkWxT>qdGHqpUY}~V#b|p|NRfz}--|x3PL3>pi%`u&EEJJwHZ(Hf97M};cG4+iI?PalO@9V0o(!y2{$^`g! zOj*&2gBuRhiy3P7(d>d0p*-VQmR8#xg{aUNa+*+jN#@}Y8sX3QH>&xGH-MmZrKfF= z&@!I4f5OC&?>IebIG>vMX6?0yXVw+ok!pX~nEz2{bJIyWL9in80!1b+bJ?miib?XL zj!#-KsXMQ1$#2ED+!eOzHpZuIDGArnyT3anlhas-;K}L4uE0`vePC2RexZlZuJu2% z<%Qxe7-ri7=|bU+`t zt7;L`^G%dD+tDmf%0;6wi%q-8E9%rLlYNdEmAc(W#^DUuxe+SumP+b3Z^|Awws$Yw z2Rokbi(87Hv9cy6t@8M)o#hq`Lc3O|n=9hs>tCKO1S}O(5y>B=EuZnV;hAR4&5KT4 zPtP`5YkMX~YsoHle2Z$gP=H#K3yQ#OE*U!G0 z8q>V&@#EyBx!ZIO9;kZ0yv?!+RvxnqckF4Ozu%0lQJy#P=WRCn#GmuEyse_m4ODh$ z@RQ#(?JmecGV9tipuG*Yjr^6}fCF z?ohfIaPv`un9c~5^;P#RwKs$A;Jmnbli_nDe{JXfPM z7*(5wf1VO>_U?7+C*S&{C;No&Tpnrr`KTGgmo3YzaPLT=)Yv-O@NVVSsXW4MQkYNo zjH`YAp7Yk>z#~1KnuVH_iqa{`+}hBttgsJ-rzz%{wx{L}G;9qX`f11MjqwIKLi?Oe zj^$HBqVK)uS~`8AY|+T^U;X8ZON@6?@UdSw2XO%kj_qwHykvi6H=n%a9L4|C;$ZYn zC&F-__CQ}$Sa(|Zw&k+@&!>ieWVgIDwY5+*Q(oDTQ|v)P9xIgzE3Bqjmh7-$s0P`( zXDvNFV@Yv`0c9{JYpb1I3rr(VHp-nF+gLh63wg9r5O(Taw z-(533ku6ABDaX}lw%fL{4W=pFGega);l8zZth86IdF8>}%hSy&oqQR=a|3VfH@lCw zxF#PG%I^*>Ybaav>z9tzZ3*u0@E`9v?7|;~No7Z9HW8axP3jS)QiHOA$$cNAbB!Zd zyPnJ5nAN+X=~LO3vSn>0Jr13J?Jk@vef;vg{WFOuFN)&vp&?D~)$~j4o6B%FUp<<3 zQ}^pW z%E-)fj*9SqNa>v0IkR)6Ta{{E!^^drIJuWo2D9Q3h=9TZ+?=;%1^1TrU@r8sl;RgI wh*MkjbBLPMIc1mL;+MM(^u-eZD1O6!faQYKI1FZPvVoen)-CdX07;Yf`~Uy| literal 8911 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 diff --git a/Mage.Client/src/main/resources/info/hand.png b/Mage.Client/src/main/resources/info/hand.png index 04482b29c7472946c8f3cf2de2271c92fed07506..59d895551601b55e845e753ac7d3b329165b96c7 100644 GIT binary patch literal 20409 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 literal 926 zcmV;P17ZA$P)zyjtj zUdRLz-neNCqkK;GH2Vef!$Ew%qC)Qeg$vlQ=|K@w3k&5BnlU4^s<($3Bq5xfd`LVz zyb8wT`)Y@dah2tU_U7Pb?GS5IttCwL^1zJ5y*y#mbz9hM>swOcu46m?Ms9sR|&?`o+chL6zm) zSPkl)K7%o_q5f!8Yg-OTfn9!nwS8``NmybczeZBhgS_TuPWhM^C7^4+JEx^d;&hEc zQc{FvK|v2lfoDQOWKKh)gF=A6rF>H229TIWNlBP)Y3Y)f+*~f4hFHYLng-U^uIQOM znX#y}RIIqRRy3okO3f-e#|ETHJ2rNks*jHz-T=1t_hAXn&Q5bJEL;>+TDI1(zJ5>l z=FR6DXUz(YNKR1+PfKgVFrazie5R_o^Y}~Z>)_7wjEtHpo09UMCnfbiUtjNk@v5r- z77G?Uh-z%`&n_)x#W2J;Jxy1(sOXDMX<7A@88g7?!!;-*F0rQOyL@EifBwp<{{q$3 z|AiXrza%y`=K7WtYGD|XR#m}b9uyp=pOJB3#=Loqx!qknx+TS}l3rea%`-FpTNIc4 z=Z}i|FI`jn&$+Sjwta4n2G;N>Xl>z+E67(YZD}zhKP>D&mygeX z?v&*JA`|-m%hcBV&<~HmozOBW${43koxzw;Q?rscJNrLpMfrc8tjzxs9v=UNtgQZX z=jZ*GC@*`NQdciRFzLGohZt+e#9Ze~O#IIW3|yJOfd4AV$)Du|0{$CiXPpQsDv~B> z2uOitd_taKbj$|@pm&_&JpKnK$0U$-OIXUt!8R>dK85ySj1qJFp znHg$Pr6tOR)is2R0%Tjfa&v`2e6xs1S$wtw0BhO&MxTR+jsO4v07*qoM6N<$g1Ppc APyhe` diff --git a/Mage.Client/src/main/resources/info/library.png b/Mage.Client/src/main/resources/info/library.png index 9cb19eb172b3fe74c36ae43e831f3a1bb3e22b2e..f799e808aa304829308e07b3f399ef260a214525 100644 GIT binary patch literal 21715 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

#wP)!B^Ay9G9VxM@$7e7hrZAht%i$Z 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 hJF)pGe@sp<0IHCOfjUO!$(ff*VoW!iN2bPDNB8 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 XyK?M|cWDS;*63inf^gp2ckBNEl>@Be literal 470 zcmV;{0V)28P)N2bPDNB8 zb~7$DE;i7Ety%y80aHmtK~y+Tg_1u@13?hQUpNV9K(4XSDoC1Gh=t%Eg5N+CEP`4I zwzgI(SosY^5N)mO1hLdFprBx7rJao?R)QJdyPZ7}S#XaZvwJ&l-^|_tiILY}m8@dO zJ*JWd-hIO$9%1!OShWtzGp?KDjwDB)NJ5d#!^Vd>Z;?ybvi%i5;R;>!raM7UGUcKz z##`7Tg{=W`2R(dwnO)fAJ?CvNah7p~yoUYtQs^ZP(NP=K7bfhJV=_Y|+zyWT432Z} zDwz%iI^Y^Ma=~~+c3rgOLiSjQ`2<%NHMCHF&*Yr!kyRq$fmfh?8mL!jGVuXx+;H(g z&d3hgAnHx%5S1AsTkc Date: Sun, 18 Sep 2016 15:28:28 -0700 Subject: [PATCH 03/50] Capture by the consolate incorrectly prevented creatures from blocking. --- Mage.Sets/src/mage/sets/kaladesh/CapturedByTheConsulate.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/kaladesh/CapturedByTheConsulate.java b/Mage.Sets/src/mage/sets/kaladesh/CapturedByTheConsulate.java index 5d91046d91e..99f8685c7b5 100644 --- a/Mage.Sets/src/mage/sets/kaladesh/CapturedByTheConsulate.java +++ b/Mage.Sets/src/mage/sets/kaladesh/CapturedByTheConsulate.java @@ -35,7 +35,7 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.AttachEffect; -import mage.abilities.effects.common.combat.CantAttackBlockAttachedEffect; +import mage.abilities.effects.common.combat.CantAttackAttachedEffect; import mage.abilities.keyword.EnchantAbility; import mage.cards.CardImpl; import mage.constants.AttachmentType; @@ -82,7 +82,7 @@ public class CapturedByTheConsulate extends CardImpl { this.addAbility(ability); // Enchanted creature can't attack or block. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackBlockAttachedEffect(AttachmentType.AURA))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackAttachedEffect (AttachmentType.AURA))); // Whenever an opponent casts a spell, if it has a single target, change the target to enchanted creature if able. this.addAbility(new CapturedByTheConsulateTriggeredAbility(Zone.BATTLEFIELD, new CapturedByTheConsulateEffect())); From b5d965d9ba252dbda528f73a80679958f253b8f6 Mon Sep 17 00:00:00 2001 From: brodee Date: Sun, 18 Sep 2016 15:35:56 -0700 Subject: [PATCH 04/50] Captured by the Consulate incorrectly prevented creature from blocking --- .../src/mage/sets/kaladesh/CapturedByTheConsulate.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Mage.Sets/src/mage/sets/kaladesh/CapturedByTheConsulate.java b/Mage.Sets/src/mage/sets/kaladesh/CapturedByTheConsulate.java index 99f8685c7b5..00fa21d2340 100644 --- a/Mage.Sets/src/mage/sets/kaladesh/CapturedByTheConsulate.java +++ b/Mage.Sets/src/mage/sets/kaladesh/CapturedByTheConsulate.java @@ -35,7 +35,7 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.AttachEffect; -import mage.abilities.effects.common.combat.CantAttackAttachedEffect; +import mage.abilities.effects.common.combat.CantAttackBlockAttachedEffect; import mage.abilities.keyword.EnchantAbility; import mage.cards.CardImpl; import mage.constants.AttachmentType; @@ -81,8 +81,8 @@ public class CapturedByTheConsulate extends CardImpl { Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); - // Enchanted creature can't attack or block. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackAttachedEffect (AttachmentType.AURA))); + // Enchanted creature can't attack. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackBlockAttachedEffect(AttachmentType.AURA))); // Whenever an opponent casts a spell, if it has a single target, change the target to enchanted creature if able. this.addAbility(new CapturedByTheConsulateTriggeredAbility(Zone.BATTLEFIELD, new CapturedByTheConsulateEffect())); From d01e8303e84a04e99733cfbcf60b6c937f42240e Mon Sep 17 00:00:00 2001 From: brodee Date: Sun, 18 Sep 2016 15:35:56 -0700 Subject: [PATCH 05/50] Captured by the Consulate incorrectly prevented creature from blocking --- Mage.Sets/src/mage/sets/kaladesh/CapturedByTheConsulate.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/kaladesh/CapturedByTheConsulate.java b/Mage.Sets/src/mage/sets/kaladesh/CapturedByTheConsulate.java index 99f8685c7b5..5de6ebe9bdc 100644 --- a/Mage.Sets/src/mage/sets/kaladesh/CapturedByTheConsulate.java +++ b/Mage.Sets/src/mage/sets/kaladesh/CapturedByTheConsulate.java @@ -81,8 +81,8 @@ public class CapturedByTheConsulate extends CardImpl { Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); - // Enchanted creature can't attack or block. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackAttachedEffect (AttachmentType.AURA))); + // Enchanted creature can't attack. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackAttachedEffect(AttachmentType.AURA))); // Whenever an opponent casts a spell, if it has a single target, change the target to enchanted creature if able. this.addAbility(new CapturedByTheConsulateTriggeredAbility(Zone.BATTLEFIELD, new CapturedByTheConsulateEffect())); From 7b336e3a0b59fea145368c1f37fcd19c48ac0b24 Mon Sep 17 00:00:00 2001 From: brodee Date: Sun, 18 Sep 2016 15:44:46 -0700 Subject: [PATCH 06/50] Captured by the Consulate incorrectly prevented creature from blocking --- .../src/mage/sets/kaladesh/CapturedByTheConsulate.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Mage.Sets/src/mage/sets/kaladesh/CapturedByTheConsulate.java b/Mage.Sets/src/mage/sets/kaladesh/CapturedByTheConsulate.java index 7da8c5e6558..5de6ebe9bdc 100644 --- a/Mage.Sets/src/mage/sets/kaladesh/CapturedByTheConsulate.java +++ b/Mage.Sets/src/mage/sets/kaladesh/CapturedByTheConsulate.java @@ -35,7 +35,7 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.AttachEffect; -import mage.abilities.effects.common.combat.CantAttackBlockAttachedEffect; +import mage.abilities.effects.common.combat.CantAttackAttachedEffect; import mage.abilities.keyword.EnchantAbility; import mage.cards.CardImpl; import mage.constants.AttachmentType; @@ -82,11 +82,7 @@ public class CapturedByTheConsulate extends CardImpl { this.addAbility(ability); // Enchanted creature can't attack. -<<<<<<< HEAD this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackAttachedEffect(AttachmentType.AURA))); -======= - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackBlockAttachedEffect(AttachmentType.AURA))); ->>>>>>> b5d965d9ba252dbda528f73a80679958f253b8f6 // Whenever an opponent casts a spell, if it has a single target, change the target to enchanted creature if able. this.addAbility(new CapturedByTheConsulateTriggeredAbility(Zone.BATTLEFIELD, new CapturedByTheConsulateEffect())); From dba0f14591d3747684a9b2aa30b4edf8a3192cfc Mon Sep 17 00:00:00 2001 From: brodee Date: Sun, 18 Sep 2016 23:24:51 -0700 Subject: [PATCH 07/50] Fixed: Inventor's Goggle was triggering for opponent's creatures. it shouldn't --- Mage.Sets/src/mage/sets/kaladesh/InventorsGoggles.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/kaladesh/InventorsGoggles.java b/Mage.Sets/src/mage/sets/kaladesh/InventorsGoggles.java index 630766e4ab7..984fc46d9a6 100644 --- a/Mage.Sets/src/mage/sets/kaladesh/InventorsGoggles.java +++ b/Mage.Sets/src/mage/sets/kaladesh/InventorsGoggles.java @@ -28,7 +28,7 @@ package mage.sets.kaladesh; import java.util.UUID; -import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.AttachEffect; @@ -58,7 +58,7 @@ public class InventorsGoggles extends CardImpl { this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(1, 2, Duration.WhileOnBattlefield))); // Whenever an Artificer enters the battlefield under your control, you may attach Inventor's Goggles to it. - this.addAbility(new EntersBattlefieldAllTriggeredAbility( + this.addAbility(new EntersBattlefieldControlledTriggeredAbility( Zone.BATTLEFIELD, new AttachEffect(Outcome.BoostCreature, "attach {this} to it"), new FilterPermanent("Artificer", "Artificer"), From 5263d1336d38c9980471a70ef84bf50e9dcebe93 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 19 Sep 2016 09:40:19 +0200 Subject: [PATCH 08/50] xmage 1.4.15v4 --- Mage.Common/src/mage/utils/MageVersion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Common/src/mage/utils/MageVersion.java b/Mage.Common/src/mage/utils/MageVersion.java index f851090a8fd..ad4b3c5ef3e 100644 --- a/Mage.Common/src/mage/utils/MageVersion.java +++ b/Mage.Common/src/mage/utils/MageVersion.java @@ -41,7 +41,7 @@ public class MageVersion implements Serializable, Comparable { public final static int MAGE_VERSION_MAJOR = 1; public final static int MAGE_VERSION_MINOR = 4; public final static int MAGE_VERSION_PATCH = 15; - public final static String MAGE_VERSION_MINOR_PATCH = "v2"; + public final static String MAGE_VERSION_MINOR_PATCH = "v4"; public final static String MAGE_VERSION_INFO = ""; private final int major; From 50c2b52d7388ef1a8382ac5ac720f6f74e9e8ed7 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 19 Sep 2016 11:18:49 +0200 Subject: [PATCH 09/50] * Spark of Creativity - Fixed the missing target definition. --- Mage.Sets/src/mage/sets/kaladesh/SparkOfCreativity.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Mage.Sets/src/mage/sets/kaladesh/SparkOfCreativity.java b/Mage.Sets/src/mage/sets/kaladesh/SparkOfCreativity.java index 6f64ad02781..b0d562e2ca2 100644 --- a/Mage.Sets/src/mage/sets/kaladesh/SparkOfCreativity.java +++ b/Mage.Sets/src/mage/sets/kaladesh/SparkOfCreativity.java @@ -44,6 +44,7 @@ import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; /** * @@ -57,6 +58,7 @@ public class SparkOfCreativity extends CardImpl { // Choose target creature. Exile the top card of your library. You may have Spark of Creativity deal damage to that creature equal to the converted mana cost of the exiled card. If you don't, you may play that card until end of turn. this.getSpellAbility().addEffect(new SparkOfCreativityEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } public SparkOfCreativity(final SparkOfCreativity card) { @@ -142,9 +144,7 @@ class SparkOfCreativityPlayEffect extends AsThoughEffectImpl { if (objectReference.refersTo(objectId, game) && affectedControllerId.equals(source.getControllerId())) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - if (controller.chooseUse(outcome, "Play the exiled card?", source, game)) { - return true; - } + return true; } else { discard(); } From b89822a6551bd068083d27513f85928318e917a4 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 19 Sep 2016 11:22:50 +0200 Subject: [PATCH 10/50] * Inventer's Google - Fixed wrong parameters. --- .../mage/sets/kaladesh/InventorsGoggles.java | 163 +++++++++--------- 1 file changed, 81 insertions(+), 82 deletions(-) diff --git a/Mage.Sets/src/mage/sets/kaladesh/InventorsGoggles.java b/Mage.Sets/src/mage/sets/kaladesh/InventorsGoggles.java index 984fc46d9a6..bba7c0e19e7 100644 --- a/Mage.Sets/src/mage/sets/kaladesh/InventorsGoggles.java +++ b/Mage.Sets/src/mage/sets/kaladesh/InventorsGoggles.java @@ -1,82 +1,81 @@ -/* - * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of BetaSteward_at_googlemail.com. - */ -package mage.sets.kaladesh; - -import java.util.UUID; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; -import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.common.AttachEffect; -import mage.abilities.effects.common.continuous.BoostEquippedEffect; -import mage.abilities.keyword.EquipAbility; -import mage.cards.CardImpl; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.SetTargetPointer; -import mage.constants.Zone; -import mage.filter.FilterPermanent; - -/** - * - * @author emerald000 - */ -public class InventorsGoggles extends CardImpl { - - public InventorsGoggles(UUID ownerId) { - super(ownerId, 218, "Inventor's Goggles", Rarity.COMMON, new CardType[]{CardType.ARTIFACT}, "{1}"); - this.expansionSetCode = "KLD"; - this.subtype.add("Equipment"); - - // Equipped creature gets +1/+2. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(1, 2, Duration.WhileOnBattlefield))); - - // Whenever an Artificer enters the battlefield under your control, you may attach Inventor's Goggles to it. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility( - Zone.BATTLEFIELD, - new AttachEffect(Outcome.BoostCreature, "attach {this} to it"), - new FilterPermanent("Artificer", "Artificer"), - true, - SetTargetPointer.PERMANENT, - null, - true)); - - // Equip {2} - this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(2))); - } - - public InventorsGoggles(final InventorsGoggles card) { - super(card); - } - - @Override - public InventorsGoggles copy() { - return new InventorsGoggles(this); - } -} +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.BoostEquippedEffect; +import mage.abilities.keyword.EquipAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.SetTargetPointer; +import mage.constants.Zone; +import mage.filter.FilterPermanent; + +/** + * + * @author emerald000 + */ +public class InventorsGoggles extends CardImpl { + + public InventorsGoggles(UUID ownerId) { + super(ownerId, 218, "Inventor's Goggles", Rarity.COMMON, new CardType[]{CardType.ARTIFACT}, "{1}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Equipment"); + + // Equipped creature gets +1/+2. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(1, 2, Duration.WhileOnBattlefield))); + + // Whenever an Artificer enters the battlefield under your control, you may attach Inventor's Goggles to it. + this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + Zone.BATTLEFIELD, + new AttachEffect(Outcome.BoostCreature, "attach {this} to it"), + new FilterPermanent("Artificer", "Artificer"), + true, + SetTargetPointer.PERMANENT, + null)); + + // Equip {2} + this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(2))); + } + + public InventorsGoggles(final InventorsGoggles card) { + super(card); + } + + @Override + public InventorsGoggles copy() { + return new InventorsGoggles(this); + } +} From 120d7612f625662796f75c1647193709041549b2 Mon Sep 17 00:00:00 2001 From: emerald000 Date: Mon, 19 Sep 2016 09:22:21 -0400 Subject: [PATCH 11/50] Fixed Panharmonicon triggering for opponents abilities. Added tests. --- .../src/mage/sets/kaladesh/Panharmonicon.java | 16 ++- .../cards/replacement/PanharmoniconTest.java | 105 ++++++++++++++++++ .../mage/abilities/TriggeredAbilities.java | 8 +- .../events/EntersTheBattlefieldEvent.java | 6 +- .../main/java/mage/game/events/GameEvent.java | 1 + .../game/events/NumberOfTriggersEvent.java | 50 +++++++++ .../mage/game/permanent/PermanentImpl.java | 7 +- 7 files changed, 178 insertions(+), 15 deletions(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/replacement/PanharmoniconTest.java create mode 100644 Mage/src/main/java/mage/game/events/NumberOfTriggersEvent.java diff --git a/Mage.Sets/src/mage/sets/kaladesh/Panharmonicon.java b/Mage.Sets/src/mage/sets/kaladesh/Panharmonicon.java index f335d301cab..187da675f2a 100644 --- a/Mage.Sets/src/mage/sets/kaladesh/Panharmonicon.java +++ b/Mage.Sets/src/mage/sets/kaladesh/Panharmonicon.java @@ -41,7 +41,7 @@ import mage.game.Game; import mage.game.events.EntersTheBattlefieldEvent; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; -import mage.game.permanent.Permanent; +import mage.game.events.NumberOfTriggersEvent; /** * @@ -85,15 +85,19 @@ class PanharmoniconEffect extends ReplacementEffectImpl { @Override public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == EventType.ENTERS_THE_BATTLEFIELD; + return event.getType() == EventType.NUMBER_OF_TRIGGERS; } @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event instanceof EntersTheBattlefieldEvent) { - Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget(); - if (permanent != null) { - return permanent.getCardType().contains(CardType.ARTIFACT) || permanent.getCardType().contains(CardType.CREATURE); + if (event instanceof NumberOfTriggersEvent) { + NumberOfTriggersEvent numberOfTriggersEvent = (NumberOfTriggersEvent) event; + if (source.getControllerId().equals(event.getPlayerId())) { + GameEvent sourceEvent = numberOfTriggersEvent.getSourceEvent(); + if (sourceEvent.getType() == EventType.ENTERS_THE_BATTLEFIELD && sourceEvent instanceof EntersTheBattlefieldEvent) { + EntersTheBattlefieldEvent entersTheBattlefieldEvent = (EntersTheBattlefieldEvent) sourceEvent; + return entersTheBattlefieldEvent.getTarget().getCardType().contains(CardType.ARTIFACT) || entersTheBattlefieldEvent.getTarget().getCardType().contains(CardType.CREATURE); + } } } return false; diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/PanharmoniconTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/PanharmoniconTest.java new file mode 100644 index 00000000000..d3286978fd1 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/PanharmoniconTest.java @@ -0,0 +1,105 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package org.mage.test.cards.replacement; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class PanharmoniconTest extends CardTestPlayerBase { + + /** + * Check that Panharmonicon adds EtB triggers correctly. + * + */ + @Test + public void testAddsTrigger() { + // If an artifact or creature entering the battlefield causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time. + addCard(Zone.BATTLEFIELD, playerA, "Panharmonicon"); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); + // Whenever another creature enters the battlefield, you gain 1 life. + addCard(Zone.HAND, playerA, "Soul Warden"); + // When Devout Monk enters the battlefield, you gain 1 life. + addCard(Zone.HAND, playerA, "Devout Monk"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Soul Warden"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Devout Monk"); // Life: 20 + 2*1 + 2*1 = 24 + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerA, 24); + } + + /** + * Check that Panharmonicon doesn't add to opponents' triggers. + * + */ + @Test + public void testDoesntAddOpponentsTriggers() { + // If an artifact or creature entering the battlefield causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time. + addCard(Zone.BATTLEFIELD, playerA, "Panharmonicon"); + addCard(Zone.BATTLEFIELD, playerB, "Plains", 2); + // Whenever another creature enters the battlefield, you gain 1 life. + addCard(Zone.HAND, playerB, "Soul Warden"); + // When Devout Monk enters the battlefield, you gain 1 life. + addCard(Zone.HAND, playerB, "Devout Monk"); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Soul Warden"); + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Devout Monk"); // Life: 20 + 1 + 1 = 22 + + setStopAt(2, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerB, 22); + } + + /** + * Check that Panharmonicon doesn't add to lands triggers. + * + */ + @Test + public void testDoesntAddLandsTriggers() { + // If an artifact or creature entering the battlefield causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time. + addCard(Zone.BATTLEFIELD, playerA, "Panharmonicon"); + // When Radiant Fountain enters the battlefield, you gain 2 life. + addCard(Zone.HAND, playerA, "Radiant Fountain"); + + playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Radiant Fountain"); // Life: 20 + 2 = 22 + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerA, 22); + } +} diff --git a/Mage/src/main/java/mage/abilities/TriggeredAbilities.java b/Mage/src/main/java/mage/abilities/TriggeredAbilities.java index c066f8ef090..e5fd438390d 100644 --- a/Mage/src/main/java/mage/abilities/TriggeredAbilities.java +++ b/Mage/src/main/java/mage/abilities/TriggeredAbilities.java @@ -41,6 +41,7 @@ import mage.cards.Card; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; +import mage.game.events.NumberOfTriggersEvent; import mage.game.permanent.Permanent; import mage.game.stack.Spell; @@ -124,7 +125,12 @@ public class TriggeredAbilities extends ConcurrentHashMap appliedEffects) { super(EventType.ENTERS_THE_BATTLEFIELD, target.getId(), sourceId, playerId); this.fromZone = fromZone; - this.target = target; if (appliedEffects != null) { this.appliedEffects = appliedEffects; } - this.amount = 1; // Number of times to trigger (Panharmonicon can change that value) } public Zone getFromZone() { diff --git a/Mage/src/main/java/mage/game/events/GameEvent.java b/Mage/src/main/java/mage/game/events/GameEvent.java index a984f80cbad..9e2626b6015 100644 --- a/Mage/src/main/java/mage/game/events/GameEvent.java +++ b/Mage/src/main/java/mage/game/events/GameEvent.java @@ -266,6 +266,7 @@ public class GameEvent implements Serializable { REGENERATE, REGENERATED, CHANGE_COLOR, COLOR_CHANGED, + NUMBER_OF_TRIGGERS, //combat events COMBAT_DAMAGE_APPLIED, SELECTED_ATTACKER, SELECTED_BLOCKER; diff --git a/Mage/src/main/java/mage/game/events/NumberOfTriggersEvent.java b/Mage/src/main/java/mage/game/events/NumberOfTriggersEvent.java new file mode 100644 index 00000000000..881baac488f --- /dev/null +++ b/Mage/src/main/java/mage/game/events/NumberOfTriggersEvent.java @@ -0,0 +1,50 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +package mage.game.events; + +import java.util.UUID; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class NumberOfTriggersEvent extends GameEvent { + + private final GameEvent sourceEvent; + + public NumberOfTriggersEvent(UUID controllerOfAbilityId, GameEvent sourceEvent) { + super(EventType.NUMBER_OF_TRIGGERS, null, null, controllerOfAbilityId); + this.sourceEvent = sourceEvent; + this.amount = 1; // Number of times to trigger. Panharmonicon can change this. + } + + public GameEvent getSourceEvent() { + return sourceEvent; + } +} diff --git a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java index cb4d9d8a211..fa4319cbecc 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java @@ -881,12 +881,9 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { EntersTheBattlefieldEvent event = new EntersTheBattlefieldEvent(this, sourceId, getControllerId(), fromZone); if (!game.replaceEvent(event)) { if (fireEvent) { - // Trigger multiple times with Panharmonicon. - for (int i = 0; i < event.getAmount(); i++) { - game.addSimultaneousEvent(event); - } + game.addSimultaneousEvent(event); + return true; } - return true; } return false; } From a4195b2bb0a789c28bf026f6fac88153a7e64dc5 Mon Sep 17 00:00:00 2001 From: spjspj Date: Mon, 19 Sep 2016 23:42:43 +1000 Subject: [PATCH 12/50] spjspj - Fix for if Combustible Gearhulk dies prior to trigger resolving KLD --- Mage.Sets/src/mage/sets/kaladesh/CombustibleGearhulk.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/kaladesh/CombustibleGearhulk.java b/Mage.Sets/src/mage/sets/kaladesh/CombustibleGearhulk.java index d5645ae1394..228d426b2c7 100644 --- a/Mage.Sets/src/mage/sets/kaladesh/CombustibleGearhulk.java +++ b/Mage.Sets/src/mage/sets/kaladesh/CombustibleGearhulk.java @@ -99,7 +99,7 @@ class CombustibleGearhulkEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); if (controller != null && sourcePermanent != null) { UUID opponentId; if (game.getOpponents(controller.getId()).size() == 1) { From e22184180d00df7e34a222c388b6ec64ceb16c9f Mon Sep 17 00:00:00 2001 From: spjspj Date: Tue, 20 Sep 2016 01:49:51 +1000 Subject: [PATCH 13/50] spjspj - Add 'Delayed Submit' button to the deck editor --- .../client/deckeditor/DeckEditorPanel.form | 11 ++- .../client/deckeditor/DeckEditorPanel.java | 89 ++++++++++++++----- 2 files changed, 78 insertions(+), 22 deletions(-) diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.form b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.form index f0db80d7055..5065dfbe631 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.form +++ b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.form @@ -201,7 +201,16 @@ - + + + + + + + + + + diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java index 266562a8d88..92ea6ce6421 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java +++ b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java @@ -27,6 +27,25 @@ */ package mage.client.deckeditor; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.File; +import java.io.IOException; +import java.util.*; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import javax.swing.*; +import javax.swing.Timer; +import javax.swing.filechooser.FileFilter; import mage.cards.Card; import mage.cards.Sets; import mage.cards.decks.Deck; @@ -39,8 +58,8 @@ import mage.client.SessionHandler; import mage.client.cards.BigCard; import mage.client.cards.ICardGrid; import mage.client.constants.Constants.DeckEditorMode; -import mage.client.deck.generator.DeckGenerator; import mage.client.deck.generator.DeckGenerator.DeckGeneratorException; +import mage.client.deck.generator.DeckGenerator; import mage.client.dialog.AddLandDialog; import mage.client.plugins.impl.Plugins; import mage.client.util.Event; @@ -52,22 +71,6 @@ import mage.remote.Session; import mage.view.CardView; import mage.view.SimpleCardView; import org.apache.log4j.Logger; - -import javax.swing.*; -import javax.swing.Timer; -import javax.swing.filechooser.FileFilter; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.io.File; -import java.io.IOException; -import java.util.*; -import java.util.List; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; - /** * * @author BetaSteward_at_googlemail.com @@ -84,6 +87,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { private int timeout; private Timer countdown; private UpdateDeckTask updateDeckTask; + private int timeToSubmit = -1; /** * Creates new form DeckEditorPanel @@ -160,6 +164,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { this.txtTimeRemaining.setVisible(true); case SIDEBOARDING: this.btnSubmit.setVisible(true); + this.btnSubmitTimer.setVisible(true); if (deck != null) { this.cardSelector.loadSideboard(new ArrayList<>(deck.getSideboard()), this.bigCard); } @@ -187,6 +192,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { case FREE_BUILDING: this.deckArea.setOrientation(/*limitedBuildingOrientation = */false); this.btnSubmit.setVisible(false); + this.btnSubmitTimer.setVisible(false); this.btnAddLand.setVisible(true); this.cardSelector.loadCards(this.bigCard); //this.cardTableSelector.loadCards(this.bigCard); @@ -484,6 +490,11 @@ public class DeckEditorPanel extends javax.swing.JPanel { if (s == 60) { AudioManager.playOnCountdown1(); } + if (timeToSubmit > 0) { + timeToSubmit --; + btnSubmitTimer.setText("Submit (" + timeToSubmit + ")"); + btnSubmitTimer.setToolTipText("Submit your deck in " + timeToSubmit + " seconds!"); + } } private void initComponents() { @@ -501,6 +512,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { btnExit = new javax.swing.JButton(); btnImport = new javax.swing.JButton(); btnSubmit = new javax.swing.JButton(); + btnSubmitTimer = new javax.swing.JButton(); btnAddLand = new javax.swing.JButton(); btnGenDeck = new javax.swing.JButton(); txtTimeRemaining = new javax.swing.JTextField(); @@ -594,6 +606,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { }); btnSubmit.setText("Submit"); + btnSubmitTimer.setToolTipText("Submit your deck now!"); btnSubmit.setName("btnSubmit"); // NOI18N btnSubmit.addActionListener(new java.awt.event.ActionListener() { @Override @@ -602,6 +615,16 @@ public class DeckEditorPanel extends javax.swing.JPanel { } }); + btnSubmitTimer.setText("Submit (60s)"); + btnSubmitTimer.setToolTipText("Submit your deck in one minute!"); + btnSubmitTimer.setName("btnSubmitTimer"); + btnSubmitTimer.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnSubmitTimerActionPerformed(evt); + } + }); + btnAddLand.setText("Add Land"); btnAddLand.setName("btnAddLand"); // NOI18N btnAddLand.addActionListener(new java.awt.event.ActionListener() { @@ -610,7 +633,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { btnAddLandActionPerformed(evt); } }); - + btnGenDeck.setText("Generate"); btnGenDeck.setName("btnGenDeck"); btnGenDeck.addActionListener(new java.awt.event.ActionListener() { @@ -658,7 +681,9 @@ public class DeckEditorPanel extends javax.swing.JPanel { .addContainerGap() .addComponent(btnAddLand) .addContainerGap() - .addComponent(btnSubmit)) + .addComponent(btnSubmit) + .addContainerGap() + .addComponent(btnSubmitTimer)) .addGroup(jPanel1Layout.createSequentialGroup() .addContainerGap() .addComponent(txtTimeRemaining)) @@ -682,7 +707,8 @@ public class DeckEditorPanel extends javax.swing.JPanel { .addComponent(btnImport) .addComponent(btnGenDeck) .addComponent(btnAddLand) - .addComponent(btnSubmit)) + .addComponent(btnSubmit) + .addComponent(btnSubmitTimer)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(txtTimeRemaining)) @@ -847,6 +873,26 @@ public class DeckEditorPanel extends javax.swing.JPanel { } }//GEN-LAST:event_btnSubmitActionPerformed + private void btnSubmitTimerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSubmitTimerActionPerformed + + ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5); + timeToSubmit = 60; + this.btnSubmitTimer.setEnabled(false); + + ScheduledFuture scheduledFuture = scheduledExecutorService.schedule(new Callable() { + public Object call() throws Exception { + if (updateDeckTask != null) { + updateDeckTask.cancel(true); + } + + if (SessionHandler.submitDeck(tableId, deck.getDeckCardLists())) { + removeDeckEditor(); + } + return null; + } + }, 60, TimeUnit.SECONDS); + }//GEN-LAST:event_btnSubmitTimerActionPerformed + private void btnAddLandActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAddLandActionPerformed AddLandDialog addLand = new AddLandDialog(); addLand.showDialog(deck, mode); @@ -867,7 +913,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { } refreshDeck(); } - + // Variables declaration - do not modify//GEN-BEGIN:variables private mage.client.cards.BigCard bigCard; private javax.swing.JButton btnExit; @@ -882,6 +928,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { private javax.swing.JLabel lblDeckName; private javax.swing.JTextField txtDeckName; private javax.swing.JButton btnSubmit; + private javax.swing.JButton btnSubmitTimer; private javax.swing.JButton btnAddLand; private javax.swing.JButton btnGenDeck; private JComponent cardInfoPane; From 8485df8cb7bc74e0aa4c121c01f75f20685affd9 Mon Sep 17 00:00:00 2001 From: Styxo Date: Tue, 20 Sep 2016 00:17:56 +0200 Subject: [PATCH 14/50] Added Blessed Wind and few refactors --- .../sets/magic2014/StrionicResonator.java | 83 +------------ .../sets/mirrodinbesieged/MelirasKeepers.java | 38 +----- .../src/mage/sets/prophecy/BlessedWind.java | 60 +++++++++ .../src/mage/sets/ravnica/TwilightDrover.java | 59 ++------- .../src/mage/sets/shadowmoor/Tatterkite.java | 40 +----- ...CombatDamageToAPlayerTriggeredAbility.java | 16 ++- .../LeavesBattlefieldAllTriggeredAbility.java | 93 ++++++++++++++ .../common/SetPlayerLifeTargetEffect.java | 81 ++++++++++++ .../CantHaveCountersSourceEffect.java | 71 +++++++++++ .../target/common/TargetTriggeredAbility.java | 117 ++++++++++++++++++ 10 files changed, 453 insertions(+), 205 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/prophecy/BlessedWind.java create mode 100644 Mage/src/main/java/mage/abilities/common/LeavesBattlefieldAllTriggeredAbility.java create mode 100644 Mage/src/main/java/mage/abilities/effects/common/SetPlayerLifeTargetEffect.java create mode 100644 Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CantHaveCountersSourceEffect.java create mode 100644 Mage/src/main/java/mage/target/common/TargetTriggeredAbility.java diff --git a/Mage.Sets/src/mage/sets/magic2014/StrionicResonator.java b/Mage.Sets/src/mage/sets/magic2014/StrionicResonator.java index 03f256ba0d9..1f56faed819 100644 --- a/Mage.Sets/src/mage/sets/magic2014/StrionicResonator.java +++ b/Mage.Sets/src/mage/sets/magic2014/StrionicResonator.java @@ -27,12 +27,9 @@ */ package mage.sets.magic2014; -import java.util.HashSet; -import java.util.Set; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.Mode; -import mage.abilities.TriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; @@ -42,14 +39,11 @@ import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; -import mage.filter.Filter; -import mage.filter.FilterAbility; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.stack.StackAbility; -import mage.game.stack.StackObject; import mage.players.Player; -import mage.target.TargetObject; +import mage.target.common.TargetTriggeredAbility; /** * @@ -96,7 +90,7 @@ class StrionicResonatorEffect extends OneShotEffect { Permanent sourcePermanent = game.getPermanent(source.getSourceId()); if (controller != null && sourcePermanent != null) { stackAbility.createCopyOnStack(game, source, source.getControllerId(), true); - game.informPlayers(new StringBuilder(sourcePermanent.getName()).append(": ").append(controller.getLogName()).append(" copied activated ability").toString()); + game.informPlayers(new StringBuilder(sourcePermanent.getName()).append(": ").append(controller.getLogName()).append(" copied triggered ability").toString()); return true; } } @@ -116,76 +110,3 @@ class StrionicResonatorEffect extends OneShotEffect { return sb.toString(); } } - -class TargetTriggeredAbility extends TargetObject { - - public TargetTriggeredAbility() { - this.minNumberOfTargets = 1; - this.maxNumberOfTargets = 1; - this.zone = Zone.STACK; - this.targetName = "target triggered ability you control"; - } - - public TargetTriggeredAbility(final TargetTriggeredAbility target) { - super(target); - } - - @Override - public boolean canTarget(UUID id, Ability source, Game game) { - if (source != null && source.getSourceId().equals(id)) { - return false; - } - - StackObject stackObject = game.getStack().getStackObject(id); - return stackObject.getStackAbility() != null - && (stackObject.getStackAbility() instanceof TriggeredAbility) - && source != null - && stackObject.getStackAbility().getControllerId().equals(source.getControllerId()); - } - - @Override - public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { - return canChoose(sourceControllerId, game); - } - - @Override - public boolean canChoose(UUID sourceControllerId, Game game) { - for (StackObject stackObject : game.getStack()) { - if (stackObject.getStackAbility() != null - && stackObject.getStackAbility() instanceof TriggeredAbility - && stackObject.getStackAbility().getControllerId().equals(sourceControllerId)) { - return true; - } - } - return false; - } - - @Override - public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { - return possibleTargets(sourceControllerId, game); - } - - @Override - public Set possibleTargets(UUID sourceControllerId, Game game) { - Set possibleTargets = new HashSet<>(); - for (StackObject stackObject : game.getStack()) { - if (stackObject.getStackAbility() != null - && stackObject.getStackAbility() instanceof TriggeredAbility - && stackObject.getStackAbility().getControllerId().equals(sourceControllerId)) { - possibleTargets.add(stackObject.getStackAbility().getId()); - } - } - return possibleTargets; - } - - @Override - public TargetTriggeredAbility copy() { - return new TargetTriggeredAbility(this); - } - - @Override - public Filter getFilter() { - return new FilterAbility(); - } - -} diff --git a/Mage.Sets/src/mage/sets/mirrodinbesieged/MelirasKeepers.java b/Mage.Sets/src/mage/sets/mirrodinbesieged/MelirasKeepers.java index 899228b0ee5..74510145dcb 100644 --- a/Mage.Sets/src/mage/sets/mirrodinbesieged/MelirasKeepers.java +++ b/Mage.Sets/src/mage/sets/mirrodinbesieged/MelirasKeepers.java @@ -29,18 +29,12 @@ package mage.sets.mirrodinbesieged; import java.util.UUID; import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.effects.common.ruleModifying.CantHaveCountersSourceEffect; import mage.cards.CardImpl; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; /** * @@ -58,7 +52,7 @@ public class MelirasKeepers extends CardImpl { this.toughness = new MageInt(4); // Melira's Keepers can't have counters placed on it - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MelirasKeepersEffect())); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantHaveCountersSourceEffect())); } public MelirasKeepers(final MelirasKeepers card) { @@ -71,31 +65,3 @@ public class MelirasKeepers extends CardImpl { } } - -class MelirasKeepersEffect extends ContinuousRuleModifyingEffectImpl { - - public MelirasKeepersEffect() { - super(Duration.WhileOnBattlefield, Outcome.PreventDamage); - staticText = "{this} can't have counters placed on it"; - } - - public MelirasKeepersEffect(final MelirasKeepersEffect effect) { - super(effect); - } - - @Override - public MelirasKeepersEffect copy() { - return new MelirasKeepersEffect(this); - } - - @Override - public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == EventType.ADD_COUNTER; - } - - @Override - public boolean applies(GameEvent event, Ability source, Game game) { - return event.getTargetId().equals(source.getSourceId()); - } - -} diff --git a/Mage.Sets/src/mage/sets/prophecy/BlessedWind.java b/Mage.Sets/src/mage/sets/prophecy/BlessedWind.java new file mode 100644 index 00000000000..8f7f89c0371 --- /dev/null +++ b/Mage.Sets/src/mage/sets/prophecy/BlessedWind.java @@ -0,0 +1,60 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.prophecy; + +import java.util.UUID; +import mage.abilities.effects.common.SetPlayerLifeTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.target.TargetPlayer; + +/** + * + * @author Styxo + */ +public class BlessedWind extends CardImpl { + + public BlessedWind(UUID ownerId) { + super(ownerId, 4, "Blessed Wind", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{7}{W}{W}"); + this.expansionSetCode = "PCY"; + + // Target player's life total becomes 20. + this.getSpellAbility().addEffect(new SetPlayerLifeTargetEffect(20)); + this.getSpellAbility().addTarget(new TargetPlayer()); + } + + public BlessedWind(final BlessedWind card) { + super(card); + } + + @Override + public BlessedWind copy() { + return new BlessedWind(this); + } +} diff --git a/Mage.Sets/src/mage/sets/ravnica/TwilightDrover.java b/Mage.Sets/src/mage/sets/ravnica/TwilightDrover.java index 77d58ada0e2..6d552e89843 100644 --- a/Mage.Sets/src/mage/sets/ravnica/TwilightDrover.java +++ b/Mage.Sets/src/mage/sets/ravnica/TwilightDrover.java @@ -30,7 +30,7 @@ package mage.sets.ravnica; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.LeavesBattlefieldAllTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.RemoveCountersSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; @@ -41,12 +41,8 @@ import mage.constants.CardType; import mage.constants.Rarity; import mage.constants.Zone; import mage.counters.CounterType; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; -import mage.game.events.ZoneChangeEvent; -import mage.game.permanent.Permanent; -import mage.game.permanent.PermanentToken; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.TokenPredicate; import mage.game.permanent.token.SpiritWhiteToken; /** @@ -55,6 +51,12 @@ import mage.game.permanent.token.SpiritWhiteToken; */ public class TwilightDrover extends CardImpl { + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("a creature token"); + + static { + filter.add(new TokenPredicate()); + } + public TwilightDrover(UUID ownerId) { super(ownerId, 33, "Twilight Drover", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{W}"); this.expansionSetCode = "RAV"; @@ -64,8 +66,8 @@ public class TwilightDrover extends CardImpl { this.toughness = new MageInt(1); // Whenever a creature token leaves the battlefield, put a +1/+1 counter on Twilight Drover. - this.addAbility(new TwilightDroverTriggeredAbility()); - + this.addAbility(new LeavesBattlefieldAllTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), filter)); + // {2}{W}, Remove a +1/+1 counter from Twilight Drover: Put two 1/1 white Spirit creature tokens with flying onto the battlefield. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new SpiritWhiteToken("RAV"), 2), new ManaCostsImpl<>("{2}{W}")); ability.addCost(new RemoveCountersSourceCost(CounterType.P1P1.createInstance())); @@ -81,42 +83,3 @@ public class TwilightDrover extends CardImpl { return new TwilightDrover(this); } } - -class TwilightDroverTriggeredAbility extends TriggeredAbilityImpl { - - TwilightDroverTriggeredAbility() { - super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false); - } - - TwilightDroverTriggeredAbility(final TwilightDroverTriggeredAbility ability) { - super(ability); - } - - @Override - public TwilightDroverTriggeredAbility copy() { - return new TwilightDroverTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == EventType.ZONE_CHANGE; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - if (zEvent.getFromZone() == Zone.BATTLEFIELD) { - UUID targetId = event.getTargetId(); - Permanent permanent = game.getPermanentOrLKIBattlefield(targetId); - if (permanent != null) { - return permanent.getCardType().contains(CardType.CREATURE) && permanent instanceof PermanentToken; - } - } - return false; - } - - @Override - public String getRule() { - return "Whenever a creature token leaves the battlefield, put a +1/+1 counter on {this}"; - } -} diff --git a/Mage.Sets/src/mage/sets/shadowmoor/Tatterkite.java b/Mage.Sets/src/mage/sets/shadowmoor/Tatterkite.java index f10c0e25d3c..d17dedb4b1a 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/Tatterkite.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/Tatterkite.java @@ -29,19 +29,14 @@ package mage.sets.shadowmoor; import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.effects.common.ruleModifying.CantHaveCountersSourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; /** * @@ -60,7 +55,7 @@ public class Tatterkite extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Tatterkite can't have counters placed on it. - this.addAbility(new SimpleStaticAbility(Zone.ALL, new CantHaveCountersSourceEffect(Duration.WhileOnBattlefield))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantHaveCountersSourceEffect())); } @@ -73,34 +68,3 @@ public class Tatterkite extends CardImpl { return new Tatterkite(this); } } - -class CantHaveCountersSourceEffect extends ContinuousRuleModifyingEffectImpl { - - public CantHaveCountersSourceEffect(Duration duration) { - super(duration, Outcome.Detriment); - staticText = "{this} can't have counters placed on it"; - } - - public CantHaveCountersSourceEffect(final CantHaveCountersSourceEffect effect) { - super(effect); - } - - @Override - public CantHaveCountersSourceEffect copy() { - return new CantHaveCountersSourceEffect(this); - } - - @Override - public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == EventType.ADD_COUNTERS; - } - - @Override - public boolean applies(GameEvent event, Ability source, Game game) { - UUID sourceId = source.getSourceId(); - if (sourceId != null) { - return sourceId.equals(event.getTargetId()); - } - return false; - } -} diff --git a/Mage/src/main/java/mage/abilities/common/DealsCombatDamageToAPlayerTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/DealsCombatDamageToAPlayerTriggeredAbility.java index 429f9c34340..43f94d113cc 100644 --- a/Mage/src/main/java/mage/abilities/common/DealsCombatDamageToAPlayerTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/DealsCombatDamageToAPlayerTriggeredAbility.java @@ -29,6 +29,7 @@ package mage.abilities.common; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; +import mage.constants.SetTargetPointer; import mage.constants.Zone; import mage.game.Game; import mage.game.events.DamagedPlayerEvent; @@ -41,7 +42,8 @@ import mage.target.targetpointer.FixedTarget; */ public class DealsCombatDamageToAPlayerTriggeredAbility extends TriggeredAbilityImpl { - private boolean setTargetPointer; + protected boolean setTargetPointer; + protected String text; public DealsCombatDamageToAPlayerTriggeredAbility(Effect effect, boolean optional) { this(effect, optional, false); @@ -52,8 +54,15 @@ public class DealsCombatDamageToAPlayerTriggeredAbility extends TriggeredAbility this.setTargetPointer = setTargetPointer; } + public DealsCombatDamageToAPlayerTriggeredAbility(Effect effect, boolean optional, String text, boolean setTargetPointer) { + super(Zone.BATTLEFIELD, effect, optional); + this.text = text; + this.setTargetPointer = setTargetPointer; + } + public DealsCombatDamageToAPlayerTriggeredAbility(final DealsCombatDamageToAPlayerTriggeredAbility ability) { super(ability); + this.text = ability.text; this.setTargetPointer = ability.setTargetPointer; } @@ -84,7 +93,10 @@ public class DealsCombatDamageToAPlayerTriggeredAbility extends TriggeredAbility @Override public String getRule() { - return "Whenever {this} deals combat damage to a player, " + super.getRule(); + if (text == null || text.isEmpty()) { + return "Whenever {this} deals combat damage to a player, " + super.getRule(); + } + return text; } } diff --git a/Mage/src/main/java/mage/abilities/common/LeavesBattlefieldAllTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/LeavesBattlefieldAllTriggeredAbility.java new file mode 100644 index 00000000000..2c056774679 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/common/LeavesBattlefieldAllTriggeredAbility.java @@ -0,0 +1,93 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.abilities.common; + +import java.util.UUID; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; + +/** + * + * @author Styxo + */ +public class LeavesBattlefieldAllTriggeredAbility extends TriggeredAbilityImpl { + + protected FilterPermanent filter; + + public LeavesBattlefieldAllTriggeredAbility(Effect effect, FilterPermanent filter) { + this(effect, filter, false); + } + + public LeavesBattlefieldAllTriggeredAbility(Effect effect, FilterPermanent filter, boolean optional) { + this(Zone.BATTLEFIELD, effect, filter, optional); + } + + public LeavesBattlefieldAllTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional) { + super(zone, effect, optional); + this.filter = filter; + } + + public LeavesBattlefieldAllTriggeredAbility(final LeavesBattlefieldAllTriggeredAbility ability) { + super(ability); + filter = ability.filter; + } + + @Override + public LeavesBattlefieldAllTriggeredAbility copy() { + return new LeavesBattlefieldAllTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ZONE_CHANGE; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; + if (zEvent.getFromZone() == Zone.BATTLEFIELD) { + UUID targetId = event.getTargetId(); + Permanent permanent = game.getPermanentOrLKIBattlefield(targetId); + if (permanent != null) { + return filter.match(permanent, getSourceId(), getControllerId(), game); + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever " + filter.getMessage() + " leaves the battlefield, " + super.getRule(); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/SetPlayerLifeTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/SetPlayerLifeTargetEffect.java new file mode 100644 index 00000000000..f38181d11e9 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/SetPlayerLifeTargetEffect.java @@ -0,0 +1,81 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.abilities.effects.common; + +import mage.abilities.Ability; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author Styxo + */ +public class SetPlayerLifeTargetEffect extends OneShotEffect { + + protected DynamicValue amount; + + public SetPlayerLifeTargetEffect(int amount) { + this(new StaticValue(amount)); + } + + public SetPlayerLifeTargetEffect(DynamicValue amount) { + super(Outcome.Neutral); + this.amount = amount; + this.staticText = setText(); + } + + public SetPlayerLifeTargetEffect(final SetPlayerLifeTargetEffect effect) { + super(effect); + this.amount = effect.amount; + } + + @Override + public SetPlayerLifeTargetEffect copy() { + return new SetPlayerLifeTargetEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(targetPointer.getFirst(game, source)); + if (player != null) { + player.setLife(amount.calculate(game, source, this), game); + return true; + } + return false; + } + + private String setText() { + StringBuilder sb = new StringBuilder("Target player's life total becomes "); + sb.append(amount.toString()); + return sb.toString(); + } +} \ No newline at end of file diff --git a/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CantHaveCountersSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CantHaveCountersSourceEffect.java new file mode 100644 index 00000000000..e6ca45a18b4 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CantHaveCountersSourceEffect.java @@ -0,0 +1,71 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.abilities.effects.common.ruleModifying; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.events.GameEvent; + +/** + * + * @author Styxo + */ +public class CantHaveCountersSourceEffect extends ContinuousRuleModifyingEffectImpl { + + public CantHaveCountersSourceEffect() { + super(Duration.WhileOnBattlefield, Outcome.Detriment); + staticText = "{this} can't have counters placed on it"; + } + + public CantHaveCountersSourceEffect(final CantHaveCountersSourceEffect effect) { + super(effect); + } + + @Override + public CantHaveCountersSourceEffect copy() { + return new CantHaveCountersSourceEffect(this); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ADD_COUNTERS; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + UUID sourceId = source.getSourceId(); + if (sourceId != null) { + return sourceId.equals(event.getTargetId()); + } + return false; + } +} diff --git a/Mage/src/main/java/mage/target/common/TargetTriggeredAbility.java b/Mage/src/main/java/mage/target/common/TargetTriggeredAbility.java new file mode 100644 index 00000000000..22896eab0d9 --- /dev/null +++ b/Mage/src/main/java/mage/target/common/TargetTriggeredAbility.java @@ -0,0 +1,117 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.target.common; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbility; +import mage.constants.Zone; +import mage.filter.Filter; +import mage.filter.FilterAbility; +import mage.game.Game; +import mage.game.stack.StackObject; +import mage.target.TargetObject; + +/** + * + * @author Styxo + */ +public class TargetTriggeredAbility extends TargetObject { + + public TargetTriggeredAbility() { + this.minNumberOfTargets = 1; + this.maxNumberOfTargets = 1; + this.zone = Zone.STACK; + this.targetName = "target triggered ability you control"; + } + + public TargetTriggeredAbility(final TargetTriggeredAbility target) { + super(target); + } + + @Override + public boolean canTarget(UUID id, Ability source, Game game) { + if (source != null && source.getSourceId().equals(id)) { + return false; + } + + StackObject stackObject = game.getStack().getStackObject(id); + return stackObject.getStackAbility() != null + && (stackObject.getStackAbility() instanceof TriggeredAbility) + && source != null + && stackObject.getStackAbility().getControllerId().equals(source.getControllerId()); + } + + @Override + public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { + return canChoose(sourceControllerId, game); + } + + @Override + public boolean canChoose(UUID sourceControllerId, Game game) { + for (StackObject stackObject : game.getStack()) { + if (stackObject.getStackAbility() != null + && stackObject.getStackAbility() instanceof TriggeredAbility + && stackObject.getStackAbility().getControllerId().equals(sourceControllerId)) { + return true; + } + } + return false; + } + + @Override + public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { + return possibleTargets(sourceControllerId, game); + } + + @Override + public Set possibleTargets(UUID sourceControllerId, Game game) { + Set possibleTargets = new HashSet<>(); + for (StackObject stackObject : game.getStack()) { + if (stackObject.getStackAbility() != null + && stackObject.getStackAbility() instanceof TriggeredAbility + && stackObject.getStackAbility().getControllerId().equals(sourceControllerId)) { + possibleTargets.add(stackObject.getStackAbility().getId()); + } + } + return possibleTargets; + } + + @Override + public TargetTriggeredAbility copy() { + return new TargetTriggeredAbility(this); + } + + @Override + public Filter getFilter() { + return new FilterAbility(); + } + +} From 9cec1aa54bc644a9011a2670a59d05b08993fc3a Mon Sep 17 00:00:00 2001 From: Fr33dan Date: Tue, 20 Sep 2016 01:05:06 -0400 Subject: [PATCH 15/50] Update EraOfInnovation.java Card triggered for all creatures when it should only trigger for Artificers --- Mage.Sets/src/mage/sets/kaladesh/EraOfInnovation.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/kaladesh/EraOfInnovation.java b/Mage.Sets/src/mage/sets/kaladesh/EraOfInnovation.java index 48ea1a388b2..34774ce5ee2 100644 --- a/Mage.Sets/src/mage/sets/kaladesh/EraOfInnovation.java +++ b/Mage.Sets/src/mage/sets/kaladesh/EraOfInnovation.java @@ -45,6 +45,7 @@ import mage.constants.Zone; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.mageobject.SubtypePredicate; /** * @@ -56,7 +57,7 @@ public class EraOfInnovation extends CardImpl { static { filter.add(Predicates.or(new CardTypePredicate(CardType.ARTIFACT), - new CardTypePredicate(CardType.CREATURE))); + new SubtypePredicate("Artificer"))); } public EraOfInnovation(UUID ownerId) { @@ -66,7 +67,7 @@ public class EraOfInnovation extends CardImpl { // Whenever an artifact or creature enters the battlefield under you control, you may pay {1}. If you do, you get {E}{E}. Effect effect = new DoIfCostPaid(new GetEnergyCountersControllerEffect(2), new GenericManaCost(1)); this.addAbility(new EntersBattlefieldAllTriggeredAbility(effect, filter, - "Whenever an artifact or creature enters the battlefield under you control, you may pay {1}. If you do, you get {E}{E}.")); + "Whenever an artifact or Artificer enters the battlefield under you control, you may pay {1}. If you do, you get {E}{E}.")); // {E}{E}{E}{E}{E}{E}, Sacrifice Era of Innovation: Draw three cards. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(3), new PayEnergyCost(6)); From 85fd7bbea211d59a6483893c5ca7f2089e62db7e Mon Sep 17 00:00:00 2001 From: Max Lebedev Date: Tue, 20 Sep 2016 02:57:59 -0400 Subject: [PATCH 16/50] Prelate now shows the chosen number --- .../mage/sets/conspiracytakethecrown/SanctumPrelate.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Mage.Sets/src/mage/sets/conspiracytakethecrown/SanctumPrelate.java b/Mage.Sets/src/mage/sets/conspiracytakethecrown/SanctumPrelate.java index 3b8ce2490d0..decc2fb635e 100644 --- a/Mage.Sets/src/mage/sets/conspiracytakethecrown/SanctumPrelate.java +++ b/Mage.Sets/src/mage/sets/conspiracytakethecrown/SanctumPrelate.java @@ -43,6 +43,7 @@ import mage.choices.ChoiceImpl; import mage.constants.*; import mage.game.Game; import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; import mage.game.stack.Spell; import mage.players.Player; import org.apache.log4j.Logger; @@ -95,6 +96,12 @@ class ChooseNumberEffect extends OneShotEffect { int numberChoice = controller.announceXMana(0, Integer.MAX_VALUE, "Choose a number. Noncreature spells with the chosen converted mana cost can't be cast", game, source); game.getState().setValue(source.getSourceId().toString(), numberChoice); + + Permanent permanent = game.getPermanentEntering(source.getSourceId()); + permanent.addInfo("chosen players", "Chosen Number: "+ numberChoice +"", game); + + game.informPlayers(permanent.getLogName() + ", chosen number: "+numberChoice); + return true; } From 781fff2169b135588c5d4d39c06903a9b9c748b7 Mon Sep 17 00:00:00 2001 From: Max Lebedev Date: Tue, 20 Sep 2016 04:45:16 -0400 Subject: [PATCH 17/50] Added Psychotic Episode --- .../sets/timespiral/PsychoticEpisode.java | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/timespiral/PsychoticEpisode.java diff --git a/Mage.Sets/src/mage/sets/timespiral/PsychoticEpisode.java b/Mage.Sets/src/mage/sets/timespiral/PsychoticEpisode.java new file mode 100644 index 00000000000..7be31993cbd --- /dev/null +++ b/Mage.Sets/src/mage/sets/timespiral/PsychoticEpisode.java @@ -0,0 +1,120 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.timespiral; + +import java.util.UUID; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.MadnessAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.TargetPlayer; + +/** + * + * @author anonymous + */ +public class PsychoticEpisode extends CardImpl { + + public PsychoticEpisode(UUID ownerId) { + super(ownerId, 126, "Psychotic Episode", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{1}{B}{B}"); + this.expansionSetCode = "TSP"; + + // Target player reveals his or her hand and the top card of his or her library. You choose a card revealed this way. That player puts the chosen card on the bottom of his or her library. + this.getSpellAbility().addEffect(new PsychoticEpisodeEffect()); + this.getSpellAbility().addTarget(new TargetPlayer()); + // Madness {1}{B} + this.addAbility(new MadnessAbility(this, new ManaCostsImpl("{1}{B}"))); + } + + public PsychoticEpisode(final PsychoticEpisode card) { + super(card); + } + + @Override + public PsychoticEpisode copy() { + return new PsychoticEpisode(this); + } +} + + +class PsychoticEpisodeEffect extends OneShotEffect { + + PsychoticEpisodeEffect() { + super(Outcome.Discard); + staticText = "Target player reveals his or her hand and the top card of his or her library. You choose a card revealed this way. That player puts the chosen card on the bottom of his or her library."; + } + + PsychoticEpisodeEffect(final PsychoticEpisodeEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(targetPointer.getFirst(game, source)); + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = source.getSourceObject(game); + if (player != null && controller != null && sourceObject != null) { + TargetCard targetCard = new TargetCard(Zone.ALL, new FilterCard()); + targetCard.setRequired(true); + Cards options = player.getHand().copy(); + Card topdeck = player.getLibrary().getFromTop(game); + options.add(topdeck); + controller.lookAtCards("Top of Library (Psychotic Episode)", topdeck, game); + if (controller.choose(Outcome.Discard, options, targetCard, game)) { + Card card = game.getCard(targetCard.getFirstTarget()); + if (card != null) { + CardsImpl cards = new CardsImpl(); + cards.add(card); + player.revealCards(sourceObject.getIdName(), cards, game); + player.putCardsOnBottomOfLibrary(cards, game, source, true); + } + } + return true; + } + return false; + } + + @Override + public PsychoticEpisodeEffect copy() { + return new PsychoticEpisodeEffect(this); + } +} From 5b35c5e9d5f40efefe9e81a714cda587c54f1366 Mon Sep 17 00:00:00 2001 From: Max Lebedev Date: Tue, 20 Sep 2016 05:42:29 -0400 Subject: [PATCH 18/50] Added Curfew --- Mage.Sets/src/mage/sets/urzassaga/Curfew.java | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/urzassaga/Curfew.java diff --git a/Mage.Sets/src/mage/sets/urzassaga/Curfew.java b/Mage.Sets/src/mage/sets/urzassaga/Curfew.java new file mode 100644 index 00000000000..cffce2b60fd --- /dev/null +++ b/Mage.Sets/src/mage/sets/urzassaga/Curfew.java @@ -0,0 +1,109 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.urzassaga; + +import java.util.List; +import java.util.UUID; + +import mage.abilities.Ability; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetControlledPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author maxlebedev + */ +public class Curfew extends CardImpl { + + public Curfew(UUID ownerId) { + super(ownerId, 68, "Curfew", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{U}"); + this.expansionSetCode = "USG"; + + // Each player returns a creature he or she controls to its owner's hand. + this.getSpellAbility().addEffect(new CurfewEffect()); + } + + public Curfew(final Curfew card) { + super(card); + } + + @Override + public Curfew copy() { + return new Curfew(this); + } +} + +class CurfewEffect extends OneShotEffect{ + + public CurfewEffect() { + super(Outcome.ReturnToHand); + staticText = "Each player returns a creature he or she controls to its owner's hand instead"; + } + + @Override + public boolean apply(Game game, Ability source) { + game.informPlayers("Each player returns a creature he or she controls to its owner's hand instead"); + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + TargetControlledCreaturePermanent target = new TargetControlledCreaturePermanent(); + List liste = game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), playerId, game); + if(!liste.isEmpty()){ + player.choose(Outcome.ReturnToHand, target, source.getSourceId(), game); + + Permanent permanent = game.getPermanent(target.getFirstTarget()); + if (permanent != null) { + permanent.moveToZone(Zone.HAND, source.getSourceId(), game, false); + } + } + } + } + return true; + } + + + @Override + public Effect copy() { + return new CurfewEffect(); + } +} + From ab352100f1e060566b6f3492b4098d8055dd454b Mon Sep 17 00:00:00 2001 From: emerald000 Date: Tue, 20 Sep 2016 09:34:36 -0400 Subject: [PATCH 19/50] Fixed Panharmonicon triggering for non-permanents. --- .../src/mage/sets/kaladesh/Panharmonicon.java | 11 ++++++++- .../cards/replacement/PanharmoniconTest.java | 24 +++++++++++++++++++ .../mage/abilities/TriggeredAbilities.java | 2 +- .../game/events/NumberOfTriggersEvent.java | 4 ++-- 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/Mage.Sets/src/mage/sets/kaladesh/Panharmonicon.java b/Mage.Sets/src/mage/sets/kaladesh/Panharmonicon.java index 187da675f2a..f25b93db0ab 100644 --- a/Mage.Sets/src/mage/sets/kaladesh/Panharmonicon.java +++ b/Mage.Sets/src/mage/sets/kaladesh/Panharmonicon.java @@ -92,11 +92,20 @@ class PanharmoniconEffect extends ReplacementEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { if (event instanceof NumberOfTriggersEvent) { NumberOfTriggersEvent numberOfTriggersEvent = (NumberOfTriggersEvent) event; + // Only triggers of the controller of Panharmonicon if (source.getControllerId().equals(event.getPlayerId())) { GameEvent sourceEvent = numberOfTriggersEvent.getSourceEvent(); + // Only EtB triggers if (sourceEvent.getType() == EventType.ENTERS_THE_BATTLEFIELD && sourceEvent instanceof EntersTheBattlefieldEvent) { EntersTheBattlefieldEvent entersTheBattlefieldEvent = (EntersTheBattlefieldEvent) sourceEvent; - return entersTheBattlefieldEvent.getTarget().getCardType().contains(CardType.ARTIFACT) || entersTheBattlefieldEvent.getTarget().getCardType().contains(CardType.CREATURE); + // Only for entering artifacts or creatures + if (entersTheBattlefieldEvent.getTarget().getCardType().contains(CardType.ARTIFACT) + || entersTheBattlefieldEvent.getTarget().getCardType().contains(CardType.CREATURE)) { + // Only for triggers of permanents + if (game.getPermanent(numberOfTriggersEvent.getSourceId()) != null) { + return true; + } + } } } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/PanharmoniconTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/PanharmoniconTest.java index d3286978fd1..b22682e1f01 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/PanharmoniconTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/PanharmoniconTest.java @@ -102,4 +102,28 @@ public class PanharmoniconTest extends CardTestPlayerBase { assertLife(playerA, 22); } + + /** + * Check that Panharmonicon doesn't add to non-permanents triggers. + * + */ + @Test + public void testDoesntAddNonPermanentsTriggers() { + // If an artifact or creature entering the battlefield causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time. + addCard(Zone.BATTLEFIELD, playerA, "Panharmonicon"); + // When a Dragon enters the battlefield, you may return Bladewing's Thrall from your graveyard to the battlefield. + addCard(Zone.GRAVEYARD, playerA, "Bladewing's Thrall"); + // A 4/4 vanilla dragon + addCard(Zone.HAND, playerA, "Scion of Ugin"); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 6); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Scion of Ugin"); + setChoice(playerA, "No"); // Return Bladewing's Thrall from your graveyard to the battlefield? + setChoice(playerA, "Yes"); // Should not get run since there is only one trigger. + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertGraveyardCount(playerA, "Bladewing's Thrall", 1); + } } diff --git a/Mage/src/main/java/mage/abilities/TriggeredAbilities.java b/Mage/src/main/java/mage/abilities/TriggeredAbilities.java index e5fd438390d..967b22938e4 100644 --- a/Mage/src/main/java/mage/abilities/TriggeredAbilities.java +++ b/Mage/src/main/java/mage/abilities/TriggeredAbilities.java @@ -125,7 +125,7 @@ public class TriggeredAbilities extends ConcurrentHashMap Date: Tue, 20 Sep 2016 17:12:19 +0200 Subject: [PATCH 20/50] Added Silvergill Douser --- .../mage/sets/lorwyn/SilvergillDouser.java | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/lorwyn/SilvergillDouser.java diff --git a/Mage.Sets/src/mage/sets/lorwyn/SilvergillDouser.java b/Mage.Sets/src/mage/sets/lorwyn/SilvergillDouser.java new file mode 100644 index 00000000000..31f291c3e22 --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/SilvergillDouser.java @@ -0,0 +1,84 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.lorwyn; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author Styxo + */ +public class SilvergillDouser extends CardImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Merfolk and/or Faeries you control"); + + static { + filter.add(Predicates.or(new SubtypePredicate("Merfolk"), new SubtypePredicate("Faerie"))); + } + + public SilvergillDouser(UUID ownerId) { + super(ownerId, 87, "Silvergill Douser", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{U}"); + this.expansionSetCode = "LRW"; + this.subtype.add("Merfolk"); + this.subtype.add("Wizard"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {tap}: Target creature gets -X/-0 until end of turn, where X is the number of Merfolk and/or Faeries you control. + DynamicValue number = new PermanentsOnBattlefieldCount(new FilterControlledCreaturePermanent(filter), -1); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(number, new StaticValue(0), Duration.EndOfTurn, true), new TapSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public SilvergillDouser(final SilvergillDouser card) { + super(card); + } + + @Override + public SilvergillDouser copy() { + return new SilvergillDouser(this); + } +} From 493cf1e3e62527250c5b955521fb468ac6c99aed Mon Sep 17 00:00:00 2001 From: Max Lebedev Date: Tue, 20 Sep 2016 14:57:37 -0400 Subject: [PATCH 21/50] removed an extra word from rules text --- Mage.Sets/src/mage/sets/urzassaga/Curfew.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/urzassaga/Curfew.java b/Mage.Sets/src/mage/sets/urzassaga/Curfew.java index cffce2b60fd..c4d78871216 100644 --- a/Mage.Sets/src/mage/sets/urzassaga/Curfew.java +++ b/Mage.Sets/src/mage/sets/urzassaga/Curfew.java @@ -76,12 +76,12 @@ class CurfewEffect extends OneShotEffect{ public CurfewEffect() { super(Outcome.ReturnToHand); - staticText = "Each player returns a creature he or she controls to its owner's hand instead"; + staticText = "Each player returns a creature he or she controls to its owner's hand"; } @Override public boolean apply(Game game, Ability source) { - game.informPlayers("Each player returns a creature he or she controls to its owner's hand instead"); + game.informPlayers("Each player returns a creature he or she controls to its owner's hand"); for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { Player player = game.getPlayer(playerId); if (player != null) { From c82d6b55663aac106c47b88f53a94c377a5b3374 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 20 Sep 2016 23:40:25 +0200 Subject: [PATCH 22/50] * Fixed some possible null pointer exceptions. --- .../src/mage/player/human/HumanPlayer.java | 11 +- .../java/mage/server/TableController.java | 2 +- .../src/mage/sets/kaladesh/BomatCourier.java | 297 +++++++++--------- .../src/mage/sets/kaladesh/LostLegacy.java | 2 +- .../mage/sets/mercadianmasques/FoodChain.java | 15 +- .../main/java/mage/players/PlayerImpl.java | 4 + 6 files changed, 171 insertions(+), 160 deletions(-) diff --git a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java index 7d619864c53..4b8bb57eece 100644 --- a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java @@ -730,11 +730,14 @@ public class HumanPlayer extends PlayerImpl { } private boolean checkPassStep(Game game) { - if (playerId.equals(game.getActivePlayerId())) { - return !this.getUserData().getUserSkipPrioritySteps().getYourTurn().isPhaseStepSet(game.getStep().getType()); - } else { - return !this.getUserData().getUserSkipPrioritySteps().getOpponentTurn().isPhaseStepSet(game.getStep().getType()); + if (game.getStep() != null) { + if (playerId.equals(game.getActivePlayerId())) { + return !this.getUserData().getUserSkipPrioritySteps().getYourTurn().isPhaseStepSet(game.getStep().getType()); + } else { + return !this.getUserData().getUserSkipPrioritySteps().getOpponentTurn().isPhaseStepSet(game.getStep().getType()); + } } + return true; } @Override diff --git a/Mage.Server/src/main/java/mage/server/TableController.java b/Mage.Server/src/main/java/mage/server/TableController.java index 266ef9164b4..4d99b36126b 100644 --- a/Mage.Server/src/main/java/mage/server/TableController.java +++ b/Mage.Server/src/main/java/mage/server/TableController.java @@ -567,7 +567,7 @@ public class TableController { String creator = null; StringBuilder opponent = new StringBuilder(); for (Entry entry : userPlayerMap.entrySet()) { // no AI players - if (!match.getPlayer(entry.getValue()).hasQuit()) { + if (match.getPlayer(entry.getValue()) != null && !match.getPlayer(entry.getValue()).hasQuit()) { User user = UserManager.getInstance().getUser(entry.getKey()); if (user != null) { user.ccGameStarted(match.getGame().getId(), entry.getValue()); diff --git a/Mage.Sets/src/mage/sets/kaladesh/BomatCourier.java b/Mage.Sets/src/mage/sets/kaladesh/BomatCourier.java index 666b27c01c6..88053bc2356 100644 --- a/Mage.Sets/src/mage/sets/kaladesh/BomatCourier.java +++ b/Mage.Sets/src/mage/sets/kaladesh/BomatCourier.java @@ -1,146 +1,151 @@ -/* - * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of BetaSteward_at_googlemail.com. - */ -package mage.sets.kaladesh; - -import java.util.UUID; -import mage.MageInt; -import mage.MageObject; -import mage.abilities.Ability; -import mage.abilities.common.AttacksTriggeredAbility; -import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.costs.common.DiscardHandCost; -import mage.abilities.costs.common.SacrificeSourceCost; -import mage.abilities.costs.mana.ColoredManaCost; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.keyword.HasteAbility; -import mage.cards.Card; -import mage.cards.CardImpl; -import mage.constants.CardType; -import mage.constants.ColoredManaSymbol; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.Zone; -import mage.game.Game; -import mage.players.Player; -import mage.util.CardUtil; - -/** - * - * @author emerald000 - */ -public class BomatCourier extends CardImpl { - - public BomatCourier(UUID ownerId) { - super(ownerId, 199, "Bomat Courier", Rarity.RARE, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{1}"); - this.expansionSetCode = "KLD"; - this.subtype.add("Construct"); - this.power = new MageInt(1); - this.toughness = new MageInt(1); - - // Haste - this.addAbility(HasteAbility.getInstance()); - - // Whenever Bomat Courier attacks, exile the top card of your library face down. - this.addAbility(new AttacksTriggeredAbility(new BomatCourierExileEffect(), false)); - - // {R}, Discard your hand, Sacrifice Bomat Courier: Put all cards exiled with Bomat Courier into their owners' hands. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BomatCourierReturnEffect(), new ColoredManaCost(ColoredManaSymbol.R)); - ability.addCost(new DiscardHandCost()); - ability.addCost(new SacrificeSourceCost()); - this.addAbility(ability); - } - - public BomatCourier(final BomatCourier card) { - super(card); - } - - @Override - public BomatCourier copy() { - return new BomatCourier(this); - } -} - -class BomatCourierExileEffect extends OneShotEffect { - - BomatCourierExileEffect() { - super(Outcome.Exile); - this.staticText = "exile the top card of your library face down"; - } - - BomatCourierExileEffect(final BomatCourierExileEffect effect) { - super(effect); - } - - @Override - public BomatCourierExileEffect copy() { - return new BomatCourierExileEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - MageObject sourceObject = source.getSourceObject(game); - if (controller != null && sourceObject != null) { - Card card = controller.getLibrary().getFromTop(game); - if (card != null) { - UUID exileZoneId = CardUtil.getCardExileZoneId(game, source); - card.setFaceDown(true, game); - controller.moveCardsToExile(card, source, game, false, exileZoneId, sourceObject.getIdName()); - card.setFaceDown(true, game); - return true; - } - } - return false; - } -} - -class BomatCourierReturnEffect extends OneShotEffect { - - BomatCourierReturnEffect() { - super(Outcome.DrawCard); - this.staticText = "Put all cards exiled with {this} into their owners' hands"; - } - - BomatCourierReturnEffect(final BomatCourierReturnEffect effect) { - super(effect); - } - - @Override - public BomatCourierReturnEffect copy() { - return new BomatCourierReturnEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - return controller.moveCards(game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source.getSourceId(), true)), Zone.HAND, source, game); - } - return false; - } -} +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.DiscardHandCost; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.mana.ColoredManaCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.HasteAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.ColoredManaSymbol; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.ExileZone; +import mage.game.Game; +import mage.players.Player; +import mage.util.CardUtil; + +/** + * + * @author emerald000 + */ +public class BomatCourier extends CardImpl { + + public BomatCourier(UUID ownerId) { + super(ownerId, 199, "Bomat Courier", Rarity.RARE, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{1}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Construct"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // Whenever Bomat Courier attacks, exile the top card of your library face down. + this.addAbility(new AttacksTriggeredAbility(new BomatCourierExileEffect(), false)); + + // {R}, Discard your hand, Sacrifice Bomat Courier: Put all cards exiled with Bomat Courier into their owners' hands. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BomatCourierReturnEffect(), new ColoredManaCost(ColoredManaSymbol.R)); + ability.addCost(new DiscardHandCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + public BomatCourier(final BomatCourier card) { + super(card); + } + + @Override + public BomatCourier copy() { + return new BomatCourier(this); + } +} + +class BomatCourierExileEffect extends OneShotEffect { + + BomatCourierExileEffect() { + super(Outcome.Exile); + this.staticText = "exile the top card of your library face down"; + } + + BomatCourierExileEffect(final BomatCourierExileEffect effect) { + super(effect); + } + + @Override + public BomatCourierExileEffect copy() { + return new BomatCourierExileEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = source.getSourceObject(game); + if (controller != null && sourceObject != null) { + Card card = controller.getLibrary().getFromTop(game); + if (card != null) { + UUID exileZoneId = CardUtil.getCardExileZoneId(game, source); + card.setFaceDown(true, game); + controller.moveCardsToExile(card, source, game, false, exileZoneId, sourceObject.getIdName()); + card.setFaceDown(true, game); + return true; + } + } + return false; + } +} + +class BomatCourierReturnEffect extends OneShotEffect { + + BomatCourierReturnEffect() { + super(Outcome.DrawCard); + this.staticText = "Put all cards exiled with {this} into their owners' hands"; + } + + BomatCourierReturnEffect(final BomatCourierReturnEffect effect) { + super(effect); + } + + @Override + public BomatCourierReturnEffect copy() { + return new BomatCourierReturnEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + ExileZone exileZone = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source.getSourceId(), true)); + if (exileZone != null) { + controller.moveCards(exileZone, Zone.HAND, source, game); + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/LostLegacy.java b/Mage.Sets/src/mage/sets/kaladesh/LostLegacy.java index eca25bd5efb..7451db1da1f 100644 --- a/Mage.Sets/src/mage/sets/kaladesh/LostLegacy.java +++ b/Mage.Sets/src/mage/sets/kaladesh/LostLegacy.java @@ -81,7 +81,7 @@ class LostLegacyEffect extends SearchTargetGraveyardHandLibraryForCardNameAndExi public boolean apply(Game game, Ability source) { String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY); Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source)); - if (targetPlayer != null) { + if (targetPlayer != null && cardName != null && !cardName.isEmpty()) { FilterCard filter = new FilterCard(); filter.add(new NamePredicate(cardName)); int cardsInHandBefore = targetPlayer.getHand().count(filter, game); diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/FoodChain.java b/Mage.Sets/src/mage/sets/mercadianmasques/FoodChain.java index 0610159baf4..bef652272cf 100644 --- a/Mage.Sets/src/mage/sets/mercadianmasques/FoodChain.java +++ b/Mage.Sets/src/mage/sets/mercadianmasques/FoodChain.java @@ -118,20 +118,19 @@ class FoodChainManaEffect extends ManaEffect { ChoiceColor choice = new ChoiceColor(); controller.choose(Outcome.PutManaInPool, choice, game); ObjectColor chosenColor = choice.getColor(); + if (chosenColor == null) { + return false; + } Mana mana = null; if (chosenColor.isBlack()) { mana = new FoodChainManaBuilder().setMana(Mana.BlackMana(manaCostExiled + 1), source, game).build(); - } - else if (chosenColor.isBlue()) { + } else if (chosenColor.isBlue()) { mana = new FoodChainManaBuilder().setMana(Mana.BlueMana(manaCostExiled + 1), source, game).build(); - } - else if (chosenColor.isRed()) { + } else if (chosenColor.isRed()) { mana = new FoodChainManaBuilder().setMana(Mana.RedMana(manaCostExiled + 1), source, game).build(); - } - else if (chosenColor.isGreen()) { + } else if (chosenColor.isGreen()) { mana = new FoodChainManaBuilder().setMana(Mana.GreenMana(manaCostExiled + 1), source, game).build(); - } - else if (chosenColor.isWhite()) { + } else if (chosenColor.isWhite()) { mana = new FoodChainManaBuilder().setMana(Mana.WhiteMana(manaCostExiled + 1), source, game).build(); } if (mana != null) { diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index a0ea1227c58..fe4f3b692c1 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -996,6 +996,10 @@ public abstract class PlayerImpl implements Player, Serializable { Zone fromZone = game.getState().getZone(card.getMainCard().getId()); card.cast(game, fromZone, ability, playerId); Spell spell = game.getStack().getSpell(ability.getId()); + if (spell == null) { + logger.error("Got no spell from stack. ability: " + ability.getRule()); + return false; + } // some effects set sourceId to cast without paying mana costs or other costs if (ability.getSourceId().equals(getCastSourceIdWithAlternateMana())) { Ability spellAbility = spell.getSpellAbility(); From 3e7479317c72f4cdc815cc0291dd38cab6c1aba0 Mon Sep 17 00:00:00 2001 From: spjspj Date: Thu, 22 Sep 2016 01:03:12 +1000 Subject: [PATCH 23/50] spjspj - Tooltip text for Reconnaissance (EXO) --- Mage.Sets/src/mage/sets/exodus/Reconnaissance.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/exodus/Reconnaissance.java b/Mage.Sets/src/mage/sets/exodus/Reconnaissance.java index 13e4d174b92..ff2883d0cf6 100644 --- a/Mage.Sets/src/mage/sets/exodus/Reconnaissance.java +++ b/Mage.Sets/src/mage/sets/exodus/Reconnaissance.java @@ -80,7 +80,7 @@ class ReconnaissanceRemoveFromCombatEffect extends OneShotEffect { public ReconnaissanceRemoveFromCombatEffect() { super(Outcome.Benefit); - this.staticText = "Remove target attacking creature from combat and untap it"; + this.staticText = "Remove target attacking creature you control from combat and untap it"; } public ReconnaissanceRemoveFromCombatEffect(final ReconnaissanceRemoveFromCombatEffect effect) { From e72393c16d27062913cbe0477cf377efdbe51da5 Mon Sep 17 00:00:00 2001 From: Adam Ginsburg Date: Mon, 19 Sep 2016 22:55:11 -0600 Subject: [PATCH 24/50] Add text to Subtle Strike's modes to clarify which creature is getting + and which is getting - (followed by a few minor squashed commits) Maybe java fixes? semicolons change case --- Mage.Sets/src/mage/sets/kaladesh/SubtleStrike.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/kaladesh/SubtleStrike.java b/Mage.Sets/src/mage/sets/kaladesh/SubtleStrike.java index 746681c62e9..5cd57faff4a 100644 --- a/Mage.Sets/src/mage/sets/kaladesh/SubtleStrike.java +++ b/Mage.Sets/src/mage/sets/kaladesh/SubtleStrike.java @@ -52,11 +52,15 @@ public class SubtleStrike extends CardImpl { this.getSpellAbility().getModes().setMinModes(1); this.getSpellAbility().getModes().setMaxModes(2); // • Target creature gets -1/-1 until end of turn. - this.getSpellAbility().addEffect(new BoostTargetEffect(-1, -1, Duration.EndOfTurn)); + BoostTargetEffect minusOneMinusOne = new BoostTargetEffect(-1, -1, Duration.EndOfTurn); + minusOneMinusOne.setText("Target creature gets -1/-1 until end of turn"); + this.getSpellAbility().addEffect(minusOneMinusOne); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); // • Put a +1/+1 counter on target creature. Mode mode1 = new Mode(); - mode1.getEffects().add(new AddCountersTargetEffect(CounterType.P1P1.createInstance())); + AddCountersTargetEffect plusOnePlusOneCounter = new AddCountersTargetEffect(CounterType.P1P1.createInstance()); + plusOnePlusOneCounter.setText("Put a +1/+1 counter on target creature"); + mode1.getEffects().add(plusOnePlusOneCounter); mode1.getTargets().add(new TargetCreaturePermanent()); this.getSpellAbility().addMode(mode1); From babeb5418c0a112e7d4f8a841bc0f6d9ed12c192 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 21 Sep 2016 19:34:29 +0200 Subject: [PATCH 25/50] * Lightmine Field - Fixed that the damge done was not preventable. --- Mage.Sets/src/mage/sets/riseoftheeldrazi/LightmineField.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/LightmineField.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/LightmineField.java index 62111bf7669..0e38b02badf 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/LightmineField.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/LightmineField.java @@ -52,7 +52,6 @@ public class LightmineField extends CardImpl { super(ownerId, 32, "Lightmine Field", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}"); this.expansionSetCode = "ROE"; - // Whenever one or more creatures attack, Lightmine Field deals damage to each of those creatures equal to the number of attacking creatures. this.addAbility(new LightmineFieldTriggeredAbility()); } @@ -122,7 +121,7 @@ class LightmineFieldEffect extends OneShotEffect { for (UUID attacker : attackers) { Permanent creature = game.getPermanent(attacker); if (creature != null) { - creature.damage(damage, source.getSourceId(), game, false, false); + creature.damage(damage, source.getSourceId(), game, false, true); } } return true; From 23e24f32baf348bdedc7855266fbd2ebd627fc31 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 21 Sep 2016 19:36:01 +0200 Subject: [PATCH 26/50] * Myojin of Life's Web - Fixed the put from hand to battlefield effect. --- .../championsofkamigawa/MyojinOfLifesWeb.java | 56 ++++++++++++++----- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/MyojinOfLifesWeb.java b/Mage.Sets/src/mage/sets/championsofkamigawa/MyojinOfLifesWeb.java index 1bae38bda5e..a05533cee27 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/MyojinOfLifesWeb.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/MyojinOfLifesWeb.java @@ -28,8 +28,6 @@ package mage.sets.championsofkamigawa; import java.util.UUID; - -import mage.constants.*; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; @@ -40,15 +38,17 @@ import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.common.RemoveCountersSourceCost; import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.decorator.ConditionalOneShotEffect; -import mage.abilities.effects.common.PutOntoBattlefieldTargetEffect; +import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.IndestructibleAbility; import mage.cards.CardImpl; +import mage.cards.CardsImpl; +import mage.constants.*; import mage.counters.CounterType; -import mage.filter.FilterCard; -import mage.filter.predicate.mageobject.CardTypePredicate; -import mage.filter.predicate.other.OwnerPredicate; +import mage.filter.common.FilterCreatureCard; +import mage.game.Game; +import mage.players.Player; import mage.target.common.TargetCardInHand; import mage.watchers.common.CastFromHandWatcher; @@ -57,12 +57,6 @@ import mage.watchers.common.CastFromHandWatcher; */ public class MyojinOfLifesWeb extends CardImpl { - private static final FilterCard filter = new FilterCard("any number of creature cards from your hand"); - static { - filter.add(new CardTypePredicate(CardType.CREATURE)); - filter.add(new OwnerPredicate(TargetController.YOU)); - } - public MyojinOfLifesWeb(UUID ownerId) { super(ownerId, 229, "Myojin of Life's Web", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{6}{G}{G}{G}"); this.expansionSetCode = "CHK"; @@ -79,10 +73,10 @@ public class MyojinOfLifesWeb extends CardImpl { // Myojin of Life's Web is indestructible as long as it has a divinity counter on it. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield), - new SourceHasCounterCondition(CounterType.DIVINITY), "{this} is indestructible as long as it has a divinity counter on it"))); + new SourceHasCounterCondition(CounterType.DIVINITY), "{this} is indestructible as long as it has a divinity counter on it"))); // Remove a divinity counter from Myojin of Life's Web: Put any number of creature cards from your hand onto the battlefield. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PutOntoBattlefieldTargetEffect(false), new RemoveCountersSourceCost(CounterType.DIVINITY.createInstance())); - ability.addTarget(new TargetCardInHand(0, Integer.MAX_VALUE, filter)); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MyojinOfLifesWebPutCreatureOnBattlefieldEffect(), new RemoveCountersSourceCost(CounterType.DIVINITY.createInstance())); + this.addAbility(ability); } @@ -95,3 +89,35 @@ public class MyojinOfLifesWeb extends CardImpl { return new MyojinOfLifesWeb(this); } } + +class MyojinOfLifesWebPutCreatureOnBattlefieldEffect extends OneShotEffect { + + public MyojinOfLifesWebPutCreatureOnBattlefieldEffect() { + super(Outcome.PutCreatureInPlay); + this.staticText = "Put any number of creature cards from your hand onto the battlefield"; + } + + public MyojinOfLifesWebPutCreatureOnBattlefieldEffect(final MyojinOfLifesWebPutCreatureOnBattlefieldEffect effect) { + super(effect); + } + + @Override + public MyojinOfLifesWebPutCreatureOnBattlefieldEffect copy() { + return new MyojinOfLifesWebPutCreatureOnBattlefieldEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + + TargetCardInHand target = new TargetCardInHand(0, Integer.MAX_VALUE, new FilterCreatureCard("creature cards from your hand to put onto the battlefield")); + if (controller.choose(Outcome.PutCreatureInPlay, target, source.getSourceId(), game)) { + return controller.moveCards(new CardsImpl(target.getTargets()).getCards(game), + Zone.BATTLEFIELD, source, game, false, false, false, null); + } + return false; + } +} From 6b431be2ba6f2fd04c67d4fca400f50624423739 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 21 Sep 2016 20:16:27 +0200 Subject: [PATCH 27/50] * Shaman of the Great Hunt - Fixed that it triggerd also for other players. --- .../src/mage/sets/legions/BroodSliver.java | 42 ++++++++++++++++--- .../test/cards/triggers/BroodSliverTest.java | 11 +++-- ...alsDamageToAPlayerAllTriggeredAbility.java | 5 +-- 3 files changed, 43 insertions(+), 15 deletions(-) diff --git a/Mage.Sets/src/mage/sets/legions/BroodSliver.java b/Mage.Sets/src/mage/sets/legions/BroodSliver.java index 86ea9e7ec7b..0367dcdcba8 100644 --- a/Mage.Sets/src/mage/sets/legions/BroodSliver.java +++ b/Mage.Sets/src/mage/sets/legions/BroodSliver.java @@ -29,15 +29,18 @@ package mage.sets.legions; import java.util.UUID; import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.CreateTokenTargetEffect; +import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.constants.CardType; +import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.SetTargetPointer; import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; import mage.game.permanent.token.SliverToken; +import mage.players.Player; /** * @@ -54,10 +57,8 @@ public class BroodSliver extends CardImpl { this.toughness = new MageInt(3); // Whenever a Sliver deals combat damage to a player, its controller may put a 1/1 colorless Sliver creature token onto the battlefield. - Effect effect = new CreateTokenTargetEffect(new SliverToken()); - effect.setText("its controller may put a 1/1 colorless Sliver creature token onto the battlefield"); - this.addAbility(new DealsDamageToAPlayerAllTriggeredAbility(effect, - new FilterCreaturePermanent("Sliver", "a Sliver"), true, SetTargetPointer.PLAYER, true)); + this.addAbility(new DealsDamageToAPlayerAllTriggeredAbility(new BroodSliverEffect(), + new FilterCreaturePermanent("Sliver", "a Sliver"), false, SetTargetPointer.PLAYER, true)); } public BroodSliver(final BroodSliver card) { @@ -69,3 +70,32 @@ public class BroodSliver extends CardImpl { return new BroodSliver(this); } } + +class BroodSliverEffect extends OneShotEffect { + + public BroodSliverEffect() { + super(Outcome.PutCardInPlay); + this.staticText = "its controller may put a 1/1 colorless Sliver creature token onto the battlefield"; + } + + public BroodSliverEffect(final BroodSliverEffect effect) { + super(effect); + } + + @Override + public BroodSliverEffect copy() { + return new BroodSliverEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player permanentController = game.getPlayer(getTargetPointer().getFirst(game, source)); + if (permanentController != null) { + if (permanentController.chooseUse(outcome, "put a 1/1 colorless Sliver creature token onto the battlefield", source, game)) { + return new SliverToken().putOntoBattlefield(1, game, source.getSourceId(), permanentController.getId()); + } + return true; + } + return false; + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/BroodSliverTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/BroodSliverTest.java index 99b54a2f340..92fb807605b 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/BroodSliverTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/BroodSliverTest.java @@ -15,24 +15,23 @@ import org.mage.test.serverside.base.CardTestPlayerBase; * @author escplan9 (Derek Monturo - dmontur1 at gmail dot com) */ public class BroodSliverTest extends CardTestPlayerBase { - + /* Reported bug: It lets the controller of Brood Sliver choose whether or not the token is created, instead of the attacking Sliver's controller. - */ + */ @Test public void testTokenCreatedBySliverController() { - + // Brood Sliver {4}{G} 3/3 Sliver // Whenever a Sliver deals combat damage to a player, its controller may put a 1/1 colorless Sliver creature token onto the battlefield. addCard(Zone.BATTLEFIELD, playerB, "Brood Sliver"); addCard(Zone.BATTLEFIELD, playerA, "Venom Sliver"); // 1/1 deathtouch granting sliver - + attack(1, playerA, "Venom Sliver"); setChoice(playerA, "Yes"); // controller of Venom Sliver dealing damage should get the choice to create token - setChoice(playerB, "No"); // Brood Sliver controller should not be given choice in the first place setStopAt(1, PhaseStep.END_COMBAT); execute(); - + assertLife(playerB, 19); assertPermanentCount(playerA, "Sliver", 1); assertPermanentCount(playerB, "Sliver", 0); diff --git a/Mage/src/main/java/mage/abilities/common/DealsDamageToAPlayerAllTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/DealsDamageToAPlayerAllTriggeredAbility.java index 1b15255bb9d..2f896f5979a 100644 --- a/Mage/src/main/java/mage/abilities/common/DealsDamageToAPlayerAllTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/DealsDamageToAPlayerAllTriggeredAbility.java @@ -73,12 +73,11 @@ public class DealsDamageToAPlayerAllTriggeredAbility extends TriggeredAbilityImp } @Override - public boolean checkTrigger(GameEvent event, Game game) { + public boolean checkTrigger(GameEvent event, Game game) { if (!onlyCombat || ((DamagedPlayerEvent) event).isCombatDamage()) { Permanent permanent = game.getPermanent(event.getSourceId()); if (permanent != null) { - controllerId = permanent.getControllerId(); - if (filter.match(permanent, sourceId, controllerId, game)) { + if (filter.match(permanent, getSourceId(), getControllerId(), game)) { if (!setTargetPointer.equals(SetTargetPointer.NONE)) { for (Effect effect : this.getEffects()) { effect.setValue("damage", event.getAmount()); From 935a51c4da094dccd6f777e6433427cb995cf4ef Mon Sep 17 00:00:00 2001 From: Styxo Date: Wed, 21 Sep 2016 21:05:37 +0200 Subject: [PATCH 28/50] Fixed Crew Ability --- Mage/src/main/java/mage/abilities/keyword/CrewAbility.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java b/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java index dc48b5baaa1..a17d5ad6e74 100644 --- a/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java @@ -122,7 +122,10 @@ class CrewCost extends CostImpl { public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { int sumPower = 0; for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, controllerId, game)) { - sumPower += permanent.getPower().getValue(); + int powerToAdd = permanent.getPower().getValue(); + if (powerToAdd > 0) { + sumPower += powerToAdd; + } if (sumPower >= value) { return true; } From f428d5533f772bd6cba732af20d021e4ac7b7f09 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 21 Sep 2016 22:42:09 +0200 Subject: [PATCH 29/50] * Selvala, Heart of the Wilds - FIxed tool tip text. --- .../SelvalaHeartOfTheWilds.java | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/Mage.Sets/src/mage/sets/conspiracytakethecrown/SelvalaHeartOfTheWilds.java b/Mage.Sets/src/mage/sets/conspiracytakethecrown/SelvalaHeartOfTheWilds.java index d092cf4b3e7..e8aa7854548 100644 --- a/Mage.Sets/src/mage/sets/conspiracytakethecrown/SelvalaHeartOfTheWilds.java +++ b/Mage.Sets/src/mage/sets/conspiracytakethecrown/SelvalaHeartOfTheWilds.java @@ -39,7 +39,6 @@ import mage.abilities.effects.OneShotEffect; import mage.abilities.mana.DynamicManaAbility; import mage.cards.CardImpl; import mage.constants.*; -import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.ObjectSourcePlayer; @@ -48,7 +47,6 @@ import mage.filter.predicate.permanent.AnotherPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.targetpointer.FixedTarget; /** * @@ -56,8 +54,8 @@ import mage.target.targetpointer.FixedTarget; */ public class SelvalaHeartOfTheWilds extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); + static { filter.add(new AnotherPredicate()); filter.add(new GreatestPowerPredicate()); @@ -75,12 +73,11 @@ public class SelvalaHeartOfTheWilds extends CardImpl { this.toughness = new MageInt(3); // Whenever another creature enters the battlefield, its controller may draw a card if its power is greater than each other creature's power. - this.addAbility(new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new SelvalaHeartOfTheWildsEffect(), filter, false, SetTargetPointer.PERMANENT, rule)); // {G}, {T}: Add X mana in any combination of colors to your mana pool, where X is the greatest power among creatures you control. - this.addAbility(new DynamicManaAbility(new Mana(0,0,0,0,0,0,1, 0), new GreatestPowerYouControlValue(), new TapSourceCost(), - "Add X mana in any combination of colors to your mana pool, where X is the number of creatures with defender you control.")); + this.addAbility(new DynamicManaAbility(new Mana(0, 0, 0, 0, 0, 0, 1, 0), new GreatestPowerYouControlValue(), new TapSourceCost(), + "Add X mana in any combination of colors to your mana pool, where X is the greatest power among creatures you control.")); } public SelvalaHeartOfTheWilds(final SelvalaHeartOfTheWilds card) { @@ -112,12 +109,12 @@ class SelvalaHeartOfTheWildsEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(targetPointer.getFirst(game, source)); - if(permanent == null){ - permanent = (Permanent)game.getLastKnownInformation(targetPointer.getFirst(game, source), Zone.BATTLEFIELD); + if (permanent == null) { + permanent = (Permanent) game.getLastKnownInformation(targetPointer.getFirst(game, source), Zone.BATTLEFIELD); } if (permanent != null) { Player cardowner = game.getPlayer(permanent.getControllerId()); - if(cardowner.chooseUse(Outcome.DrawCard, "Would you like to draw a card?", source, game)){ + if (cardowner.chooseUse(Outcome.DrawCard, "Would you like to draw a card?", source, game)) { cardowner.drawCards(1, game); } } @@ -125,18 +122,17 @@ class SelvalaHeartOfTheWildsEffect extends OneShotEffect { } } - class GreatestPowerPredicate implements ObjectSourcePlayerPredicate> { @Override public boolean apply(ObjectSourcePlayer input, Game game) { int pow = input.getObject().getPower().getValue(); - for (UUID id :game.getPlayerList()){ + for (UUID id : game.getPlayerList()) { Player player = game.getPlayer(id); if (player != null) { for (Permanent p : game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), id, game)) { - if(p.getPower().getValue() >= pow && !p.equals(input.getObject())){ + if (p.getPower().getValue() >= pow && !p.equals(input.getObject())) { return false; //we found something with equal/more power } } @@ -144,6 +140,7 @@ class GreatestPowerPredicate implements ObjectSourcePlayerPredicate Date: Wed, 21 Sep 2016 22:50:41 +0200 Subject: [PATCH 30/50] * Sequestered Stash - Fixed that the return to library effect was wrongly targeted. --- .../mage/sets/kaladesh/SequesteredStash.java | 48 ++++++++++++++++--- 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/Mage.Sets/src/mage/sets/kaladesh/SequesteredStash.java b/Mage.Sets/src/mage/sets/kaladesh/SequesteredStash.java index 24d0e111b52..89080e4e5cc 100644 --- a/Mage.Sets/src/mage/sets/kaladesh/SequesteredStash.java +++ b/Mage.Sets/src/mage/sets/kaladesh/SequesteredStash.java @@ -33,15 +33,18 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.PutOnLibraryTargetEffect; +import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveControllerEffect; import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.Card; import mage.cards.CardImpl; import mage.constants.CardType; +import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; import mage.filter.common.FilterArtifactCard; +import mage.game.Game; +import mage.players.Player; import mage.target.common.TargetCardInYourGraveyard; /** @@ -61,10 +64,7 @@ public class SequesteredStash extends CardImpl { Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PutTopCardOfLibraryIntoGraveControllerEffect(5), new GenericManaCost(4)); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); - Effect effect = new PutOnLibraryTargetEffect(true); - effect.setText("Then you may put an artifact card from your graveyard on top of your library"); - ability.addEffect(effect); - ability.addTarget(new TargetCardInYourGraveyard(new FilterArtifactCard("artifact card from your graveyard"))); + ability.addEffect(new SequesteredStashEffect()); this.addAbility(ability); } @@ -78,3 +78,39 @@ public class SequesteredStash extends CardImpl { return new SequesteredStash(this); } } + +class SequesteredStashEffect extends OneShotEffect { + + public SequesteredStashEffect() { + super(Outcome.Benefit); + this.staticText = "Then you may put an artifact card from your graveyard on top of your library"; + } + + public SequesteredStashEffect(final SequesteredStashEffect effect) { + super(effect); + } + + @Override + public SequesteredStashEffect copy() { + return new SequesteredStashEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(new FilterArtifactCard("artifact card from your graveyard")); + target.setNotTarget(true); + if (target.canChoose(source.getSourceId(), source.getControllerId(), game) + && controller.chooseUse(outcome, "Put an artifact card from your graveyard to library?", source, game) + && controller.choose(outcome, target, source.getSourceId(), game)) { + Card card = game.getCard(target.getFirstTarget()); + if (card != null) { + controller.moveCards(card, Zone.LIBRARY, source, game); + } + } + return true; + } +} From 716377cc327a0e41c8f156bdabc9fdb3ff3f9699 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 21 Sep 2016 22:56:31 +0200 Subject: [PATCH 31/50] * Multiform Wonder - Fixed the nor working boost effect. --- Mage.Sets/src/mage/sets/kaladesh/MultiformWonder.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Mage.Sets/src/mage/sets/kaladesh/MultiformWonder.java b/Mage.Sets/src/mage/sets/kaladesh/MultiformWonder.java index bb955975e05..6ec7d861bbe 100644 --- a/Mage.Sets/src/mage/sets/kaladesh/MultiformWonder.java +++ b/Mage.Sets/src/mage/sets/kaladesh/MultiformWonder.java @@ -187,10 +187,10 @@ class MultiformWonder2Effect extends ContinuousEffectImpl { @Override public boolean apply(Game game, Ability source) { - Permanent target = game.getPermanent(source.getFirstTarget()); - if (target != null) { - target.addPower(power); - target.addToughness(toughness); + Permanent sourceObject = game.getPermanent(source.getSourceId()); + if (sourceObject != null) { + sourceObject.addPower(power); + sourceObject.addToughness(toughness); return true; } return false; From 130554954b62c37047b3a6b9df95de1702a60d5d Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 21 Sep 2016 23:00:52 +0200 Subject: [PATCH 32/50] * Selvala, Heart of the Wilds - Added the missing {G} cost for the mana ability. --- .../conspiracytakethecrown/SelvalaHeartOfTheWilds.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/conspiracytakethecrown/SelvalaHeartOfTheWilds.java b/Mage.Sets/src/mage/sets/conspiracytakethecrown/SelvalaHeartOfTheWilds.java index e8aa7854548..6aff8f6068c 100644 --- a/Mage.Sets/src/mage/sets/conspiracytakethecrown/SelvalaHeartOfTheWilds.java +++ b/Mage.Sets/src/mage/sets/conspiracytakethecrown/SelvalaHeartOfTheWilds.java @@ -33,6 +33,7 @@ import mage.Mana; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; @@ -76,8 +77,11 @@ public class SelvalaHeartOfTheWilds extends CardImpl { this.addAbility(new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new SelvalaHeartOfTheWildsEffect(), filter, false, SetTargetPointer.PERMANENT, rule)); // {G}, {T}: Add X mana in any combination of colors to your mana pool, where X is the greatest power among creatures you control. - this.addAbility(new DynamicManaAbility(new Mana(0, 0, 0, 0, 0, 0, 1, 0), new GreatestPowerYouControlValue(), new TapSourceCost(), - "Add X mana in any combination of colors to your mana pool, where X is the greatest power among creatures you control.")); + Ability ability = new DynamicManaAbility(new Mana(0, 0, 0, 0, 0, 0, 1, 0), new GreatestPowerYouControlValue(), new ManaCostsImpl<>("{G}"), + "Add X mana in any combination of colors to your mana pool, where X is the greatest power among creatures you control."); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } public SelvalaHeartOfTheWilds(final SelvalaHeartOfTheWilds card) { From d6e19e41144fd4e8803f2234ff0c688b53a7b1a9 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 21 Sep 2016 23:11:36 +0200 Subject: [PATCH 33/50] * Era of Innovation - Fixed wrong tool tip text. --- Mage.Sets/src/mage/sets/kaladesh/EraOfInnovation.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/kaladesh/EraOfInnovation.java b/Mage.Sets/src/mage/sets/kaladesh/EraOfInnovation.java index 34774ce5ee2..bcc9ff3ef47 100644 --- a/Mage.Sets/src/mage/sets/kaladesh/EraOfInnovation.java +++ b/Mage.Sets/src/mage/sets/kaladesh/EraOfInnovation.java @@ -53,7 +53,7 @@ import mage.filter.predicate.mageobject.SubtypePredicate; */ public class EraOfInnovation extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent("an artifact or creature"); + private static final FilterControlledPermanent filter = new FilterControlledPermanent("an artifact or Artificer"); static { filter.add(Predicates.or(new CardTypePredicate(CardType.ARTIFACT), @@ -64,7 +64,7 @@ public class EraOfInnovation extends CardImpl { super(ownerId, 45, "Era of Innovation", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}"); this.expansionSetCode = "KLD"; - // Whenever an artifact or creature enters the battlefield under you control, you may pay {1}. If you do, you get {E}{E}. + // Whenever an artifact or Artificer enters the battlefield under you control, you may pay {1}. If you do, you get {E}{E}. Effect effect = new DoIfCostPaid(new GetEnergyCountersControllerEffect(2), new GenericManaCost(1)); this.addAbility(new EntersBattlefieldAllTriggeredAbility(effect, filter, "Whenever an artifact or Artificer enters the battlefield under you control, you may pay {1}. If you do, you get {E}{E}.")); From 274dbc2dbb56a88f478658350e83603618e1328d Mon Sep 17 00:00:00 2001 From: fireshoes Date: Thu, 22 Sep 2016 10:52:28 -0500 Subject: [PATCH 34/50] Added Legacy Cube Sept 16 to the menu... --- Mage.Server/config/config.xml | 1 + Mage.Server/release/config/config.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/Mage.Server/config/config.xml b/Mage.Server/config/config.xml index 608510af330..74a28df7ac2 100644 --- a/Mage.Server/config/config.xml +++ b/Mage.Server/config/config.xml @@ -102,6 +102,7 @@ + diff --git a/Mage.Server/release/config/config.xml b/Mage.Server/release/config/config.xml index 606359499cf..99c5047d52c 100644 --- a/Mage.Server/release/config/config.xml +++ b/Mage.Server/release/config/config.xml @@ -99,6 +99,7 @@ + From 3870a1e522e26744110fad8e178cfe1f3256fc22 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 22 Sep 2016 20:36:10 +0200 Subject: [PATCH 35/50] * Leovold, Emissary of Trest - Some code cleanup. --- .../LeovoldEmissaryOfTrest.java | 64 +++---------------- 1 file changed, 8 insertions(+), 56 deletions(-) diff --git a/Mage.Sets/src/mage/sets/conspiracytakethecrown/LeovoldEmissaryOfTrest.java b/Mage.Sets/src/mage/sets/conspiracytakethecrown/LeovoldEmissaryOfTrest.java index 7f372c4baf4..179cf7c0b4a 100644 --- a/Mage.Sets/src/mage/sets/conspiracytakethecrown/LeovoldEmissaryOfTrest.java +++ b/Mage.Sets/src/mage/sets/conspiracytakethecrown/LeovoldEmissaryOfTrest.java @@ -27,7 +27,6 @@ */ package mage.sets.conspiracytakethecrown; -import java.util.HashSet; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; @@ -41,8 +40,7 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.watchers.Watcher; - +import mage.watchers.common.CardsAmountDrawnThisTurnWatcher; /** * @@ -60,7 +58,7 @@ public class LeovoldEmissaryOfTrest extends CardImpl { this.toughness = new MageInt(3); // Each opponent can't draw more than one card each turn. (Based on SpiritOfTheLabyrinth) - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new LeovoldEmissaryOfTrestEffect()), new LeovoldEmissaryOfTrestWatcher()); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new LeovoldEmissaryOfTrestEffect()), new CardsAmountDrawnThisTurnWatcher()); // Whenever you or a permanent you control becomes the target of a spell or ability an opponent controls, you may draw a card. this.addAbility(new LeovoldEmissaryOfTrestTriggeredAbility()); @@ -76,47 +74,6 @@ public class LeovoldEmissaryOfTrest extends CardImpl { } } - -class LeovoldEmissaryOfTrestWatcher extends Watcher { - - private final HashSet playersThatDrewCard; - - public LeovoldEmissaryOfTrestWatcher() { - super("DrewCard", WatcherScope.GAME); - this.playersThatDrewCard = new HashSet<>(); - } - - public LeovoldEmissaryOfTrestWatcher(final LeovoldEmissaryOfTrestWatcher watcher) { - super(watcher); - this.playersThatDrewCard = new HashSet<>(); - playersThatDrewCard.addAll(watcher.playersThatDrewCard); - } - - @Override - public LeovoldEmissaryOfTrestWatcher copy() { - return new LeovoldEmissaryOfTrestWatcher(this); - } - - @Override - public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.DREW_CARD ) { - playersThatDrewCard.add(event.getPlayerId()); - - } - } - - @Override - public void reset() { - super.reset(); - playersThatDrewCard.clear(); - } - - public boolean hasPlayerDrewCardThisTurn(UUID playerId) { - return playersThatDrewCard.contains(playerId); - } - -} - class LeovoldEmissaryOfTrestEffect extends ContinuousRuleModifyingEffectImpl { public LeovoldEmissaryOfTrestEffect() { @@ -133,11 +90,6 @@ class LeovoldEmissaryOfTrestEffect extends ContinuousRuleModifyingEffectImpl { return new LeovoldEmissaryOfTrestEffect(this); } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public boolean checksEventType(GameEvent event, Game game) { return event.getType() == GameEvent.EventType.DRAW_CARD; @@ -145,10 +97,9 @@ class LeovoldEmissaryOfTrestEffect extends ContinuousRuleModifyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - LeovoldEmissaryOfTrestWatcher watcher = (LeovoldEmissaryOfTrestWatcher) game.getState().getWatchers().get("DrewCard"); - + CardsAmountDrawnThisTurnWatcher watcher = (CardsAmountDrawnThisTurnWatcher) game.getState().getWatchers().get(CardsAmountDrawnThisTurnWatcher.BASIC_KEY); Player controller = game.getPlayer(source.getControllerId()); - return watcher != null && controller != null && watcher.hasPlayerDrewCardThisTurn(event.getPlayerId()) + return watcher != null && controller != null && watcher.getAmountCardsDrawn(event.getPlayerId()) >= 1 && game.isOpponent(controller, event.getPlayerId()); } @@ -178,9 +129,10 @@ class LeovoldEmissaryOfTrestTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { Player controller = game.getPlayer(this.getControllerId()); Player targetter = game.getPlayer(event.getPlayerId()); - if (controller != null && targetter != null && !controller.getId().equals(targetter.getId())) { + if (controller != null && targetter != null + && game.isOpponent(controller, targetter.getId())) { if (event.getTargetId().equals(controller.getId())) { - return true; + return true; // Player was targeted } Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId()); if (permanent != null && this.getControllerId().equals(permanent.getControllerId())) { @@ -192,6 +144,6 @@ class LeovoldEmissaryOfTrestTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "Whenever you or a permanent you control becomes the target of a spell or ability an opponent controls, you may draw a card."; + return "Whenever you or a permanent you control becomes the target of a spell or ability an opponent controls, " + super.getRule(); } } From 2ca0639f155fd84a6536677736c2e25c1db03f57 Mon Sep 17 00:00:00 2001 From: Clint Herron Date: Thu, 22 Sep 2016 14:37:23 -0400 Subject: [PATCH 36/50] Adding Quilled Sliver by merging Gemhide Sliver with Crossbow Infantry --- .../mage/sets/timespiral/QuilledSliver.java | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/timespiral/QuilledSliver.java diff --git a/Mage.Sets/src/mage/sets/timespiral/QuilledSliver.java b/Mage.Sets/src/mage/sets/timespiral/QuilledSliver.java new file mode 100644 index 00000000000..5408ad84424 --- /dev/null +++ b/Mage.Sets/src/mage/sets/timespiral/QuilledSliver.java @@ -0,0 +1,81 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.timespiral; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.target.common.TargetAttackingOrBlockingCreature; + +/** + * + * @author HanClinto + * + * A relatively straightforward merge between GemhideSliver.java and CrossbowInfantry.java + */ +public class QuilledSliver extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("Sliver", "All Slivers"); + + public QuilledSliver(UUID ownerId) { + super(ownerId, 37, "Quilled Sliver", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{W}"); + this.expansionSetCode = "TSP"; + this.subtype.add("Sliver"); + + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // All Slivers have "{tap}: This permanent deals 1 damage to target attacking or blocking creature." + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new TapSourceCost()); + ability.addTarget(new TargetAttackingOrBlockingCreature()); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, + new GainAbilityAllEffect(ability, + Duration.WhileOnBattlefield, filter, + "All Slivers have \"{T}: This permanent deals 1 damage to target attacking or blocking creature.\""))); + } + + public QuilledSliver(final QuilledSliver card) { + super(card); + } + + @Override + public QuilledSliver copy() { + return new QuilledSliver(this); + } +} \ No newline at end of file From 44f8293c4281b2b44b65b64400703cf251b985d0 Mon Sep 17 00:00:00 2001 From: Clint Herron Date: Thu, 22 Sep 2016 14:39:12 -0400 Subject: [PATCH 37/50] Fixing tabs to spaces --- Mage.Sets/src/mage/sets/timespiral/QuilledSliver.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/timespiral/QuilledSliver.java b/Mage.Sets/src/mage/sets/timespiral/QuilledSliver.java index 5408ad84424..e2383f61e92 100644 --- a/Mage.Sets/src/mage/sets/timespiral/QuilledSliver.java +++ b/Mage.Sets/src/mage/sets/timespiral/QuilledSliver.java @@ -61,8 +61,8 @@ public class QuilledSliver extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - // All Slivers have "{tap}: This permanent deals 1 damage to target attacking or blocking creature." - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new TapSourceCost()); + // All Slivers have "{tap}: This permanent deals 1 damage to target attacking or blocking creature." + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new TapSourceCost()); ability.addTarget(new TargetAttackingOrBlockingCreature()); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(ability, From 3eae5e9a0014d2368a69f56f147b740fb5608b16 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 22 Sep 2016 20:49:12 +0200 Subject: [PATCH 38/50] Fixed a bug of the copy effect that could lead to null pointer exceptions e.g. for Permeating Mass trying to copy meanwhile removed target(fixes #2342). --- .../main/java/mage/abilities/effects/common/CopyEffect.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Mage/src/main/java/mage/abilities/effects/common/CopyEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CopyEffect.java index 7b472f6566a..65f0fcb96de 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CopyEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CopyEffect.java @@ -104,6 +104,10 @@ public class CopyEffect extends ContinuousEffectImpl { @Override public boolean apply(Game game, Ability source) { + if (affectedObjectList.isEmpty()) { + this.discard(); + return false; + } Permanent permanent = affectedObjectList.get(0).getPermanent(game); if (permanent == null) { permanent = (Permanent) game.getLastKnownInformation(getSourceId(), Zone.BATTLEFIELD, source.getSourceObjectZoneChangeCounter()); From 8fb04ddbef655b5763c9bd9a102a6f8278bd8e71 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 22 Sep 2016 21:36:21 +0200 Subject: [PATCH 39/50] Fixed a bug that let cards disappear after moving cards from hand to library (e.g. Teferi's puzzle). --- .../mage/sets/timespiral/QuilledSliver.java | 9 ++--- Mage/src/main/java/mage/cards/CardImpl.java | 36 ++++++++++--------- .../main/java/mage/players/PlayerImpl.java | 5 +-- 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/Mage.Sets/src/mage/sets/timespiral/QuilledSliver.java b/Mage.Sets/src/mage/sets/timespiral/QuilledSliver.java index e2383f61e92..1f382c85aab 100644 --- a/Mage.Sets/src/mage/sets/timespiral/QuilledSliver.java +++ b/Mage.Sets/src/mage/sets/timespiral/QuilledSliver.java @@ -30,11 +30,11 @@ package mage.sets.timespiral; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.common.continuous.GainAbilityAllEffect; import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityAllEffect; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Duration; @@ -47,7 +47,8 @@ import mage.target.common.TargetAttackingOrBlockingCreature; * * @author HanClinto * - * A relatively straightforward merge between GemhideSliver.java and CrossbowInfantry.java + * A relatively straightforward merge between GemhideSliver.java and + * CrossbowInfantry.java */ public class QuilledSliver extends CardImpl { @@ -78,4 +79,4 @@ public class QuilledSliver extends CardImpl { public QuilledSliver copy() { return new QuilledSliver(this); } -} \ No newline at end of file +} diff --git a/Mage/src/main/java/mage/cards/CardImpl.java b/Mage/src/main/java/mage/cards/CardImpl.java index d890e5561dc..8beaabca2b4 100644 --- a/Mage/src/main/java/mage/cards/CardImpl.java +++ b/Mage/src/main/java/mage/cards/CardImpl.java @@ -29,7 +29,6 @@ package mage.cards; import java.lang.reflect.Constructor; import java.util.*; - import mage.MageObject; import mage.MageObjectImpl; import mage.Mana; @@ -53,10 +52,8 @@ import mage.game.command.Commander; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; -import mage.game.permanent.PermanentCard; import mage.game.stack.Spell; import mage.game.stack.StackObject; -import mage.players.Player; import mage.util.GameLog; import mage.watchers.Watcher; import org.apache.log4j.Logger; @@ -315,11 +312,11 @@ public abstract class CardImpl extends MageObjectImpl implements Card { public String getTokenSetCode() { return tokenSetCode; } - + @Override public String getTokenDescriptor() { return tokenDescriptor; - } + } @Override public List getMana() { @@ -342,22 +339,29 @@ public abstract class CardImpl extends MageObjectImpl implements Card { Zone fromZone = game.getState().getZone(objectId); ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, ownerId, fromZone, toZone, appliedEffects); ZoneChangeInfo zoneChangeInfo; - if (toZone == Zone.LIBRARY) { - zoneChangeInfo = new ZoneChangeInfo.Library(event, flag /* put on top */); - } else if (toZone == Zone.BATTLEFIELD) { - zoneChangeInfo = new ZoneChangeInfo.Battlefield(event, flag /* comes into play tapped */); - } else { - zoneChangeInfo = new ZoneChangeInfo(event); + if (null != toZone) { + switch (toZone) { + case LIBRARY: + zoneChangeInfo = new ZoneChangeInfo.Library(event, flag /* put on top */); + break; + case BATTLEFIELD: + zoneChangeInfo = new ZoneChangeInfo.Battlefield(event, flag /* comes into play tapped */); + break; + default: + zoneChangeInfo = new ZoneChangeInfo(event); + break; + } + return ZonesHandler.moveCard(zoneChangeInfo, game); } - return ZonesHandler.moveCard(zoneChangeInfo, game); + return false; } @Override public boolean cast(Game game, Zone fromZone, SpellAbility ability, UUID controllerId) { Card mainCard = getMainCard(); ZoneChangeEvent event = new ZoneChangeEvent(mainCard.getId(), ability.getId(), controllerId, fromZone, Zone.STACK); - ZoneChangeInfo.Stack info = - new ZoneChangeInfo.Stack(event, new Spell(this, ability.copy(), controllerId, event.getFromZone())); + ZoneChangeInfo.Stack info + = new ZoneChangeInfo.Stack(event, new Spell(this, ability.copy(), controllerId, event.getFromZone())); return ZonesHandler.cast(info, game); } @@ -598,7 +602,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card { returnCode = false; } } - if(finalAmount > 0) { + if (finalAmount > 0) { game.fireEvent(GameEvent.getEvent(GameEvent.EventType.COUNTERS_ADDED, objectId, getControllerOrOwner(), counter.getName(), amount)); } } else { @@ -656,7 +660,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card { } return super.getColor(game); } - + @Override public List getSubtype(Game game) { if (game != null) { diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index fe4f3b692c1..6a045a8e48b 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -863,8 +863,9 @@ public abstract class PlayerImpl implements Player, Serializable { } @Override - public boolean putCardsOnBottomOfLibrary(Cards cards, Game game, Ability source, boolean anyOrder) { - if (!cards.isEmpty()) { + public boolean putCardsOnBottomOfLibrary(Cards cardsToLibrary, Game game, Ability source, boolean anyOrder) { + if (!cardsToLibrary.isEmpty()) { + Cards cards = new CardsImpl(cardsToLibrary); // prevent possible ConcurrentModificationException if (!anyOrder) { for (UUID objectId : cards) { moveObjectToLibrary(objectId, source == null ? null : source.getSourceId(), game, false, false); From 4c91440f5e4a441a7298c93f84ed55f7b05638ab Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 22 Sep 2016 21:48:39 +0200 Subject: [PATCH 40/50] Chnaged color frame for active player to green (that white was a no go). --- Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java b/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java index baf41b67ff2..fc494cdbe26 100644 --- a/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java +++ b/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java @@ -110,7 +110,7 @@ public class PlayerPanelExt extends javax.swing.JPanel { private static final int PANEL_HEIGHT_SMALL = 212; private static final int MANA_LABEL_SIZE_HORIZONTAL = 20; - private static final Border GREEN_BORDER = new LineBorder(Color.white, 3); + private static final Border GREEN_BORDER = new LineBorder(Color.green, 3); private static final Border RED_BORDER = new LineBorder(Color.red, 2); private static final Border EMPTY_BORDER = BorderFactory.createEmptyBorder(0, 0, 0, 0); private final Color greenBackgroundColor = new Color(206, 192, 174, 200); From 4ad3ef4e6876410353c10c3828adf74fff476ba3 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 22 Sep 2016 23:08:40 +0200 Subject: [PATCH 41/50] * Fixed a problem with card movement that prevented Tiny Leaders go to command zone at game start. --- Mage/src/main/java/mage/cards/CardImpl.java | 7 ++++++- Mage/src/main/java/mage/game/ZonesHandler.java | 4 +++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Mage/src/main/java/mage/cards/CardImpl.java b/Mage/src/main/java/mage/cards/CardImpl.java index 8beaabca2b4..d4a18701215 100644 --- a/Mage/src/main/java/mage/cards/CardImpl.java +++ b/Mage/src/main/java/mage/cards/CardImpl.java @@ -453,6 +453,9 @@ public abstract class CardImpl extends MageObjectImpl implements Card { } else if (game.getPlayer(ownerId).getSideboard().contains(this.getId())) { game.getPlayer(ownerId).getSideboard().remove(this.getId()); removed = true; + } else if (game.getPhase() == null) { + // E.g. Commander of commander game + removed = true; } break; case BATTLEFIELD: // for sacrificing permanents or putting to library @@ -465,7 +468,9 @@ public abstract class CardImpl extends MageObjectImpl implements Card { break; } if (removed) { - game.rememberLKI(lkiObject != null ? lkiObject.getId() : objectId, fromZone, lkiObject != null ? lkiObject : this); + if (!fromZone.equals(Zone.OUTSIDE)) { + game.rememberLKI(lkiObject != null ? lkiObject.getId() : objectId, fromZone, lkiObject != null ? lkiObject : this); + } } else { logger.warn("Couldn't find card in fromZone, card=" + getIdName() + ", fromZone=" + fromZone); } diff --git a/Mage/src/main/java/mage/game/ZonesHandler.java b/Mage/src/main/java/mage/game/ZonesHandler.java index 6a53736d4a7..a57df07facd 100644 --- a/Mage/src/main/java/mage/game/ZonesHandler.java +++ b/Mage/src/main/java/mage/game/ZonesHandler.java @@ -59,7 +59,9 @@ public class ZonesHandler { } for (ZoneChangeInfo zoneChangeInfo : zoneChangeInfos) { placeInDestinationZone(zoneChangeInfo, game); - game.addSimultaneousEvent(zoneChangeInfo.event); + if (game.getPhase() != null) { // moving cards to zones before game started does not need events + game.addSimultaneousEvent(zoneChangeInfo.event); + } } return zoneChangeInfos; } From 500926f0936e4bbf649090c5b80b1590830293e7 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 22 Sep 2016 23:42:43 +0200 Subject: [PATCH 42/50] * Terastodon - Fixed that the tokens were not put to battlefield. --- Mage.Sets/src/mage/sets/worldwake/Terastodon.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/worldwake/Terastodon.java b/Mage.Sets/src/mage/sets/worldwake/Terastodon.java index ad2eb45ae7c..30ff2d09ecb 100644 --- a/Mage.Sets/src/mage/sets/worldwake/Terastodon.java +++ b/Mage.Sets/src/mage/sets/worldwake/Terastodon.java @@ -111,7 +111,7 @@ class TerastodonEffect extends OneShotEffect { if (destroyedPermanents.containsKey(permanent.getControllerId())) { numberPermanents = destroyedPermanents.get(permanent.getControllerId()); } - destroyedPermanents.put(permanent.getControllerId(), numberPermanents); + destroyedPermanents.put(permanent.getControllerId(), numberPermanents + 1); } } } From ae8e6122a5bb9ef60e511bc58b7e523386a62637 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 22 Sep 2016 23:58:45 +0200 Subject: [PATCH 43/50] * Smokestack - Fixed that the sacrifice was wrongly handled targeted. --- Mage.Sets/src/mage/sets/urzassaga/Smokestack.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/urzassaga/Smokestack.java b/Mage.Sets/src/mage/sets/urzassaga/Smokestack.java index 42d7bcbbdb3..02fdf63ab36 100644 --- a/Mage.Sets/src/mage/sets/urzassaga/Smokestack.java +++ b/Mage.Sets/src/mage/sets/urzassaga/Smokestack.java @@ -96,7 +96,7 @@ class SmokestackEffect extends OneShotEffect { int count = sourcePermanent.getCounters(game).getCount("Soot"); if (count > 0) { int amount = Math.min(count, game.getBattlefield().countAll(new FilterControlledPermanent(), activePlayer.getId(), game)); - Target target = new TargetControlledPermanent(amount, amount, new FilterControlledPermanent(), false); + Target target = new TargetControlledPermanent(amount, amount, new FilterControlledPermanent(), true); //A spell or ability could have removed the only legal target this player //had, if thats the case this ability should fizzle. if (target.canChoose(activePlayer.getId(), game)) { From 3c6402f8a6a29849b836730fda95354a12ae52b2 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 23 Sep 2016 00:32:48 +0200 Subject: [PATCH 44/50] * Altar of the Brood - Fixed wrong rule tool tip text. --- Mage.Sets/src/mage/sets/khansoftarkir/AltarOfTheBrood.java | 2 +- .../PutTopCardOfLibraryIntoGraveEachPlayerEffect.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/AltarOfTheBrood.java b/Mage.Sets/src/mage/sets/khansoftarkir/AltarOfTheBrood.java index 781ad817f93..6aa6bb85c89 100644 --- a/Mage.Sets/src/mage/sets/khansoftarkir/AltarOfTheBrood.java +++ b/Mage.Sets/src/mage/sets/khansoftarkir/AltarOfTheBrood.java @@ -56,7 +56,7 @@ public class AltarOfTheBrood extends CardImpl { // Whenever another permanent enters the battlefield under your control, each opponent puts the top card of his or her library into his or her graveyard. this.addAbility(new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, - new PutTopCardOfLibraryIntoGraveEachPlayerEffect(1, TargetController.OPPONENT), filter, false)); + new PutTopCardOfLibraryIntoGraveEachPlayerEffect(1, TargetController.OPPONENT), filter, false, null, true)); } public AltarOfTheBrood(final AltarOfTheBrood card) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveEachPlayerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveEachPlayerEffect.java index dec2bee0464..77ebb1377df 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveEachPlayerEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveEachPlayerEffect.java @@ -111,13 +111,13 @@ public class PutTopCardOfLibraryIntoGraveEachPlayerEffect extends OneShotEffect StringBuilder sb = new StringBuilder(); switch (targetController) { case OPPONENT: - sb.append("Each opponent "); + sb.append("each opponent "); break; case ANY: - sb.append("Each player "); + sb.append("each player "); break; case NOT_YOU: - sb.append("Each other player "); + sb.append("each other player "); break; default: throw new UnsupportedOperationException("TargetController type not supported."); From 1509b2ea089807073ec1bebfd4172a474530c780 Mon Sep 17 00:00:00 2001 From: eirkei Date: Fri, 23 Sep 2016 14:43:07 +0200 Subject: [PATCH 45/50] Krosan Drover implemented --- .../src/mage/sets/scourge/KrosanDrover.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/scourge/KrosanDrover.java diff --git a/Mage.Sets/src/mage/sets/scourge/KrosanDrover.java b/Mage.Sets/src/mage/sets/scourge/KrosanDrover.java new file mode 100644 index 00000000000..35c049026b3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/scourge/KrosanDrover.java @@ -0,0 +1,75 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.scourge; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.Filter.ComparisonType; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; + +/** + * + * @author Eirkei + */ +public class KrosanDrover extends CardImpl { + + private static final FilterCard filter = new FilterCard("Creature spells with converted mana cost 6 or greater"); + + static { + filter.add(new CardTypePredicate(CardType.CREATURE)); + filter.add(new ConvertedManaCostPredicate(ComparisonType.GreaterThan, 5)); + } + + public KrosanDrover(UUID ownerId) { + super(ownerId, 122, "Krosan Drover", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{3}{G}"); + this.expansionSetCode = "SCG"; + this.subtype.add("Elf"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Creature spells you cast with converted mana cost 6 or greater cost {2} less to cast. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(filter, 2))); + } + + public KrosanDrover(final KrosanDrover card) { + super(card); + } + + @Override + public KrosanDrover copy() { + return new KrosanDrover(this); + } +} From 5d50179c8497a2f7a05745677fd83bffefc025d5 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 23 Sep 2016 15:12:21 +0200 Subject: [PATCH 46/50] Added Test. --- .../mage/test/cards/modal/OneOrBothTest.java | 105 ++++++++++++++++++ Mage/src/main/java/mage/abilities/Modes.java | 55 +++++---- 2 files changed, 141 insertions(+), 19 deletions(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/modal/OneOrBothTest.java diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/modal/OneOrBothTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/modal/OneOrBothTest.java new file mode 100644 index 00000000000..cee56e63951 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/modal/OneOrBothTest.java @@ -0,0 +1,105 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package org.mage.test.cards.modal; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class OneOrBothTest extends CardTestPlayerBase { + + @Test + public void testSubtleStrikeFirstMode() { + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2); + // Choose one or both — + // • Target creature gets -1/-1 until end of turn. + // • Put a +1/+1 counter on target creature. + addCard(Zone.HAND, playerA, "Subtle Strike"); // Instant {1}{B} + + addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); + addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Subtle Strike", "Silvercoat Lion"); + setModeChoice(playerA, "1"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPowerToughness(playerA, "Silvercoat Lion", 2, 2); + assertPowerToughness(playerB, "Pillarfield Ox", 1, 3); + } + + @Test + public void testSubtleStrikeSecondMode() { + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2); + // Choose one or both — + // • Target creature gets -1/-1 until end of turn. + // • Put a +1/+1 counter on target creature. + addCard(Zone.HAND, playerA, "Subtle Strike"); // Instant {1}{B} + + addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); + addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Subtle Strike", "Pillarfield Ox"); + setModeChoice(playerA, "2"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPowerToughness(playerA, "Silvercoat Lion", 2, 2); + assertPowerToughness(playerB, "Pillarfield Ox", 3, 5); + } + + @Test + public void testSubtleStrikeBothModes() { + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2); + // Choose one or both — + // • Target creature gets -1/-1 until end of turn. + // • Put a +1/+1 counter on target creature. + addCard(Zone.HAND, playerA, "Subtle Strike"); // Instant {1}{B} + + addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); + addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Subtle Strike", "Pillarfield Ox"); + addTarget(playerA, "Silvercoat Lion"); + setModeChoice(playerA, "1"); + setModeChoice(playerA, "2"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPowerToughness(playerA, "Silvercoat Lion", 3, 3); + assertPowerToughness(playerB, "Pillarfield Ox", 1, 3); + } +} diff --git a/Mage/src/main/java/mage/abilities/Modes.java b/Mage/src/main/java/mage/abilities/Modes.java index 08a317f95cf..c8fa0d3cae8 100644 --- a/Mage/src/main/java/mage/abilities/Modes.java +++ b/Mage/src/main/java/mage/abilities/Modes.java @@ -49,7 +49,7 @@ import mage.util.CardUtil; */ public class Modes extends LinkedHashMap { - private Mode mode; // the current mode of the selected modes + private Mode currentMode; // the current mode of the selected modes private final ArrayList selectedModes = new ArrayList<>(); private int minModes; private int maxModes; @@ -58,11 +58,11 @@ public class Modes extends LinkedHashMap { private boolean eachModeOnlyOnce; // state if each mode can be chosen only once as long as the source object exists public Modes() { - this.mode = new Mode(); - this.put(mode.getId(), mode); + this.currentMode = new Mode(); + this.put(currentMode.getId(), currentMode); this.minModes = 1; this.maxModes = 1; - this.selectedModes.add(mode); + this.selectedModes.add(currentMode); this.modeChooser = TargetController.YOU; this.eachModeOnlyOnce = false; this.eachModeMoreThanOnce = false; @@ -76,19 +76,17 @@ public class Modes extends LinkedHashMap { this.maxModes = modes.maxModes; if (modes.size() == 1) { - this.mode = values().iterator().next(); - this.selectedModes.add(mode); + this.currentMode = values().iterator().next(); + this.selectedModes.add(currentMode); } else { // probably there is still a problem with copying modes with the same mode selected multiple times. for (Mode selectedMode : modes.getSelectedModes()) { Mode copiedMode = selectedMode.copy(); this.selectedModes.add(copiedMode); if (modes.getSelectedModes().size() == 1) { - this.mode = copiedMode; - } else { - if (selectedMode.equals(modes.getMode())) { - this.mode = copiedMode; - } + this.currentMode = copiedMode; + } else if (selectedMode.equals(modes.getMode())) { + this.currentMode = copiedMode; } } } @@ -102,15 +100,15 @@ public class Modes extends LinkedHashMap { } public Mode getMode() { - return mode; + return currentMode; } public UUID getModeId(int index) { int idx = 0; - for (Mode currentMode : this.values()) { + for (Mode mode : this.values()) { idx++; if (idx == index) { - return currentMode.getId(); + return mode.getId(); } } return null; @@ -146,7 +144,7 @@ public class Modes extends LinkedHashMap { public void setActiveMode(Mode mode) { if (selectedModes.contains(mode)) { - this.mode = mode; + this.currentMode = mode; } } @@ -203,7 +201,7 @@ public class Modes extends LinkedHashMap { Player player = game.getPlayer(playerId); // player chooses modes manually - this.mode = null; + this.currentMode = null; while (this.selectedModes.size() < this.getMaxModes()) { Mode choice = player.chooseMode(this, source, game); if (choice == null) { @@ -213,8 +211,8 @@ public class Modes extends LinkedHashMap { return this.selectedModes.size() >= this.getMinModes(); } this.selectedModes.add(choice.copy()); - if (mode == null) { - mode = choice; + if (currentMode == null) { + currentMode = choice; } } if (isEachModeOnlyOnce()) { @@ -222,7 +220,7 @@ public class Modes extends LinkedHashMap { } return true; } - if (mode == null) { + if (currentMode == null) { this.selectedModes.clear(); Mode copiedMode = this.values().iterator().next().copy(); this.selectedModes.add(copiedMode); @@ -234,8 +232,16 @@ public class Modes extends LinkedHashMap { return true; } + /** + * Saves the already selected modes to the state value + * + * @param selectedModes + * @param source + * @param game + */ private void setAlreadySelectedModes(ArrayList selectedModes, Ability source, Game game) { String key = getKey(source, game); + @SuppressWarnings("unchecked") Set onceSelectedModes = (Set) game.getState().getValue(key); if (onceSelectedModes == null) { onceSelectedModes = new HashSet<>(); @@ -247,14 +253,25 @@ public class Modes extends LinkedHashMap { game.getState().setValue(key, onceSelectedModes); } + // The already once selected modes for a modal card are stored as a state value + // That's important for modal abilities with modes that can only selected once while the object stays in its zone + @SuppressWarnings("unchecked") private Set getAlreadySelectedModes(Ability source, Game game) { return (Set) game.getState().getValue(getKey(source, game)); } + // creates the key the selected modes are saved with to the state values private String getKey(Ability source, Game game) { return CardUtil.getObjectZoneString("selectedModes", source.getSourceId(), game, game.getState().getZoneChangeCounter(source.getSourceId()), false); } + /** + * Returns all (still) available modes of the ability + * + * @param source + * @param game + * @return + */ public List getAvailableModes(Ability source, Game game) { List availableModes = new ArrayList<>(); Set nonAvailableModes; From 0b118d074e25926cf3a64af28e357ae522ec51a5 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 23 Sep 2016 19:10:25 +0200 Subject: [PATCH 47/50] * Demonic Pact - Fixed that the already chosen options were not correctly rollbacked. --- Mage/src/main/java/mage/abilities/Modes.java | 25 ++++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/Mage/src/main/java/mage/abilities/Modes.java b/Mage/src/main/java/mage/abilities/Modes.java index c8fa0d3cae8..7ac07f93681 100644 --- a/Mage/src/main/java/mage/abilities/Modes.java +++ b/Mage/src/main/java/mage/abilities/Modes.java @@ -41,7 +41,6 @@ import mage.constants.TargetController; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetOpponent; -import mage.util.CardUtil; /** * @@ -240,29 +239,29 @@ public class Modes extends LinkedHashMap { * @param game */ private void setAlreadySelectedModes(ArrayList selectedModes, Ability source, Game game) { - String key = getKey(source, game); - @SuppressWarnings("unchecked") - Set onceSelectedModes = (Set) game.getState().getValue(key); - if (onceSelectedModes == null) { - onceSelectedModes = new HashSet<>(); - } for (Mode mode : selectedModes) { - onceSelectedModes.add(mode.getId()); + String key = getKey(source, game, mode.getId()); + game.getState().setValue(key, true); } - - game.getState().setValue(key, onceSelectedModes); } // The already once selected modes for a modal card are stored as a state value // That's important for modal abilities with modes that can only selected once while the object stays in its zone @SuppressWarnings("unchecked") private Set getAlreadySelectedModes(Ability source, Game game) { - return (Set) game.getState().getValue(getKey(source, game)); + Set onceSelectedModes = new HashSet<>(); + for (UUID modeId : this.keySet()) { + Object exist = game.getState().getValue(getKey(source, game, modeId)); + if (exist != null) { + onceSelectedModes.add(modeId); + } + } + return onceSelectedModes; } // creates the key the selected modes are saved with to the state values - private String getKey(Ability source, Game game) { - return CardUtil.getObjectZoneString("selectedModes", source.getSourceId(), game, game.getState().getZoneChangeCounter(source.getSourceId()), false); + private String getKey(Ability source, Game game, UUID modeId) { + return source.getSourceId().toString() + game.getState().getZoneChangeCounter(source.getSourceId()) + modeId.toString(); } /** From c9bb0be016d1b13611d3ab25b34974bd669b6c78 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 24 Sep 2016 01:12:01 +0200 Subject: [PATCH 48/50] Reworked selected modes handling. That fixed the Subtle Strike targeting problem. --- Mage.Common/src/mage/view/CardView.java | 23 ++++---- .../src/mage/view/StackAbilityView.java | 6 ++- .../java/mage/player/ai/ComputerPlayer.java | 3 +- .../src/mage/player/human/HumanPlayer.java | 3 +- .../battleforzendikar/ZadaHedronGrinder.java | 9 ++-- .../mage/sets/chronicles/GoblinArtisans.java | 54 +++++++++---------- .../sets/dragonsoftarkir/IcefallRegent.java | 3 +- .../sets/fatereforged/MonasterySiege.java | 3 +- .../sets/kaladesh/CapturedByTheConsulate.java | 3 +- .../sets/magicorigins/PsychicRebuttal.java | 3 +- .../sets/planechase2012/ElderwoodScion.java | 3 +- .../src/mage/sets/scourge/GripOfChaos.java | 7 +-- .../shadowsoverinnistrad/AccursedWitch.java | 3 +- .../shadowsoverinnistrad/InfectiousCurse.java | 3 +- .../sets/shardsofalara/HinderingLight.java | 3 +- .../src/mage/sets/venservskoth/Torchling.java | 6 +-- .../sets/vintagemasters/KaerveksTorch.java | 3 +- .../test/AI/basic/CastDestroySpellsTest.java | 6 +-- .../mage/test/cards/modal/OneOrBothTest.java | 4 +- .../cards/single/bfz/BrutalExpulsionTest.java | 24 +++++---- .../java/org/mage/test/player/TestPlayer.java | 3 +- .../main/java/mage/abilities/AbilityImpl.java | 6 ++- Mage/src/main/java/mage/abilities/Modes.java | 37 +++++-------- ...getOfTargetSpellAbilityToSourceEffect.java | 11 ++-- .../mage/abilities/keyword/HeroicAbility.java | 5 +- .../mageobject/NumberOfTargetsPredicate.java | 4 +- .../other/TargetsPermanentPredicate.java | 3 +- Mage/src/main/java/mage/game/GameState.java | 12 +++-- Mage/src/main/java/mage/game/stack/Spell.java | 9 ++-- .../java/mage/game/stack/StackObjImpl.java | 7 ++- .../main/java/mage/players/PlayerImpl.java | 2 +- .../common/TargetCreatureOrPlaneswalker.java | 19 ++++++- .../main/java/mage/util/TargetAddress.java | 4 +- 33 files changed, 163 insertions(+), 131 deletions(-) diff --git a/Mage.Common/src/mage/view/CardView.java b/Mage.Common/src/mage/view/CardView.java index 2e0414ecb8c..9accefe8ed5 100644 --- a/Mage.Common/src/mage/view/CardView.java +++ b/Mage.Common/src/mage/view/CardView.java @@ -30,7 +30,6 @@ package mage.view; import java.util.ArrayList; import java.util.List; import java.util.UUID; - import mage.MageObject; import mage.ObjectColor; import mage.abilities.Mode; @@ -55,7 +54,6 @@ import mage.game.stack.Spell; import mage.game.stack.StackAbility; import mage.target.Target; import mage.target.Targets; -import org.apache.log4j.Logger; /** * @author BetaSteward_at_googlemail.com @@ -81,7 +79,7 @@ public class CardView extends SimpleCardView { protected List manaCost; protected int convertedManaCost; protected Rarity rarity; - + protected MageObjectType mageObjectType = MageObjectType.NULL; protected boolean isAbility; @@ -323,7 +321,8 @@ public class CardView extends SimpleCardView { this.mageObjectType = MageObjectType.SPELL; Spell spell = (Spell) card; for (SpellAbility spellAbility : spell.getSpellAbilities()) { - for (Mode mode : spellAbility.getModes().getSelectedModes()) { + for (UUID modeId : spellAbility.getModes().getSelectedModes()) { + Mode mode = spellAbility.getModes().get(modeId); if (mode.getTargets().size() > 0) { setTargets(spellAbility.getTargets()); } @@ -331,18 +330,19 @@ public class CardView extends SimpleCardView { } // show for modal spell, which mode was choosen if (spell.getSpellAbility().isModal()) { - for (Mode mode : spell.getSpellAbility().getModes().getSelectedModes()) { + for (UUID modeId : spell.getSpellAbility().getModes().getSelectedModes()) { + Mode mode = spell.getSpellAbility().getModes().get(modeId); this.rules.add("Chosen mode: " + mode.getEffects().getText(mode) + ""); } } } - + // Frame color this.frameColor = card.getFrameColor(game); // Frame style this.frameStyle = card.getFrameStyle(); - + // Get starting loyalty this.startingLoyalty = "" + card.getStartingLoyalty(); } @@ -355,7 +355,7 @@ public class CardView extends SimpleCardView { this.mageObjectType = MageObjectType.PERMANENT; this.power = Integer.toString(object.getPower().getValue()); this.toughness = Integer.toString(object.getToughness().getValue()); - this.loyalty = Integer.toString(((Permanent) object).getCounters((Game)null).getCount(CounterType.LOYALTY)); + this.loyalty = Integer.toString(((Permanent) object).getCounters((Game) null).getCount(CounterType.LOYALTY)); } else { this.power = object.getPower().toString(); this.toughness = object.getToughness().toString(); @@ -488,7 +488,7 @@ public class CardView extends SimpleCardView { this.rarity = Rarity.NA; this.type = token.getTokenType(); this.tokenDescriptor = token.getTokenDescriptor(); - this.tokenSetCode = token.getOriginalExpansionSetCode(); + this.tokenSetCode = token.getOriginalExpansionSetCode(); } protected final void setTargets(Targets targets) { @@ -547,7 +547,7 @@ public class CardView extends SimpleCardView { public String getLoyalty() { return loyalty; } - + public String getStartingLoyalty() { return startingLoyalty; } @@ -567,7 +567,7 @@ public class CardView extends SimpleCardView { public ObjectColor getColor() { return color; } - + public ObjectColor getFrameColor() { return frameColor; } @@ -807,4 +807,3 @@ public class CardView extends SimpleCardView { } } - diff --git a/Mage.Common/src/mage/view/StackAbilityView.java b/Mage.Common/src/mage/view/StackAbilityView.java index 9b195d1b5bb..1c5c6914d52 100644 --- a/Mage.Common/src/mage/view/StackAbilityView.java +++ b/Mage.Common/src/mage/view/StackAbilityView.java @@ -99,7 +99,8 @@ public class StackAbilityView extends CardView { private void updateTargets(Game game, StackAbility ability) { List names = new ArrayList<>(); - for (Mode mode : ability.getModes().getSelectedModes()) { + for (UUID modeId : ability.getModes().getSelectedModes()) { + Mode mode = ability.getModes().get(modeId); if (mode.getTargets().size() > 0) { setTargets(mode.getTargets()); } else { @@ -132,7 +133,8 @@ public class StackAbilityView extends CardView { // show for modal ability, which mode was choosen if (ability.isModal()) { Modes modes = ability.getModes(); - for (Mode mode : modes.getSelectedModes()) { + for (UUID modeId : modes.getSelectedModes()) { + Mode mode = modes.get(modeId); this.rules.add("Chosen mode: " + mode.getEffects().getText(mode) + ""); } } diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java index 0d1a60d29dd..8f2d515fe35 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java @@ -1516,7 +1516,8 @@ public class ComputerPlayer extends PlayerImpl implements Player { //TODO: improve this; AvailableMode: for (Mode mode : modes.getAvailableModes(source, game)) { - for (Mode selectedMode : modes.getSelectedModes()) { + for (UUID selectedModeId : modes.getSelectedModes()) { + Mode selectedMode = modes.get(selectedModeId); if (selectedMode.getId().equals(mode.getId())) { continue AvailableMode; } diff --git a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java index 4b8bb57eece..03ca681e47f 100644 --- a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java @@ -1326,7 +1326,8 @@ public class HumanPlayer extends PlayerImpl { AvailableModes: for (Mode mode : modes.getAvailableModes(source, game)) { int timesSelected = 0; - for (Mode selectedMode : modes.getSelectedModes()) { + for (UUID selectedModeId : modes.getSelectedModes()) { + Mode selectedMode = modes.get(selectedModeId); if (mode.getId().equals(selectedMode.getId())) { if (modes.isEachModeMoreThanOnce()) { timesSelected++; diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/ZadaHedronGrinder.java b/Mage.Sets/src/mage/sets/battleforzendikar/ZadaHedronGrinder.java index 129686fc335..557f05bd6f1 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/ZadaHedronGrinder.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/ZadaHedronGrinder.java @@ -104,7 +104,8 @@ class ZadaHedronGrinderTriggeredAbility extends TriggeredAbilityImpl { if (isControlledInstantOrSorcery(spell)) { boolean targetsSource = false; for (Ability ability : spell.getSpellAbilities()) { - for (Mode mode : ability.getModes().getSelectedModes()) { + for (UUID modeId : ability.getModes().getSelectedModes()) { + Mode mode = ability.getModes().get(modeId); for (Target target : mode.getTargets()) { if (!target.isNotTarget()) { for (UUID targetId : target.getTargets()) { @@ -167,7 +168,8 @@ class ZadaHedronGrinderEffect extends OneShotEffect { Target usedTarget = null; setUsedTarget: for (Ability ability : spell.getSpellAbilities()) { - for (Mode mode : ability.getModes().getSelectedModes()) { + for (UUID modeId : ability.getModes().getSelectedModes()) { + Mode mode = ability.getModes().get(modeId); for (Target target : mode.getTargets()) { if (!target.isNotTarget() && target.getFirstTarget().equals(source.getSourceId())) { usedTarget = target.copy(); @@ -185,7 +187,8 @@ class ZadaHedronGrinderEffect extends OneShotEffect { Spell copy = spell.copySpell(source.getControllerId()); game.getStack().push(copy); setTarget: - for (Mode mode : copy.getSpellAbility().getModes().getSelectedModes()) { + for (UUID modeId : copy.getSpellAbility().getModes().getSelectedModes()) { + Mode mode = copy.getSpellAbility().getModes().get(modeId); for (Target target : mode.getTargets()) { if (target.getClass().equals(usedTarget.getClass())) { target.clearChosen(); // For targets with Max > 1 we need to clear before the text is comapred diff --git a/Mage.Sets/src/mage/sets/chronicles/GoblinArtisans.java b/Mage.Sets/src/mage/sets/chronicles/GoblinArtisans.java index a255033f825..271326e7b58 100644 --- a/Mage.Sets/src/mage/sets/chronicles/GoblinArtisans.java +++ b/Mage.Sets/src/mage/sets/chronicles/GoblinArtisans.java @@ -70,7 +70,7 @@ public class GoblinArtisans extends CardImpl { // {tap}: Flip a coin. If you win the flip, draw a card. If you lose the flip, counter target artifact spell you control that isn't the target of an ability from another creature named Goblin Artisans. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new GoblinArtisansEffect(), new TapSourceCost())); - + } public GoblinArtisans(final GoblinArtisans card) { @@ -83,15 +83,14 @@ public class GoblinArtisans extends CardImpl { } } - class GoblinArtisansEffect extends OneShotEffect { private static final FilterPermanent filter = new FilterPermanent("permanent named Goblin Artisans"); - + static { filter.add(new NamePredicate("Goblin Artisans")); } - + public GoblinArtisansEffect() { super(Outcome.Damage); staticText = "Flip a coin. If you win the flip, draw a card. If you lose the flip, counter target artifact spell you control that isn't the target of an ability from another creature named Goblin Artisans."; @@ -109,37 +108,38 @@ class GoblinArtisansEffect extends OneShotEffect { controller.drawCards(1, game); } else { List artifacts = game.getBattlefield().getActivePermanents(new FilterControlledArtifactPermanent(), source.getControllerId(), game); - if (artifacts.isEmpty()){//Don't even bother if there is no artifact to 'counter'/sacrifice + if (artifacts.isEmpty()) {//Don't even bother if there is no artifact to 'counter'/sacrifice return true; - } - + } + filter.add(Predicates.not(new PermanentIdPredicate(source.getSourceId()))); - //removed the activating instance of Artisans, btw, wasn't that filter declared as static final? How come I can do this here? :) - List list = game.getBattlefield().getAllActivePermanents(filter, game); - for (Permanent perm : list){ // should I limit below for a particular kind of ability? Going for the most general, it's unlikely there'll be any other artisans anyway, so not concerned about efficiency :p - for (Ability abil : perm.getAbilities(game)){//below is copied from TargetsPermanentPredicate, but why only "selectedModes"? Shouldnt be more general as well? - for (Mode mode : abil.getModes().getSelectedModes()){ + //removed the activating instance of Artisans, btw, wasn't that filter declared as static final? How come I can do this here? :) + List list = game.getBattlefield().getAllActivePermanents(filter, game); + for (Permanent perm : list) { // should I limit below for a particular kind of ability? Going for the most general, it's unlikely there'll be any other artisans anyway, so not concerned about efficiency :p + for (Ability abil : perm.getAbilities(game)) {//below is copied from TargetsPermanentPredicate, but why only "selectedModes"? Shouldnt be more general as well? + for (UUID modeId : abil.getModes().getSelectedModes()) { + Mode mode = abil.getModes().get(modeId); for (Target target : mode.getTargets()) { - for (UUID targetId : target.getTargets()) { - artifacts.remove(game.getPermanentOrLKIBattlefield(targetId)); - }// we could - }// remove this - }//closing bracers - }// pyramid, if it's bothering anyone - } //they are all one-liners after all :) - if (!artifacts.isEmpty()){ - Cards cards=new CardsImpl(); - for (Permanent perm : artifacts){ + for (UUID targetId : target.getTargets()) { + artifacts.remove(game.getPermanentOrLKIBattlefield(targetId)); + }// we could + }// remove this + }//closing bracers + }// pyramid, if it's bothering anyone + } //they are all one-liners after all :) + if (!artifacts.isEmpty()) { + Cards cards = new CardsImpl(); + for (Permanent perm : artifacts) { cards.add(perm.getId()); } - TargetCard target = new TargetCard(Zone.BATTLEFIELD, new FilterCard()); + TargetCard target = new TargetCard(Zone.BATTLEFIELD, new FilterCard()); controller.choose(Outcome.Sacrifice, cards, target, game); - game.getPermanent(target.getFirstTarget()).sacrifice(source.getSourceId(), game); - } + game.getPermanent(target.getFirstTarget()).sacrifice(source.getSourceId(), game); + } return true; - } } - + } + return false; } diff --git a/Mage.Sets/src/mage/sets/dragonsoftarkir/IcefallRegent.java b/Mage.Sets/src/mage/sets/dragonsoftarkir/IcefallRegent.java index 7a5b1418363..dfac065c16f 100644 --- a/Mage.Sets/src/mage/sets/dragonsoftarkir/IcefallRegent.java +++ b/Mage.Sets/src/mage/sets/dragonsoftarkir/IcefallRegent.java @@ -227,7 +227,8 @@ class IcefallRegentCostIncreaseEffect extends CostModificationEffectImpl { public boolean applies(Ability abilityToModify, Ability source, Game game) { if (abilityToModify instanceof SpellAbility) { if (game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) { - for (Mode mode : abilityToModify.getModes().getSelectedModes()) { + for (UUID modeId : abilityToModify.getModes().getSelectedModes()) { + Mode mode = abilityToModify.getModes().get(modeId); for (Target target : mode.getTargets()) { for (UUID targetUUID : target.getTargets()) { if (targetUUID.equals(source.getSourceId())) { diff --git a/Mage.Sets/src/mage/sets/fatereforged/MonasterySiege.java b/Mage.Sets/src/mage/sets/fatereforged/MonasterySiege.java index 77e9e768e4c..d3b6e04e238 100644 --- a/Mage.Sets/src/mage/sets/fatereforged/MonasterySiege.java +++ b/Mage.Sets/src/mage/sets/fatereforged/MonasterySiege.java @@ -109,7 +109,8 @@ class MonasterySiegeCostIncreaseEffect extends CostModificationEffectImpl { if (new ModeChoiceSourceCondition("Dragons").apply(game, source)) { if (abilityToModify instanceof SpellAbility) { if (game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) { - for (Mode mode : abilityToModify.getModes().getSelectedModes()) { + for (UUID modeId : abilityToModify.getModes().getSelectedModes()) { + Mode mode = abilityToModify.getModes().get(modeId); for (Target target : mode.getTargets()) { for (UUID targetUUID : target.getTargets()) { if (targetUUID.equals(source.getControllerId())) { diff --git a/Mage.Sets/src/mage/sets/kaladesh/CapturedByTheConsulate.java b/Mage.Sets/src/mage/sets/kaladesh/CapturedByTheConsulate.java index 5de6ebe9bdc..bb0eb4cc8d2 100644 --- a/Mage.Sets/src/mage/sets/kaladesh/CapturedByTheConsulate.java +++ b/Mage.Sets/src/mage/sets/kaladesh/CapturedByTheConsulate.java @@ -141,7 +141,8 @@ class CapturedByTheConsulateTriggeredAbility extends TriggeredAbilityImpl { } if (stackObject != null) { int numberOfTargets = 0; - for (Mode mode : stackObject.getStackAbility().getModes().getSelectedModes()) { + for (UUID modeId : stackObject.getStackAbility().getModes().getSelectedModes()) { + Mode mode = stackObject.getStackAbility().getModes().get(modeId); for (Target target : mode.getTargets()) { numberOfTargets += target.getTargets().size(); } diff --git a/Mage.Sets/src/mage/sets/magicorigins/PsychicRebuttal.java b/Mage.Sets/src/mage/sets/magicorigins/PsychicRebuttal.java index 9aa89e0b2f2..533925a5786 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/PsychicRebuttal.java +++ b/Mage.Sets/src/mage/sets/magicorigins/PsychicRebuttal.java @@ -135,7 +135,8 @@ class PsychicRebuttalPredicate implements ObjectPlayerPredicate possibleTargets = target.possibleTargets(source.getSourceId(), source.getControllerId(), game); diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/AccursedWitch.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/AccursedWitch.java index bc42294c7f1..6e0f6c19ae0 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/AccursedWitch.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/AccursedWitch.java @@ -140,7 +140,8 @@ class AccursedWitchSpellsCostReductionEffect extends CostModificationEffectImpl public boolean applies(Ability abilityToModify, Ability source, Game game) { if (abilityToModify instanceof SpellAbility) { if (game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) { - for (Mode mode : abilityToModify.getModes().getSelectedModes()) { + for (UUID modeId : abilityToModify.getModes().getSelectedModes()) { + Mode mode = abilityToModify.getModes().get(modeId); for (Target target : mode.getTargets()) { for (UUID targetUUID : target.getTargets()) { Permanent permanent = game.getPermanent(targetUUID); diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/InfectiousCurse.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/InfectiousCurse.java index 2cc858e4bb6..03e76ef9b6e 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/InfectiousCurse.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/InfectiousCurse.java @@ -155,7 +155,8 @@ class InfectiousCurseCostReductionEffect extends CostModificationEffectImpl { public boolean applies(Ability abilityToModify, Ability source, Game game) { if (abilityToModify instanceof SpellAbility) { if (source.getControllerId().equals(abilityToModify.getControllerId())) { - for (Mode mode : abilityToModify.getModes().getSelectedModes()) { + for (UUID modeId : abilityToModify.getModes().getSelectedModes()) { + Mode mode = abilityToModify.getModes().get(modeId); for (Target target : mode.getTargets()) { for (UUID targetUUID : target.getTargets()) { Permanent enchantment = game.getPermanent(source.getSourceId()); diff --git a/Mage.Sets/src/mage/sets/shardsofalara/HinderingLight.java b/Mage.Sets/src/mage/sets/shardsofalara/HinderingLight.java index 7726f3ab806..6cfe4482004 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/HinderingLight.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/HinderingLight.java @@ -84,7 +84,8 @@ class HinderingLightPredicate implements ObjectPlayerPredicate { if (spell != null) { int numberOfTargets = 0; for (SpellAbility spellAbility : spell.getSpellAbilities()) { - for (Mode mode : spellAbility.getModes().getSelectedModes()) { + for (UUID modeId : spellAbility.getModes().getSelectedModes()) { + Mode mode = spellAbility.getModes().get(modeId); for (Target target : mode.getTargets()) { for (UUID targetId : target.getTargets()) { if (!targetId.equals(sourceId)) { return false; - } - else { + } else { numberOfTargets++; } } diff --git a/Mage.Sets/src/mage/sets/vintagemasters/KaerveksTorch.java b/Mage.Sets/src/mage/sets/vintagemasters/KaerveksTorch.java index 2af317e2e49..14b5866ca5f 100644 --- a/Mage.Sets/src/mage/sets/vintagemasters/KaerveksTorch.java +++ b/Mage.Sets/src/mage/sets/vintagemasters/KaerveksTorch.java @@ -96,7 +96,8 @@ class KaerveksTorchCostIncreaseEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility) { - for (Mode mode : abilityToModify.getModes().getSelectedModes()) { + for (UUID modeId : abilityToModify.getModes().getSelectedModes()) { + Mode mode = abilityToModify.getModes().get(modeId); for (Target target : mode.getTargets()) { for (UUID targetId : target.getTargets()) { if (targetId.equals(source.getSourceObject(game).getId())) { diff --git a/Mage.Tests/src/test/java/org/mage/test/AI/basic/CastDestroySpellsTest.java b/Mage.Tests/src/test/java/org/mage/test/AI/basic/CastDestroySpellsTest.java index 57f34cbc672..792284f65ab 100644 --- a/Mage.Tests/src/test/java/org/mage/test/AI/basic/CastDestroySpellsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/AI/basic/CastDestroySpellsTest.java @@ -38,10 +38,6 @@ import org.mage.test.serverside.base.CardTestPlayerBaseAI; */ public class CastDestroySpellsTest extends CardTestPlayerBaseAI { - /** - * - * - */ @Test public void testOrzhovCharm() { // Choose one - @@ -58,6 +54,8 @@ public class CastDestroySpellsTest extends CardTestPlayerBaseAI { // Cycling abilities you activate cost you up to {2} less to activate. addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Orzhov Charm", "Silvercoat Lion"); + setModeChoice(playerA, "2"); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/modal/OneOrBothTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/modal/OneOrBothTest.java index cee56e63951..52aef300aaf 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/modal/OneOrBothTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/modal/OneOrBothTest.java @@ -49,8 +49,9 @@ public class OneOrBothTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox"); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Subtle Strike", "Silvercoat Lion"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Subtle Strike", "Pillarfield Ox"); setModeChoice(playerA, "1"); + setModeChoice(playerA, null); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); @@ -72,6 +73,7 @@ public class OneOrBothTest extends CardTestPlayerBase { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Subtle Strike", "Pillarfield Ox"); setModeChoice(playerA, "2"); + setModeChoice(playerA, null); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/bfz/BrutalExpulsionTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/bfz/BrutalExpulsionTest.java index 195666c6097..727efe0738b 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/bfz/BrutalExpulsionTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/bfz/BrutalExpulsionTest.java @@ -39,20 +39,22 @@ import org.mage.test.serverside.base.CardTestPlayerBase; public class BrutalExpulsionTest extends CardTestPlayerBase { /** - * Brutal Expulsion targeting Gideon, Ally of Zendikar. Gideon has 3 loyalty. Brutal Expulsion resolves, - * leaves 1 loyalty. I attack Gideon for 1 with a Scion token, Gideon dies. Instead of going to graveyard, - * Expulsion sends Gideon to exile. However, in game Gideon went to graveyard. + * Brutal Expulsion targeting Gideon, Ally of Zendikar. Gideon has 3 + * loyalty. Brutal Expulsion resolves, leaves 1 loyalty. I attack Gideon for + * 1 with a Scion token, Gideon dies. Instead of going to graveyard, + * Expulsion sends Gideon to exile. However, in game Gideon went to + * graveyard. */ @Test public void testPlaneswalkerExile() { // Choose one or both // - Return target spell or creature to its owner's hand; // or Brutal Expulsion deals 2 damage to target creature or planeswalker. If that permanent would be put into a graveyard this turn, exile it instead. - addCard(Zone.HAND, playerA, "Brutal Expulsion"); + addCard(Zone.HAND, playerA, "Brutal Expulsion"); // {2}{U}{R} // Shock deals 2 damage to target creature or player. - addCard(Zone.HAND, playerA, "Shock"); - addCard(Zone.BATTLEFIELD, playerA, "Island", 4); - addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5); + addCard(Zone.HAND, playerA, "Shock"); // {R} + addCard(Zone.BATTLEFIELD, playerA, "Island", 1); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); // Planeswalker with 4 loyalty. addCard(Zone.BATTLEFIELD, playerB, "Gideon, Ally of Zendikar"); @@ -60,12 +62,12 @@ public class BrutalExpulsionTest extends CardTestPlayerBase { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Brutal Expulsion", playerB); setModeChoice(playerA, "2"); setModeChoice(playerA, null); - setChoice(playerA, "Yes"); + setChoice(playerA, "Yes"); // Redirect to planeswalker - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Shock", playerB); - setChoice(playerA, "Yes"); + castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Shock", playerB); + setChoice(playerA, "Yes"); // Redirect to planeswalker - setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + setStopAt(1, PhaseStep.END_COMBAT); execute(); assertPermanentCount(playerB, "Gideon, Ally of Zendikar", 0); diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java index fd3b5ba7906..a8856084e0b 100644 --- a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java +++ b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java @@ -287,7 +287,8 @@ public class TestPlayer implements Player { } UUID modeId = ability.getModes().getModeId(modeNr); - for (Mode mode : ability.getModes().getSelectedModes()) { + for (UUID currentModeId : ability.getModes().getSelectedModes()) { + Mode mode = ability.getModes().get(currentModeId); if (mode.getId().equals(modeId)) { selectedMode = mode; ability.getModes().setActiveMode(mode); diff --git a/Mage/src/main/java/mage/abilities/AbilityImpl.java b/Mage/src/main/java/mage/abilities/AbilityImpl.java index 65f1095d378..c79e37f28bc 100644 --- a/Mage/src/main/java/mage/abilities/AbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/AbilityImpl.java @@ -306,7 +306,8 @@ public abstract class AbilityImpl implements Ability { && game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.CAST_SPELL_LATE, getId(), getSourceId(), getControllerId()), this)) { return false; } - for (Mode mode : this.getModes().getSelectedModes()) { + for (UUID modeId : this.getModes().getSelectedModes()) { + Mode mode = this.getModes().get(modeId); this.getModes().setActiveMode(mode); //20121001 - 601.2c // 601.2c The player announces his or her choice of an appropriate player, object, or zone for @@ -1060,7 +1061,8 @@ public abstract class AbilityImpl implements Ability { } } else if (object instanceof Spell && ((Spell) object).getSpellAbility().getModes().size() > 1) { Modes spellModes = ((Spell) object).getSpellAbility().getModes(); - for (Mode selectedMode : spellModes.getSelectedModes()) { + for (UUID selectedModeId : spellModes.getSelectedModes()) { + Mode selectedMode = spellModes.get(selectedModeId); int item = 0; for (Mode mode : spellModes.values()) { item++; diff --git a/Mage/src/main/java/mage/abilities/Modes.java b/Mage/src/main/java/mage/abilities/Modes.java index 7ac07f93681..6f1ea6502a3 100644 --- a/Mage/src/main/java/mage/abilities/Modes.java +++ b/Mage/src/main/java/mage/abilities/Modes.java @@ -49,7 +49,7 @@ import mage.target.common.TargetOpponent; public class Modes extends LinkedHashMap { private Mode currentMode; // the current mode of the selected modes - private final ArrayList selectedModes = new ArrayList<>(); + private final ArrayList selectedModes = new ArrayList<>(); private int minModes; private int maxModes; private TargetController modeChooser; @@ -61,7 +61,7 @@ public class Modes extends LinkedHashMap { this.put(currentMode.getId(), currentMode); this.minModes = 1; this.maxModes = 1; - this.selectedModes.add(currentMode); + this.selectedModes.add(currentMode.getId()); this.modeChooser = TargetController.YOU; this.eachModeOnlyOnce = false; this.eachModeMoreThanOnce = false; @@ -74,21 +74,8 @@ public class Modes extends LinkedHashMap { this.minModes = modes.minModes; this.maxModes = modes.maxModes; - if (modes.size() == 1) { - this.currentMode = values().iterator().next(); - this.selectedModes.add(currentMode); - } else { - // probably there is still a problem with copying modes with the same mode selected multiple times. - for (Mode selectedMode : modes.getSelectedModes()) { - Mode copiedMode = selectedMode.copy(); - this.selectedModes.add(copiedMode); - if (modes.getSelectedModes().size() == 1) { - this.currentMode = copiedMode; - } else if (selectedMode.equals(modes.getMode())) { - this.currentMode = copiedMode; - } - } - } + this.currentMode = values().iterator().next(); + selectedModes.addAll(modes.getSelectedModes()); this.modeChooser = modes.modeChooser; this.eachModeOnlyOnce = modes.eachModeOnlyOnce; this.eachModeMoreThanOnce = modes.eachModeMoreThanOnce; @@ -113,7 +100,7 @@ public class Modes extends LinkedHashMap { return null; } - public ArrayList getSelectedModes() { + public ArrayList getSelectedModes() { return selectedModes; } @@ -142,7 +129,7 @@ public class Modes extends LinkedHashMap { } public void setActiveMode(Mode mode) { - if (selectedModes.contains(mode)) { + if (selectedModes.contains(mode.getId())) { this.currentMode = mode; } } @@ -172,7 +159,7 @@ public class Modes extends LinkedHashMap { for (Mode mode : this.values()) { if ((!isEachModeOnlyOnce() || onceSelectedModes == null || !onceSelectedModes.contains(mode.getId())) && mode.getTargets().canChoose(source.getSourceId(), source.getControllerId(), game)) { - this.selectedModes.add(mode.copy()); + this.selectedModes.add(mode.getId()); } } if (isEachModeOnlyOnce()) { @@ -209,7 +196,7 @@ public class Modes extends LinkedHashMap { } return this.selectedModes.size() >= this.getMinModes(); } - this.selectedModes.add(choice.copy()); + this.selectedModes.add(choice.getId()); if (currentMode == null) { currentMode = choice; } @@ -222,7 +209,7 @@ public class Modes extends LinkedHashMap { if (currentMode == null) { this.selectedModes.clear(); Mode copiedMode = this.values().iterator().next().copy(); - this.selectedModes.add(copiedMode); + this.selectedModes.add(copiedMode.getId()); this.setActiveMode(copiedMode); } if (isEachModeOnlyOnce()) { @@ -238,9 +225,9 @@ public class Modes extends LinkedHashMap { * @param source * @param game */ - private void setAlreadySelectedModes(ArrayList selectedModes, Ability source, Game game) { - for (Mode mode : selectedModes) { - String key = getKey(source, game, mode.getId()); + private void setAlreadySelectedModes(ArrayList selectedModes, Ability source, Game game) { + for (UUID modeId : selectedModes) { + String key = getKey(source, game, modeId); game.getState().setValue(key, true); } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/ChangeATargetOfTargetSpellAbilityToSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ChangeATargetOfTargetSpellAbilityToSourceEffect.java index 43dd5593277..8884c6c1414 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ChangeATargetOfTargetSpellAbilityToSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ChangeATargetOfTargetSpellAbilityToSourceEffect.java @@ -51,7 +51,8 @@ public class ChangeATargetOfTargetSpellAbilityToSourceEffect extends OneShotEffe } else { return false; } - for (Mode mode : sourceAbility.getModes().getSelectedModes()) { + for (UUID modeId : sourceAbility.getModes().getSelectedModes()) { + Mode mode = sourceAbility.getModes().get(modeId); targets.addAll(mode.getTargets()); } @@ -102,12 +103,10 @@ public class ChangeATargetOfTargetSpellAbilityToSourceEffect extends OneShotEffe } if (oldTargetName != null) { game.informPlayers(sourceObject.getLogName() + ": Changed target of " + stackObject.getLogName() + " from " + oldTargetName + " to " + sourceObject.getLogName()); + } else if (twoTimesTarget) { + game.informPlayers(sourceObject.getLogName() + ": Target not changed to " + sourceObject.getLogName() + " because its not valid to target it twice for " + stackObject.getLogName()); } else { - if (twoTimesTarget) { - game.informPlayers(sourceObject.getLogName() + ": Target not changed to " + sourceObject.getLogName() + " because its not valid to target it twice for " + stackObject.getLogName()); - } else { - game.informPlayers(sourceObject.getLogName() + ": Target not changed to " + sourceObject.getLogName() + " because its no valid target for " + stackObject.getLogName()); - } + game.informPlayers(sourceObject.getLogName() + ": Target not changed to " + sourceObject.getLogName() + " because its no valid target for " + stackObject.getLogName()); } return true; } diff --git a/Mage/src/main/java/mage/abilities/keyword/HeroicAbility.java b/Mage/src/main/java/mage/abilities/keyword/HeroicAbility.java index bbd8ed567db..083a80484b7 100644 --- a/Mage/src/main/java/mage/abilities/keyword/HeroicAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/HeroicAbility.java @@ -1,4 +1,4 @@ - /* +/* * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -82,7 +82,8 @@ public class HeroicAbility extends TriggeredAbilityImpl { private boolean checkSpell(Spell spell, Game game) { if (spell != null) { SpellAbility sa = spell.getSpellAbility(); - for (Mode mode : sa.getModes().getSelectedModes()) { + for (UUID modeId : sa.getModes().getSelectedModes()) { + Mode mode = sa.getModes().get(modeId); for (Target target : mode.getTargets()) { if (!target.isNotTarget() && target.getTargets().contains(this.getSourceId())) { return true; diff --git a/Mage/src/main/java/mage/filter/predicate/mageobject/NumberOfTargetsPredicate.java b/Mage/src/main/java/mage/filter/predicate/mageobject/NumberOfTargetsPredicate.java index 47bfd2ed07c..3653b268a78 100644 --- a/Mage/src/main/java/mage/filter/predicate/mageobject/NumberOfTargetsPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/mageobject/NumberOfTargetsPredicate.java @@ -27,6 +27,7 @@ */ package mage.filter.predicate.mageobject; +import java.util.UUID; import mage.MageObject; import mage.abilities.Mode; import mage.filter.predicate.Predicate; @@ -51,7 +52,8 @@ public class NumberOfTargetsPredicate implements Predicate { StackObject stackObject = game.getState().getStack().getStackObject(input.getId()); if (stackObject != null) { int numberOfTargets = 0; - for (Mode mode : stackObject.getStackAbility().getModes().getSelectedModes()) { + for (UUID modeId : stackObject.getStackAbility().getModes().getSelectedModes()) { + Mode mode = stackObject.getStackAbility().getModes().get(modeId); for (Target target : mode.getTargets()) { numberOfTargets += target.getTargets().size(); } diff --git a/Mage/src/main/java/mage/filter/predicate/other/TargetsPermanentPredicate.java b/Mage/src/main/java/mage/filter/predicate/other/TargetsPermanentPredicate.java index aad5bb551b6..7dc12d7984d 100644 --- a/Mage/src/main/java/mage/filter/predicate/other/TargetsPermanentPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/other/TargetsPermanentPredicate.java @@ -54,7 +54,8 @@ public class TargetsPermanentPredicate implements ObjectSourcePlayerPredicate input, Game game) { StackObject object = game.getStack().getStackObject(input.getObject().getId()); if (object != null) { - for (Mode mode : object.getStackAbility().getModes().getSelectedModes()) { + for (UUID modeId : object.getStackAbility().getModes().getSelectedModes()) { + Mode mode = object.getStackAbility().getModes().get(modeId); for (Target target : mode.getTargets()) { for (UUID targetId : target.getTargets()) { Permanent permanent = game.getPermanentOrLKIBattlefield(targetId); diff --git a/Mage/src/main/java/mage/game/GameState.java b/Mage/src/main/java/mage/game/GameState.java index 2e48c954ce0..eb553340685 100644 --- a/Mage/src/main/java/mage/game/GameState.java +++ b/Mage/src/main/java/mage/game/GameState.java @@ -314,7 +314,8 @@ public class GameState implements Serializable, Copyable { for (StackObject spell : stack) { sb.append(spell.getControllerId()).append(spell.getName()); sb.append(spell.getStackAbility().toString()); - for (Mode mode : spell.getStackAbility().getModes().getSelectedModes()) { + for (UUID modeId : spell.getStackAbility().getModes().getSelectedModes()) { + Mode mode = spell.getStackAbility().getModes().get(modeId); if (!mode.getTargets().isEmpty()) { sb.append("targets"); for (Target target : mode.getTargets()) { @@ -366,7 +367,8 @@ public class GameState implements Serializable, Copyable { for (StackObject spell : stack) { sb.append(spell.getControllerId()).append(spell.getName()); sb.append(spell.getStackAbility().toString()); - for (Mode mode : spell.getStackAbility().getModes().getSelectedModes()) { + for (UUID modeId : spell.getStackAbility().getModes().getSelectedModes()) { + Mode mode = spell.getStackAbility().getModes().get(modeId); if (!mode.getTargets().isEmpty()) { sb.append("targets"); for (Target target : mode.getTargets()) { @@ -784,7 +786,8 @@ public class GameState implements Serializable, Copyable { public void addAbility(Ability ability, MageObject attachedTo) { if (ability instanceof StaticAbility) { - for (Mode mode : ability.getModes().getSelectedModes()) { + for (UUID modeId : ability.getModes().getSelectedModes()) { + Mode mode = ability.getModes().get(modeId); for (Effect effect : mode.getEffects()) { if (effect instanceof ContinuousEffect) { addEffect((ContinuousEffect) effect, ability); @@ -806,7 +809,8 @@ public class GameState implements Serializable, Copyable { */ public void addAbility(Ability ability, UUID sourceId, Card attachedTo) { if (ability instanceof StaticAbility) { - for (Mode mode : ability.getModes().getSelectedModes()) { + for (UUID modeId : ability.getModes().getSelectedModes()) { + Mode mode = ability.getModes().get(modeId); for (Effect effect : mode.getEffects()) { if (effect instanceof ContinuousEffect) { addEffect((ContinuousEffect) effect, sourceId, ability); diff --git a/Mage/src/main/java/mage/game/stack/Spell.java b/Mage/src/main/java/mage/game/stack/Spell.java index b6bc9b98356..f587a9ed7ab 100644 --- a/Mage/src/main/java/mage/game/stack/Spell.java +++ b/Mage/src/main/java/mage/game/stack/Spell.java @@ -210,7 +210,8 @@ public class Spell extends StackObjImpl implements Card { if (notTargeted || legalParts) { for (SpellAbility spellAbility : this.spellAbilities) { if (spellAbilityHasLegalParts(spellAbility, game)) { - for (Mode mode : spellAbility.getModes().getSelectedModes()) { + for (UUID modeId : spellAbility.getModes().getSelectedModes()) { + Mode mode = spellAbility.getModes().get(modeId); spellAbility.getModes().setActiveMode(mode); if (mode.getTargets().stillLegal(spellAbility, game)) { if (!spellAbility.getSpellAbilityType().equals(SpellAbilityType.SPLICE)) { @@ -283,7 +284,8 @@ public class Spell extends StackObjImpl implements Card { private boolean hasTargets(SpellAbility spellAbility, Game game) { if (spellAbility.getModes().getSelectedModes().size() > 1) { - for (Mode mode : spellAbility.getModes().getSelectedModes()) { + for (UUID modeId : spellAbility.getModes().getSelectedModes()) { + Mode mode = spellAbility.getModes().get(modeId); if (!mode.getTargets().isEmpty()) { return true; } @@ -299,7 +301,8 @@ public class Spell extends StackObjImpl implements Card { if (spellAbility.getModes().getSelectedModes().size() > 1) { boolean targetedMode = false; boolean legalTargetedMode = false; - for (Mode mode : spellAbility.getModes().getSelectedModes()) { + for (UUID modeId : spellAbility.getModes().getSelectedModes()) { + Mode mode = spellAbility.getModes().get(modeId); if (mode.getTargets().size() > 0) { targetedMode = true; if (mode.getTargets().stillLegal(spellAbility, game)) { diff --git a/Mage/src/main/java/mage/game/stack/StackObjImpl.java b/Mage/src/main/java/mage/game/stack/StackObjImpl.java index 2286fd06ae5..d37d6f78a97 100644 --- a/Mage/src/main/java/mage/game/stack/StackObjImpl.java +++ b/Mage/src/main/java/mage/game/stack/StackObjImpl.java @@ -117,7 +117,8 @@ public abstract class StackObjImpl implements StackObject { } for (Ability ability : objectAbilities) { // Some spells can have more than one mode - for (Mode mode : ability.getModes().getSelectedModes()) { + for (UUID modeId : ability.getModes().getSelectedModes()) { + Mode mode = ability.getModes().get(modeId); ability.getModes().setActiveMode(mode); oldTargetDescription.append(ability.getTargetDescription(mode.getTargets(), game)); for (Target target : mode.getTargets()) { @@ -210,8 +211,7 @@ public abstract class StackObjImpl implements StackObject { again = true; } } else // if possible add the alternate Target - it may not be included in the old definition nor in the already selected targets of the new definition - { - if (newTarget.getTargets().contains(tempTarget.getFirstTarget()) || target.getTargets().contains(tempTarget.getFirstTarget())) { + if (newTarget.getTargets().contains(tempTarget.getFirstTarget()) || target.getTargets().contains(tempTarget.getFirstTarget())) { if (targetController.isHuman()) { if (targetController.chooseUse(Outcome.Benefit, "This target was already selected from origin spell. Reset to original target?", ability, game)) { // use previous target no target was selected @@ -240,7 +240,6 @@ public abstract class StackObjImpl implements StackObject { // valid target was selected, add it to the new target definition newTarget.addTarget(tempTarget.getFirstTarget(), target.getTargetAmount(targetId), ability, game, false); } - } } while (again && targetController.canRespond()); } } // keep the target diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index 6a045a8e48b..8b5ca4049d4 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -2870,7 +2870,7 @@ public abstract class PlayerImpl implements Player, Serializable { for (Mode mode : option.getModes().values()) { Ability newOption = option.copy(); newOption.getModes().getSelectedModes().clear(); - newOption.getModes().getSelectedModes().add(mode); + newOption.getModes().getSelectedModes().add(mode.getId()); newOption.getModes().setActiveMode(mode); if (newOption.getTargets().getUnchosen().size() > 0) { if (newOption.getManaCosts().getVariableCosts().size() > 0) { diff --git a/Mage/src/main/java/mage/target/common/TargetCreatureOrPlaneswalker.java b/Mage/src/main/java/mage/target/common/TargetCreatureOrPlaneswalker.java index 3e58a0523eb..c075c54d4fa 100644 --- a/Mage/src/main/java/mage/target/common/TargetCreatureOrPlaneswalker.java +++ b/Mage/src/main/java/mage/target/common/TargetCreatureOrPlaneswalker.java @@ -25,10 +25,13 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.target.common; +import java.util.UUID; +import mage.abilities.Ability; import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent; +import mage.game.Game; +import mage.players.Player; import mage.target.TargetPermanent; /** @@ -38,7 +41,7 @@ import mage.target.TargetPermanent; public class TargetCreatureOrPlaneswalker extends TargetPermanent { public TargetCreatureOrPlaneswalker() { - this(1, 1 ,new FilterCreatureOrPlaneswalkerPermanent(), false); + this(1, 1, new FilterCreatureOrPlaneswalkerPermanent(), false); } public TargetCreatureOrPlaneswalker(int minNumTargets, int maxNumTargets, FilterCreatureOrPlaneswalkerPermanent filter, boolean notTarget) { @@ -55,4 +58,16 @@ public class TargetCreatureOrPlaneswalker extends TargetPermanent { return new TargetCreatureOrPlaneswalker(this); } + @Override + public boolean isLegal(Ability source, Game game) { + for (UUID playerId : targets.keySet()) { + Player targetPlayer = game.getPlayer(playerId); + if (targetPlayer != null) { + // there seems to be no possibility to add more predicates for theplayer so return here true + return true; + } + } + return super.isLegal(source, game); //To change body of generated methods, choose Tools | Templates. + } + } diff --git a/Mage/src/main/java/mage/util/TargetAddress.java b/Mage/src/main/java/mage/util/TargetAddress.java index 57bdddc23b4..80c5724676d 100644 --- a/Mage/src/main/java/mage/util/TargetAddress.java +++ b/Mage/src/main/java/mage/util/TargetAddress.java @@ -70,7 +70,7 @@ public class TargetAddress { protected Iterator spellAbilityIterator; protected Integer lastSpellAbilityIndex = null; - protected Iterator modeIterator = null; + protected Iterator modeIterator = null; protected Modes modes = null; protected UUID lastMode = null; protected Iterator targetIterator = null; @@ -127,7 +127,7 @@ public class TargetAddress { } if (modeIterator != null && modeIterator.hasNext()) { - lastMode = modeIterator.next().getId(); + lastMode = modeIterator.next(); targetIterator = modes.get(lastMode).getTargets().iterator(); } else { lastMode = null; From d5d00451a84f760fa2ef15947a2efaed426ab37c Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 24 Sep 2016 01:13:13 +0200 Subject: [PATCH 49/50] Fixed a problem with static abilities for battlefield zone where the source was entering the battlefield but the ability did not work. --- .../org/mage/test/cards/abilities/keywords/UndyingTest.java | 2 +- Mage/src/main/java/mage/abilities/StaticAbility.java | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/UndyingTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/UndyingTest.java index 5a2fa4d5402..e591cae4831 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/UndyingTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/UndyingTest.java @@ -219,7 +219,7 @@ public class UndyingTest extends CardTestPlayerBase { } /** - * Tatterkite is getting counters on it, i have him in a edh deck with + * Tatterkite is getting counters on it, I have him in a edh deck with * Mikaeus, the Lunarch and when Tatterkite dies it triggers the undying and * he gets the +1/+1 counters */ diff --git a/Mage/src/main/java/mage/abilities/StaticAbility.java b/Mage/src/main/java/mage/abilities/StaticAbility.java index bbeee56b6a9..1930634dbe8 100644 --- a/Mage/src/main/java/mage/abilities/StaticAbility.java +++ b/Mage/src/main/java/mage/abilities/StaticAbility.java @@ -56,6 +56,9 @@ public abstract class StaticAbility extends AbilityImpl { if (game.getShortLivingLKI(getSourceId(), zone)) { return true; // maybe this can be a problem if effects removed the ability from the object } + if (game.getPermanentEntering(getSourceId()) != null && zone.equals(Zone.BATTLEFIELD)) { + return true; // abilities of permanents entering battlefield are countes as on battlefield + } return super.isInUseableZone(game, source, event); } From 5215a02181de333126c59df53b836f8c45cce9ed Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 24 Sep 2016 02:22:21 +0200 Subject: [PATCH 50/50] Minor change. --- .../src/mage/sets/commander2013/JelevaNephaliasScourge.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/commander2013/JelevaNephaliasScourge.java b/Mage.Sets/src/mage/sets/commander2013/JelevaNephaliasScourge.java index 40657270108..49573dd952c 100644 --- a/Mage.Sets/src/mage/sets/commander2013/JelevaNephaliasScourge.java +++ b/Mage.Sets/src/mage/sets/commander2013/JelevaNephaliasScourge.java @@ -120,7 +120,7 @@ class JelevaNephaliasScourgeEffect extends OneShotEffect { for (int i = 0; i < cardsToExile; i++) { Card card = player.getLibrary().removeFromTop(game); if (card != null) { - card.moveToExile(CardUtil.getCardExileZoneId(game, source), sourceCard.getName(), source.getSourceId(), game); + card.moveToExile(CardUtil.getCardExileZoneId(game, source), sourceCard.getIdName(), source.getSourceId(), game); } } }