mirror of
https://github.com/magefree/mage.git
synced 2026-01-10 12:52:06 -08:00
Merge branch 'master' into Network_Upgrade
Conflicts: Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java Mage.Client/src/main/java/mage/client/game/GamePanel.java Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java Mage.Server/src/main/java/mage/server/Session.java Mage.Server/src/main/java/mage/server/User.java Mage.Server/src/main/java/mage/server/game/GameController.java Mage.Server/src/main/java/mage/server/game/GameSessionPlayer.java Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java
This commit is contained in:
commit
5c829b79d5
552 changed files with 30213 additions and 6146 deletions
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.1</version>
|
||||
<version>1.4.2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage</artifactId>
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>1.4.185</version>
|
||||
<version>1.4.187</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
|||
|
|
@ -1,31 +1,30 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
* 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;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
|
@ -50,26 +49,27 @@ public class ObjectColor implements Serializable, Copyable<ObjectColor>, Compara
|
|||
private boolean red;
|
||||
private boolean green;
|
||||
|
||||
public ObjectColor() {}
|
||||
public ObjectColor() {
|
||||
}
|
||||
|
||||
public ObjectColor(String color) {
|
||||
for (int i = 0; i < color.length(); i++) {
|
||||
switch (color.charAt(i)) {
|
||||
case 'W':
|
||||
white = true;
|
||||
break;
|
||||
case 'U':
|
||||
blue = true;
|
||||
break;
|
||||
case 'B':
|
||||
black = true;
|
||||
break;
|
||||
case 'R':
|
||||
red = true;
|
||||
break;
|
||||
case 'G':
|
||||
green = true;
|
||||
break;
|
||||
case 'W':
|
||||
white = true;
|
||||
break;
|
||||
case 'U':
|
||||
blue = true;
|
||||
break;
|
||||
case 'B':
|
||||
black = true;
|
||||
break;
|
||||
case 'R':
|
||||
red = true;
|
||||
break;
|
||||
case 'G':
|
||||
green = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -157,30 +157,39 @@ public class ObjectColor implements Serializable, Copyable<ObjectColor>, Compara
|
|||
public boolean isWhite() {
|
||||
return white;
|
||||
}
|
||||
|
||||
public void setWhite(boolean white) {
|
||||
this.white = white;
|
||||
}
|
||||
|
||||
public boolean isBlue() {
|
||||
return blue;
|
||||
}
|
||||
|
||||
public void setBlue(boolean blue) {
|
||||
this.blue = blue;
|
||||
}
|
||||
|
||||
public boolean isBlack() {
|
||||
return black;
|
||||
}
|
||||
|
||||
public void setBlack(boolean black) {
|
||||
this.black = black;
|
||||
}
|
||||
|
||||
public boolean isRed() {
|
||||
return red;
|
||||
}
|
||||
|
||||
public void setRed(boolean red) {
|
||||
this.red = red;
|
||||
}
|
||||
|
||||
public boolean isGreen() {
|
||||
return green;
|
||||
}
|
||||
|
||||
public void setGreen(boolean green) {
|
||||
this.green = green;
|
||||
}
|
||||
|
|
@ -287,14 +296,10 @@ public class ObjectColor implements Serializable, Copyable<ObjectColor>, Compara
|
|||
}
|
||||
|
||||
public boolean shares(ObjectColor color) {
|
||||
if (this == color) {
|
||||
return true;
|
||||
}
|
||||
if (!hasColor() && !color.hasColor()) {
|
||||
return true;
|
||||
}
|
||||
return color.white && white || color.blue && blue || color.black && black ||
|
||||
color.red && red || color.green && green;
|
||||
// 105.4. [...] “Multicolored” is not a color. Neither is “colorless.”
|
||||
return !color.isColorless()
|
||||
&& (color.white && white || color.blue && blue || color.black && black
|
||||
|| color.red && red || color.green && green);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -309,32 +314,32 @@ public class ObjectColor implements Serializable, Copyable<ObjectColor>, Compara
|
|||
|
||||
if (this.isMulticolored()) {
|
||||
o1 = 6;
|
||||
} else if(this.isColorless()) {
|
||||
} else if (this.isColorless()) {
|
||||
o1 = 0;
|
||||
} else if(this.isBlack()) {
|
||||
} else if (this.isBlack()) {
|
||||
o1 = 1;
|
||||
} else if(this.isBlue()) {
|
||||
} else if (this.isBlue()) {
|
||||
o1 = 2;
|
||||
} else if(this.isGreen()) {
|
||||
} else if (this.isGreen()) {
|
||||
o1 = 3;
|
||||
} else if(this.isRed()) {
|
||||
} else if (this.isRed()) {
|
||||
o1 = 4;
|
||||
} else if(this.isWhite()) {
|
||||
} else if (this.isWhite()) {
|
||||
o1 = 5;
|
||||
}
|
||||
if (o.isMulticolored()) {
|
||||
o2 = 6;
|
||||
} else if(o.isColorless()) {
|
||||
} else if (o.isColorless()) {
|
||||
o2 = 0;
|
||||
} else if(o.isBlack()) {
|
||||
} else if (o.isBlack()) {
|
||||
o2 = 1;
|
||||
} else if(o.isBlue()) {
|
||||
} else if (o.isBlue()) {
|
||||
o2 = 2;
|
||||
} else if(o.isGreen()) {
|
||||
} else if (o.isGreen()) {
|
||||
o2 = 3;
|
||||
} else if(o.isRed()) {
|
||||
} else if (o.isRed()) {
|
||||
o2 = 4;
|
||||
} else if(o.isWhite()) {
|
||||
} else if (o.isWhite()) {
|
||||
o2 = 5;
|
||||
}
|
||||
return o1 - o2;
|
||||
|
|
|
|||
|
|
@ -872,9 +872,13 @@ public abstract class AbilityImpl implements Ability {
|
|||
|
||||
@Override
|
||||
public boolean canChooseTarget(Game game) {
|
||||
int found = 0;
|
||||
for (Mode mode : modes.values()) {
|
||||
if (mode.getTargets().canChoose(sourceId, controllerId, game)) {
|
||||
return true;
|
||||
found++;
|
||||
if (found >= getModes().getMinModes()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -47,9 +47,10 @@ import mage.game.permanent.Permanent;
|
|||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*
|
||||
*
|
||||
* This class uses ConcurrentHashMap to avoid ConcurrentModificationExceptions.
|
||||
* See ticket https://github.com/magefree/mage/issues/966 and https://github.com/magefree/mage/issues/473
|
||||
* See ticket https://github.com/magefree/mage/issues/966 and
|
||||
* https://github.com/magefree/mage/issues/473
|
||||
*/
|
||||
public class TriggeredAbilities extends ConcurrentHashMap<String, TriggeredAbility> {
|
||||
|
||||
|
|
@ -100,7 +101,6 @@ public class TriggeredAbilities extends ConcurrentHashMap<String, TriggeredAbili
|
|||
}
|
||||
}
|
||||
|
||||
// ability.setSourceObject(object);
|
||||
if (ability.checkTrigger(event, game)) {
|
||||
ability.trigger(game, ability.getControllerId());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge
|
|||
public void trigger(Game game, UUID controllerId) {
|
||||
//20091005 - 603.4
|
||||
if (checkInterveningIfClause(game)) {
|
||||
setSourceObject(null, game); // set the source object the time the trigger goes off
|
||||
setSourceObject(null, game);
|
||||
game.addTriggeredAbility(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,96 +1,95 @@
|
|||
/*
|
||||
* 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 mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
||||
public class BecomesBlockedAllTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
private FilterCreaturePermanent filter;
|
||||
private boolean setTargetPointer;
|
||||
|
||||
public BecomesBlockedAllTriggeredAbility(Effect effect, boolean optional) {
|
||||
this(effect, optional, new FilterCreaturePermanent("a creature"), false);
|
||||
}
|
||||
public BecomesBlockedAllTriggeredAbility(Effect effect, boolean optional, FilterCreaturePermanent filter, boolean setTargetPointer) {
|
||||
super(Zone.BATTLEFIELD, effect, optional);
|
||||
this.filter = filter;
|
||||
this.setTargetPointer = setTargetPointer;
|
||||
}
|
||||
|
||||
public BecomesBlockedAllTriggeredAbility(final BecomesBlockedAllTriggeredAbility ability) {
|
||||
super(ability);
|
||||
this.filter = ability.filter;
|
||||
this.setTargetPointer = ability.setTargetPointer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.CREATURE_BLOCKED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
Permanent permanent = game.getPermanent(event.getTargetId());
|
||||
if (permanent != null && filter.match(permanent, getSourceId(), getControllerId(), game)) {
|
||||
if (setTargetPointer) {
|
||||
for(Effect effect :this.getEffects()) {
|
||||
effect.setTargetPointer(new FixedTarget(event.getTargetId()));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
StringBuilder sb = new StringBuilder("Whenever ").append(filter.getMessage());
|
||||
sb.append(" becomes blocked, ").append(super.getRule());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BecomesBlockedAllTriggeredAbility copy() {
|
||||
return new BecomesBlockedAllTriggeredAbility(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.abilities.common;
|
||||
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
||||
public class BecomesBlockedAllTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
private FilterCreaturePermanent filter;
|
||||
private boolean setTargetPointer;
|
||||
|
||||
public BecomesBlockedAllTriggeredAbility(Effect effect, boolean optional) {
|
||||
this(effect, optional, new FilterCreaturePermanent("a creature"), false);
|
||||
}
|
||||
public BecomesBlockedAllTriggeredAbility(Effect effect, boolean optional, FilterCreaturePermanent filter, boolean setTargetPointer) {
|
||||
super(Zone.BATTLEFIELD, effect, optional);
|
||||
this.filter = filter;
|
||||
this.setTargetPointer = setTargetPointer;
|
||||
}
|
||||
|
||||
public BecomesBlockedAllTriggeredAbility(final BecomesBlockedAllTriggeredAbility ability) {
|
||||
super(ability);
|
||||
this.filter = ability.filter;
|
||||
this.setTargetPointer = ability.setTargetPointer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.CREATURE_BLOCKED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
Permanent permanent = game.getPermanent(event.getTargetId());
|
||||
if (permanent != null && filter.match(permanent, getSourceId(), getControllerId(), game)) {
|
||||
if (setTargetPointer) {
|
||||
for(Effect effect :this.getEffects()) {
|
||||
effect.setTargetPointer(new FixedTarget(event.getTargetId()));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
StringBuilder sb = new StringBuilder("Whenever ").append(filter.getMessage());
|
||||
sb.append(" becomes blocked, ").append(super.getRule());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BecomesBlockedAllTriggeredAbility copy() {
|
||||
return new BecomesBlockedAllTriggeredAbility(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,28 +15,27 @@ import mage.game.events.GameEvent;
|
|||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
||||
public class BecomesRenownSourceTriggeredAbility extends TriggeredAbilityImpl {
|
||||
public class BecomesRenownedSourceTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
private int renownValue;
|
||||
|
||||
public BecomesRenownSourceTriggeredAbility(Effect effect, boolean optional) {
|
||||
public BecomesRenownedSourceTriggeredAbility(Effect effect, boolean optional) {
|
||||
super(Zone.BATTLEFIELD, effect, optional);
|
||||
}
|
||||
|
||||
public BecomesRenownSourceTriggeredAbility(final BecomesRenownSourceTriggeredAbility ability) {
|
||||
public BecomesRenownedSourceTriggeredAbility(final BecomesRenownedSourceTriggeredAbility ability) {
|
||||
super(ability);
|
||||
this.renownValue = ability.renownValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BecomesRenownSourceTriggeredAbility copy() {
|
||||
return new BecomesRenownSourceTriggeredAbility(this);
|
||||
public BecomesRenownedSourceTriggeredAbility copy() {
|
||||
return new BecomesRenownedSourceTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.BECOMES_RENOWN;
|
||||
return event.getType() == GameEvent.EventType.BECOMES_RENOWNED;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -54,6 +53,6 @@ public class BecomesRenownSourceTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "When {this} becomes monstrous, " + super.getRule();
|
||||
return "When {this} becomes renowned, " + super.getRule();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package mage.abilities.common;
|
||||
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.SpellAbilityType;
|
||||
import mage.constants.TimingRule;
|
||||
import mage.constants.Zone;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class PayMoreToCastAsThoughtItHadFlashAbility extends SpellAbility {
|
||||
|
||||
private final ManaCosts costsToAdd;
|
||||
|
||||
public PayMoreToCastAsThoughtItHadFlashAbility(Card card, ManaCosts costsToAdd) {
|
||||
super(card.getSpellAbility().getManaCosts().copy(), card.getName() + " as though it had flash", Zone.HAND, SpellAbilityType.BASE_ALTERNATE);
|
||||
this.costsToAdd = costsToAdd;
|
||||
this.timing = TimingRule.INSTANT;
|
||||
|
||||
CardUtil.increaseCost(this, costsToAdd);
|
||||
}
|
||||
|
||||
public PayMoreToCastAsThoughtItHadFlashAbility(final PayMoreToCastAsThoughtItHadFlashAbility ability) {
|
||||
super(ability);
|
||||
this.costsToAdd = ability.costsToAdd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayMoreToCastAsThoughtItHadFlashAbility copy() {
|
||||
return new PayMoreToCastAsThoughtItHadFlashAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule(boolean all) {
|
||||
return getRule();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "You may cast {this} as though it had flash if you pay " + costsToAdd.getText() + " more to cast it. <i>(You may cast it any time you could cast an instant)</i>";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -2,8 +2,10 @@ package mage.abilities.condition.common;
|
|||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
* Condition for - Controller has X or more cards in his or her graveyard
|
||||
|
|
@ -13,14 +15,31 @@ import mage.players.Player;
|
|||
public class CardsInControllerGraveCondition implements Condition {
|
||||
|
||||
private final int value;
|
||||
private final FilterCard filter;
|
||||
|
||||
public CardsInControllerGraveCondition(int value) {
|
||||
this(value, null);
|
||||
}
|
||||
|
||||
public CardsInControllerGraveCondition(int value, FilterCard filter) {
|
||||
this.value = value;
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (filter != null) {
|
||||
return player != null && player.getGraveyard().count(filter, source.getSourceId(), source.getControllerId(), game) >= value;
|
||||
}
|
||||
return player != null && player.getGraveyard().size() >= value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "there are " + CardUtil.numberToText(value, "one") + " or more "
|
||||
+ (filter == null ? "cards" : filter.getMessage())
|
||||
+ " in your graveyard";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,15 +16,15 @@ import mage.game.permanent.Permanent;
|
|||
* @author LevelX2
|
||||
*/
|
||||
|
||||
public class RenownCondition implements Condition {
|
||||
public class RenownedSourceCondition implements Condition {
|
||||
|
||||
private static RenownCondition fInstance = null;
|
||||
private static RenownedSourceCondition fInstance = null;
|
||||
|
||||
private RenownCondition() {}
|
||||
private RenownedSourceCondition() {}
|
||||
|
||||
public static RenownCondition getInstance() {
|
||||
public static RenownedSourceCondition getInstance() {
|
||||
if (fInstance == null) {
|
||||
fInstance = new RenownCondition();
|
||||
fInstance = new RenownedSourceCondition();
|
||||
}
|
||||
return fInstance;
|
||||
}
|
||||
|
|
@ -33,7 +33,7 @@ public class RenownCondition implements Condition {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null) {
|
||||
return permanent.isRenown();
|
||||
return permanent.isRenowned();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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.condition.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class RenownedTargetCondition implements Condition {
|
||||
|
||||
private static RenownedTargetCondition fInstance = null;
|
||||
|
||||
private RenownedTargetCondition() {
|
||||
}
|
||||
|
||||
public static RenownedTargetCondition getInstance() {
|
||||
if (fInstance == null) {
|
||||
fInstance = new RenownedTargetCondition();
|
||||
}
|
||||
return fInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(source.getTargets().getFirstTarget());
|
||||
if (permanent != null) {
|
||||
return permanent.isRenowned();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "it's renowned";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -207,7 +207,7 @@ public class AlternativeCostSourceAbility extends StaticAbility implements Alter
|
|||
|
||||
@Override
|
||||
public String getCastMessageSuffix(Game game) {
|
||||
return alternateCosts.isEmpty() ? " without paying it's mana costs" : " using alternative casting costs";
|
||||
return alternateCosts.isEmpty() ? " without paying its mana costs" : " using alternative casting costs";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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.costs.common;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.CostImpl;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author markedagain
|
||||
*/
|
||||
public class ReturnToHandFromGraveyardCost extends CostImpl {
|
||||
|
||||
public ReturnToHandFromGraveyardCost(TargetCardInYourGraveyard target) {
|
||||
this.addTarget(target);
|
||||
if (target.getMaxNumberOfTargets() > 1 && target.getMaxNumberOfTargets() == target.getNumberOfTargets()) {
|
||||
this.text = new StringBuilder("return ").append(target.getMaxNumberOfTargets()).append(" ").append(target.getTargetName()).append(" from graveyard to it's owner's hand").toString();
|
||||
} else {
|
||||
this.text = new StringBuilder("return ").append(target.getTargetName()).append(" from graveyard to it's owner's hand").toString();
|
||||
}
|
||||
}
|
||||
public ReturnToHandFromGraveyardCost(ReturnToHandFromGraveyardCost cost) {
|
||||
super(cost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) {
|
||||
Player controller = game.getPlayer(controllerId);
|
||||
if (controller != null) {
|
||||
if (targets.choose(Outcome.ReturnToHand, controllerId, sourceId, game)) {
|
||||
for (UUID targetId: targets.get(0).getTargets()) {
|
||||
mage.cards.Card targetCard = game.getCard(targetId);
|
||||
if (targetCard == null) {
|
||||
return false;
|
||||
}
|
||||
paid |= controller.moveCardToHandWithInfo(targetCard, sourceId, game, Zone.HAND);
|
||||
}
|
||||
}
|
||||
}
|
||||
return paid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
|
||||
return targets.canChoose(controllerId, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnToHandFromGraveyardCost copy() {
|
||||
return new ReturnToHandFromGraveyardCost(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
/*
|
||||
* 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
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
* 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.
|
||||
|
|
@ -42,7 +42,7 @@ import mage.game.permanent.Permanent;
|
|||
public class ReturnToHandSourceCost extends CostImpl {
|
||||
|
||||
public ReturnToHandSourceCost() {
|
||||
this.text = "return {this} to it's owner's hand";
|
||||
this.text = "return {this} to its owner's hand";
|
||||
}
|
||||
|
||||
public ReturnToHandSourceCost(ReturnToHandSourceCost cost) {
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
/*
|
||||
* 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
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
* 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.
|
||||
|
|
@ -47,9 +47,9 @@ public class ReturnToHandTargetPermanentCost extends CostImpl {
|
|||
public ReturnToHandTargetPermanentCost(TargetControlledPermanent target) {
|
||||
this.addTarget(target);
|
||||
if (target.getMaxNumberOfTargets() > 1 && target.getMaxNumberOfTargets() == target.getNumberOfTargets()) {
|
||||
this.text = new StringBuilder("return ").append(target.getMaxNumberOfTargets()).append(" ").append(target.getTargetName()).append(" you control to it's owner's hand").toString();
|
||||
this.text = new StringBuilder("return ").append(target.getMaxNumberOfTargets()).append(" ").append(target.getTargetName()).append(" you control to its owner's hand").toString();
|
||||
} else {
|
||||
this.text = new StringBuilder("return ").append(target.getTargetName()).append(" you control to it's owner's hand").toString();
|
||||
this.text = new StringBuilder("return ").append(target.getTargetName()).append(" you control to its owner's hand").toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package mage.abilities.decorator;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.TriggeredAbility;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.condition.Condition;
|
||||
|
|
@ -9,7 +8,8 @@ import mage.game.Game;
|
|||
import mage.game.events.GameEvent;
|
||||
|
||||
/**
|
||||
* Adds condition to {@link mage.abilities.effects.ContinuousEffect}. Acts as decorator.
|
||||
* Adds condition to {@link mage.abilities.effects.ContinuousEffect}. Acts as
|
||||
* decorator.
|
||||
*
|
||||
* @author nantuko
|
||||
*/
|
||||
|
|
@ -19,7 +19,7 @@ public class ConditionalTriggeredAbility extends TriggeredAbilityImpl {
|
|||
protected Condition condition;
|
||||
protected String text;
|
||||
|
||||
public ConditionalTriggeredAbility(TriggeredAbility ability, Condition condition, String text) {
|
||||
public ConditionalTriggeredAbility(TriggeredAbility ability, Condition condition, String text) {
|
||||
this(ability, condition, text, false);
|
||||
}
|
||||
|
||||
|
|
@ -39,7 +39,6 @@ public class ConditionalTriggeredAbility extends TriggeredAbilityImpl {
|
|||
this.text = triggered.text;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean checkInterveningIfClause(Game game) {
|
||||
return condition.apply(game, this);
|
||||
|
|
@ -64,7 +63,7 @@ public class ConditionalTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
@Override
|
||||
public String getRule() {
|
||||
if (text == null || text.isEmpty()) {
|
||||
if (text == null || text.isEmpty()) {
|
||||
return ability.getRule();
|
||||
}
|
||||
return text;
|
||||
|
|
@ -75,21 +74,4 @@ public class ConditionalTriggeredAbility extends TriggeredAbilityImpl {
|
|||
return ability.getEffects();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MageObject getSourceObjectIfItStillExists(Game game) {
|
||||
return ability.getSourceObjectIfItStillExists(game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MageObject getSourceObject(Game game) {
|
||||
return ability.getSourceObject(game);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int getSourceObjectZoneChangeCounter() {
|
||||
return ability.getSourceObjectZoneChangeCounter();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -214,12 +214,16 @@ public class ContinuousEffects implements Serializable {
|
|||
case WhileOnStack:
|
||||
case WhileInGraveyard:
|
||||
HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
// If e.g. triggerd abilities (non static) created the effect, the ability must not be in usable zone (e.g. Unearth giving Haste effect)
|
||||
if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, null)) {
|
||||
layerEffects.add(effect);
|
||||
break;
|
||||
if (abilities != null) {
|
||||
for (Ability ability : abilities) {
|
||||
// If e.g. triggerd abilities (non static) created the effect, the ability must not be in usable zone (e.g. Unearth giving Haste effect)
|
||||
if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, null)) {
|
||||
layerEffects.add(effect);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.error("No abilities for continuous effect: " + effect.toString());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
@ -336,7 +340,8 @@ public class ContinuousEffects implements Serializable {
|
|||
if (ability.getAbilityType() != AbilityType.STATIC || ability.isInUseableZone(game, null, event)) {
|
||||
if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) {
|
||||
if (!game.getScopeRelevant() || effect.hasSelfScope() || !event.getTargetId().equals(ability.getSourceId())) {
|
||||
if (effect.applies(event, ability, game)) {
|
||||
if (effect.applies(event, ability, game)
|
||||
&& !((PayCostToAttackBlockEffect) effect).isCostless(event, ability, game)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1057,14 +1062,16 @@ public class ContinuousEffects implements Serializable {
|
|||
private void setControllerForEffect(ContinuousEffectsList<?> effects, UUID cardId, UUID controllerId) {
|
||||
for (Effect effect : effects) {
|
||||
HashSet<Ability> abilities = effects.getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
if (ability.getSourceId() != null) {
|
||||
if (ability.getSourceId().equals(cardId)) {
|
||||
ability.setControllerId(controllerId);
|
||||
}
|
||||
} else {
|
||||
if (!ability.getZone().equals(Zone.COMMAND)) {
|
||||
logger.fatal(new StringBuilder("No sourceId Ability: ").append(ability));
|
||||
if (abilities != null) {
|
||||
for (Ability ability : abilities) {
|
||||
if (ability.getSourceId() != null) {
|
||||
if (ability.getSourceId().equals(cardId)) {
|
||||
ability.setControllerId(controllerId);
|
||||
}
|
||||
} else {
|
||||
if (!ability.getZone().equals(Zone.COMMAND)) {
|
||||
logger.fatal(new StringBuilder("No sourceId Ability: ").append(ability));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,4 +42,6 @@ public interface PayCostToAttackBlockEffect extends ReplacementEffect {
|
|||
ManaCosts getManaCostToPay(GameEvent event, Ability source, Game game);
|
||||
|
||||
Cost getOtherCostToPay(GameEvent event, Ability source, Game game);
|
||||
|
||||
boolean isCostless(GameEvent event, Ability source, Game game);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,13 +46,26 @@ public abstract class PayCostToAttackBlockEffectImpl extends ReplacementEffectIm
|
|||
|
||||
public static enum RestrictType {
|
||||
|
||||
ATTACK, ATTACK_AND_BLOCK, BLOCK
|
||||
ATTACK("attack"),
|
||||
ATTACK_AND_BLOCK("attack or block"),
|
||||
BLOCK("block");
|
||||
|
||||
private final String text;
|
||||
|
||||
RestrictType(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
private final Cost cost;
|
||||
private final ManaCosts manaCosts;
|
||||
protected final Cost cost;
|
||||
protected final ManaCosts manaCosts;
|
||||
|
||||
private final RestrictType restrictType;
|
||||
protected final RestrictType restrictType;
|
||||
|
||||
public PayCostToAttackBlockEffectImpl(Duration duration, Outcome outcome, RestrictType restrictType) {
|
||||
super(duration, outcome, false);
|
||||
|
|
@ -165,4 +178,13 @@ public abstract class PayCostToAttackBlockEffectImpl extends ReplacementEffectIm
|
|||
return manaCosts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCostless(GameEvent event, Ability source, Game game) {
|
||||
ManaCosts currentManaCosts = getManaCostToPay(event, source, game);
|
||||
if (currentManaCosts != null && currentManaCosts.convertedManaCost() > 0) {
|
||||
return false;
|
||||
}
|
||||
return getOtherCostToPay(event, source, game) == null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,38 +1,36 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
* 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.constants.Outcome;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.Spell;
|
||||
|
|
@ -82,8 +80,11 @@ public class CopyTargetSpellEffect extends OneShotEffect {
|
|||
return new CopyTargetSpellEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public String getText(Mode mode) {
|
||||
if (staticText != null && !staticText.isEmpty()) {
|
||||
return staticText;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("copy target ").append(mode.getTargets().get(0).getTargetName()).append(". You may choose new targets for the copy");
|
||||
return sb.toString();
|
||||
|
|
|
|||
|
|
@ -1,31 +1,30 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
* 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 java.util.UUID;
|
||||
|
|
@ -50,9 +49,10 @@ public class DontUntapInControllersNextUntapStepTargetEffect extends ContinuousR
|
|||
private String targetName;
|
||||
|
||||
/**
|
||||
* Attention: This effect won't work with targets controlled by different controllers
|
||||
* If this is needed, the validForTurnNum has to be saved per controller.
|
||||
*
|
||||
* Attention: This effect won't work with targets controlled by different
|
||||
* controllers If this is needed, the validForTurnNum has to be saved per
|
||||
* controller.
|
||||
*
|
||||
*/
|
||||
public DontUntapInControllersNextUntapStepTargetEffect() {
|
||||
super(Duration.Custom, Outcome.Detriment, false, true);
|
||||
|
|
@ -94,13 +94,13 @@ public class DontUntapInControllersNextUntapStepTargetEffect extends ContinuousR
|
|||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == EventType.UNTAP_STEP || event.getType() == EventType.UNTAP;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
// the check for turn number is needed if multiple effects are added to prevent untap in next untap step of controller
|
||||
// if we don't check for turn number, every untap step of a turn only one effect would be used instead of correctly only one time
|
||||
// to skip the untap effect.
|
||||
|
||||
|
||||
// Discard effect if it's related to a previous turn
|
||||
if (validForTurnNum > 0 && validForTurnNum < game.getTurnNum()) {
|
||||
discard();
|
||||
|
|
@ -109,7 +109,7 @@ public class DontUntapInControllersNextUntapStepTargetEffect extends ContinuousR
|
|||
// remember the turn of the untap step the effect has to be applied
|
||||
if (GameEvent.EventType.UNTAP_STEP.equals(event.getType())) {
|
||||
UUID controllerId = null;
|
||||
for(UUID targetId : getTargetPointer().getTargets(game, source)) {
|
||||
for (UUID targetId : getTargetPointer().getTargets(game, source)) {
|
||||
Permanent permanent = game.getPermanent(targetId);
|
||||
if (permanent != null) {
|
||||
controllerId = permanent.getControllerId();
|
||||
|
|
@ -128,7 +128,7 @@ public class DontUntapInControllersNextUntapStepTargetEffect extends ContinuousR
|
|||
validForTurnNum = game.getTurnNum();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (game.getTurn().getStepType() == PhaseStep.UNTAP && event.getType() == EventType.UNTAP) {
|
||||
if (targetPointer.getTargets(game, source).contains(event.getTargetId())) {
|
||||
Permanent permanent = game.getPermanent(event.getTargetId());
|
||||
|
|
@ -147,9 +147,8 @@ public class DontUntapInControllersNextUntapStepTargetEffect extends ContinuousR
|
|||
}
|
||||
if (targetName != null && targetName.length() > 0) {
|
||||
return targetName + " doesn't untap during its controller's next untap step";
|
||||
}
|
||||
else {
|
||||
return "Target " + mode.getTargets().get(0).getTargetName() + " doesn't untap during its controller's next untap step";
|
||||
} else {
|
||||
return "Target " + (mode == null ? "creature" : mode.getTargets().get(0).getTargetName()) + " doesn't untap during its controller's next untap step";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,12 +25,11 @@
|
|||
* 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.constants.Outcome;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
|
||||
public class EndTurnEffect extends OneShotEffect {
|
||||
|
|
@ -46,8 +45,9 @@ public class EndTurnEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
if (!game.isSimulation())
|
||||
if (!game.isSimulation()) {
|
||||
game.informPlayers("The current turn ends");
|
||||
}
|
||||
return game.endTurn();
|
||||
}
|
||||
|
||||
|
|
@ -56,4 +56,3 @@ public class EndTurnEffect extends OneShotEffect {
|
|||
return new EndTurnEffect(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,49 +5,73 @@
|
|||
*/
|
||||
package mage.abilities.effects.common;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.keyword.TransformAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
||||
public class ExileAndReturnTransformedSourceEffect extends OneShotEffect {
|
||||
|
||||
public static enum Gender { MALE, FEMAL };
|
||||
|
||||
|
||||
public static enum Gender {
|
||||
|
||||
MALE, FEMAL
|
||||
};
|
||||
|
||||
protected Effect additionalEffect;
|
||||
|
||||
public ExileAndReturnTransformedSourceEffect(Gender gender) {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "exile {this}, then return " + (gender.equals(Gender.MALE) ? "him":"her")
|
||||
+ " to the battlefield transformed under" + (gender.equals(Gender.MALE) ? "his":"her")+ " owner's control";
|
||||
this(gender, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param gender
|
||||
* @param additionalEffect that effect is applies as source is exiled
|
||||
*/
|
||||
public ExileAndReturnTransformedSourceEffect(Gender gender, Effect additionalEffect) {
|
||||
super(Outcome.Benefit);
|
||||
this.additionalEffect = additionalEffect;
|
||||
this.staticText = "exile {this}, then return " + (gender.equals(Gender.MALE) ? "him" : "her")
|
||||
+ " to the battlefield transformed under" + (gender.equals(Gender.MALE) ? "his" : "her") + " owner's control";
|
||||
}
|
||||
|
||||
public ExileAndReturnTransformedSourceEffect(final ExileAndReturnTransformedSourceEffect effect) {
|
||||
super(effect);
|
||||
this.additionalEffect = effect.additionalEffect;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ExileAndReturnTransformedSourceEffect copy() {
|
||||
return new ExileAndReturnTransformedSourceEffect(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
MageObject sourceObject = source.getSourceObjectIfItStillExists(game);
|
||||
// Creature has to be on the battlefield to get exiled and be able to return transformed
|
||||
Permanent sourceObject = game.getPermanent(source.getSourceId());
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (sourceObject != null && controller != null) {
|
||||
Card card = (Card) sourceObject;
|
||||
if (controller.moveCards(card, Zone.BATTLEFIELD, Zone.EXILED, source, game)) {
|
||||
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
|
||||
controller.putOntoBattlefieldWithInfo(card, game, Zone.EXILED, source.getSourceId());
|
||||
if (additionalEffect != null) {
|
||||
if (additionalEffect instanceof ContinuousEffect) {
|
||||
game.addEffect((ContinuousEffect) additionalEffect, source);
|
||||
} else {
|
||||
additionalEffect.apply(game, source);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* 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.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class ExileReturnToBattlefieldOwnerNextEndStepEffect extends OneShotEffect {
|
||||
|
||||
private static final String effectText = "exile {this}. Return it to the battlefield under its owner's control at the beginning of the next end step";
|
||||
|
||||
public ExileReturnToBattlefieldOwnerNextEndStepEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = effectText;
|
||||
}
|
||||
|
||||
public ExileReturnToBattlefieldOwnerNextEndStepEffect(ExileReturnToBattlefieldOwnerNextEndStepEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null) {
|
||||
int zcc = game.getState().getZoneChangeCounter(permanent.getId());
|
||||
if (controller.moveCardToExileWithInfo(permanent, source.getSourceId(), permanent.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true)) {
|
||||
//create delayed triggered ability and return it from every public zone he was next moved to
|
||||
AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(
|
||||
new ReturnToBattlefieldUnderOwnerControlSourceEffect(false, zcc + 1));
|
||||
delayedAbility.setSourceId(source.getSourceId());
|
||||
delayedAbility.setControllerId(source.getControllerId());
|
||||
delayedAbility.setSourceObject(source.getSourceObject(game), game);
|
||||
game.addDelayedTriggeredAbility(delayedAbility);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExileReturnToBattlefieldOwnerNextEndStepEffect copy() {
|
||||
return new ExileReturnToBattlefieldOwnerNextEndStepEffect(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -82,7 +82,7 @@ public class HideawayPlayEffect extends OneShotEffect {
|
|||
// The land's last ability allows you to play the removed card as part of the resolution of that ability.
|
||||
// Timing restrictions based on the card's type are ignored (for instance, if it's a creature or sorcery).
|
||||
// Other play restrictions are not (such as "Play [this card] only during combat").
|
||||
if (controller.chooseUse(Outcome.Benefit, "Cast "+ card.getLogName() + " without paying it's mana cost?", source, game)) {
|
||||
if (controller.chooseUse(Outcome.Benefit, "Cast "+ card.getLogName() + " without paying its mana cost?", source, game)) {
|
||||
card.setFaceDown(false, game);
|
||||
return controller.cast(card.getSpellAbility(), game, true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package mage.abilities.effects.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.Outcome;
|
||||
|
|
@ -15,15 +16,20 @@ import mage.target.common.TargetCardInHand;
|
|||
*/
|
||||
public class PutCreatureOnBattlefieldEffect extends OneShotEffect {
|
||||
|
||||
private static final String choiceText = "Put a creature card from your hand onto the battlefield?";
|
||||
private final FilterCreatureCard filter;
|
||||
|
||||
public PutCreatureOnBattlefieldEffect() {
|
||||
this(new FilterCreatureCard("a creature card"));
|
||||
}
|
||||
|
||||
public PutCreatureOnBattlefieldEffect(FilterCreatureCard filter) {
|
||||
super(Outcome.PutCreatureInPlay);
|
||||
this.staticText = "You may put a creature card from your hand onto the battlefield";
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
public PutCreatureOnBattlefieldEffect(final PutCreatureOnBattlefieldEffect effect) {
|
||||
super(effect);
|
||||
this.filter = effect.filter.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -34,11 +40,12 @@ public class PutCreatureOnBattlefieldEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
String choiceText = "Put " + filter.getMessage() + " from your hand onto the battlefield?";
|
||||
if (player == null || !player.chooseUse(Outcome.PutCreatureInPlay, choiceText, source, game)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TargetCardInHand target = new TargetCardInHand(new FilterCreatureCard());
|
||||
TargetCardInHand target = new TargetCardInHand(filter);
|
||||
if (player.choose(Outcome.PutCreatureInPlay, target, source.getSourceId(), game)) {
|
||||
Card card = game.getCard(target.getFirstTarget());
|
||||
if (card != null) {
|
||||
|
|
@ -48,4 +55,13 @@ public class PutCreatureOnBattlefieldEffect extends OneShotEffect {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(Mode mode) {
|
||||
if(this.staticText != null && !this.staticText.isEmpty()) {
|
||||
return staticText;
|
||||
}
|
||||
|
||||
return "You may put " + filter.getMessage() + " from your hand onto the battlefield";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ public class PutOnLibrarySourceEffect extends OneShotEffect {
|
|||
} else {
|
||||
// Put Champion of Stray Souls on top of your library from your graveyard
|
||||
sb.append("put {this} on ");
|
||||
sb.append(onTop ? "top" : "the bottom").append(" of it's owner's library");
|
||||
sb.append(onTop ? "top" : "the bottom").append(" of its owner's library");
|
||||
}
|
||||
return sb.toString();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
/*
|
||||
* 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
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
* 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.
|
||||
|
|
@ -147,7 +147,7 @@ public class PutOnLibraryTargetEffect extends OneShotEffect {
|
|||
if (this.staticText != null && !this.staticText.isEmpty()) {
|
||||
return staticText;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Target target = mode.getTargets().get(0);
|
||||
sb.append("Put ");
|
||||
if (target.getMaxNumberOfTargets() == 0) {
|
||||
|
|
@ -161,8 +161,8 @@ public class PutOnLibraryTargetEffect extends OneShotEffect {
|
|||
}
|
||||
}
|
||||
sb.append("target ").append(mode.getTargets().get(0).getTargetName()).append(" on ");
|
||||
sb.append(onTop ? "top" : "the bottom").append(" of it's owner's library");
|
||||
|
||||
sb.append(onTop ? "top" : "the bottom").append(" of its owner's library");
|
||||
|
||||
return sb.toString();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,15 +25,12 @@
|
|||
* 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.cards.Card;
|
||||
import mage.cards.Cards;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
|
|
@ -43,7 +40,6 @@ import mage.util.CardUtil;
|
|||
/**
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
||||
public class PutTopCardOfLibraryIntoGraveTargetEffect extends OneShotEffect {
|
||||
|
||||
private DynamicValue numberCards;
|
||||
|
|
@ -51,6 +47,7 @@ public class PutTopCardOfLibraryIntoGraveTargetEffect extends OneShotEffect {
|
|||
public PutTopCardOfLibraryIntoGraveTargetEffect(int numberCards) {
|
||||
this(new StaticValue(numberCards));
|
||||
}
|
||||
|
||||
public PutTopCardOfLibraryIntoGraveTargetEffect(DynamicValue numberCards) {
|
||||
super(Outcome.Discard);
|
||||
this.numberCards = numberCards;
|
||||
|
|
|
|||
|
|
@ -25,12 +25,11 @@
|
|||
* 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.constants.Outcome;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
|
@ -40,10 +39,9 @@ import mage.target.targetpointer.FixedTarget;
|
|||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class RegenerateAllEffect extends OneShotEffect {
|
||||
|
||||
public class RegenerateAllEffect extends OneShotEffect {
|
||||
|
||||
private FilterPermanent filter;
|
||||
private final FilterPermanent filter;
|
||||
|
||||
public RegenerateAllEffect(FilterPermanent filter) {
|
||||
super(Outcome.DestroyPermanent);
|
||||
|
|
|
|||
|
|
@ -1,35 +1,32 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
* 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 java.util.LinkedList;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
|
|
@ -41,6 +38,7 @@ import static mage.constants.Zone.GRAVEYARD;
|
|||
import static mage.constants.Zone.HAND;
|
||||
import mage.game.ExileZone;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.PermanentToken;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
|
|
@ -55,7 +53,7 @@ public class ReturnFromExileForSourceEffect extends OneShotEffect {
|
|||
private boolean previousZone;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param zone Zone the card should return to
|
||||
*/
|
||||
public ReturnFromExileForSourceEffect(Zone zone) {
|
||||
|
|
@ -65,12 +63,13 @@ public class ReturnFromExileForSourceEffect extends OneShotEffect {
|
|||
public ReturnFromExileForSourceEffect(Zone zone, boolean tapped) {
|
||||
this(zone, tapped, true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param zone
|
||||
* @param tapped
|
||||
* @param previousZone if this is used from a dies leave battlefield or destroyed trigger, the exile zone is based on previous zone of the object
|
||||
* @param previousZone if this is used from a dies leave battlefield or
|
||||
* destroyed trigger, the exile zone is based on previous zone of the object
|
||||
*/
|
||||
public ReturnFromExileForSourceEffect(Zone zone, boolean tapped, boolean previousZone) {
|
||||
super(Outcome.PutCardInPlay);
|
||||
|
|
@ -94,24 +93,25 @@ public class ReturnFromExileForSourceEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
int zoneChangeCounter = source.getSourceObjectZoneChangeCounter() - (previousZone ? 1:0);
|
||||
UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), zoneChangeCounter);
|
||||
ExileZone exile = game.getExile().getExileZone(exileId);
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (sourceObject != null && controller != null) {
|
||||
int zoneChangeCounter = source.getSourceObjectZoneChangeCounter();
|
||||
if (zoneChangeCounter > 0 && previousZone && !(sourceObject instanceof PermanentToken)) {
|
||||
zoneChangeCounter--;
|
||||
}
|
||||
ExileZone exile = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source.getSourceId(), zoneChangeCounter));
|
||||
if (exile != null) { // null is valid if source left battlefield before enters the battlefield effect resolved
|
||||
LinkedList<UUID> cards = new LinkedList<>(exile);
|
||||
for (UUID cardId: cards) {
|
||||
Card card = game.getCard(cardId);
|
||||
if (card == null) {
|
||||
return false;
|
||||
if (returnToZone.equals(Zone.BATTLEFIELD)) {
|
||||
for (Card card : exile.getCards(game)) {
|
||||
Player owner = game.getPlayer(card.getOwnerId());
|
||||
if (owner != null) {
|
||||
owner.putOntoBattlefieldWithInfo(card, game, Zone.EXILED, source.getSourceId());
|
||||
}
|
||||
}
|
||||
if (!game.isSimulation()) {
|
||||
game.informPlayers(controller.getLogName() + " moves " + card.getLogName() + " from exile to " + returnToZone.toString().toLowerCase());
|
||||
}
|
||||
card.moveToZone(returnToZone, source.getSourceId(), game, tapped);
|
||||
} else {
|
||||
controller.moveCards(exile, Zone.EXILED, returnToZone, source, game);
|
||||
}
|
||||
exile.clear();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -121,7 +121,7 @@ public class ReturnFromExileForSourceEffect extends OneShotEffect {
|
|||
private void setText() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("return the exiled cards ");
|
||||
switch(returnToZone) {
|
||||
switch (returnToZone) {
|
||||
case BATTLEFIELD:
|
||||
sb.append("to the battlefield under its owner's control");
|
||||
if (tapped) {
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
/*
|
||||
* 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
|
||||
|
|
@ -20,12 +20,11 @@
|
|||
* 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 java.util.UUID;
|
||||
|
|
@ -69,18 +68,12 @@ public class ReturnFromGraveyardToBattlefieldTargetEffect extends OneShotEffect
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player != null) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
for (UUID targetId : getTargetPointer().getTargets(game, source)) {
|
||||
Card card = game.getCard(targetId);
|
||||
if (card != null) {
|
||||
if (player.putOntoBattlefieldWithInfo(card, game, Zone.GRAVEYARD, source.getSourceId(), tapped)) {
|
||||
// why is this neccessary - it contradicts Gather Specimens in play
|
||||
// Permanent permanent = game.getPermanent(targetId);
|
||||
// if (permanent != null) {
|
||||
// permanent.changeControllerId(source.getControllerId(), game);
|
||||
// }
|
||||
}
|
||||
controller.putOntoBattlefieldWithInfo(card, game, Zone.GRAVEYARD, source.getSourceId(), tapped);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
* 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;
|
||||
|
|
@ -42,20 +41,27 @@ import mage.game.Game;
|
|||
public class ReturnToBattlefieldUnderOwnerControlSourceEffect extends OneShotEffect {
|
||||
|
||||
private boolean tapped;
|
||||
private int zoneChangeCounter;
|
||||
|
||||
public ReturnToBattlefieldUnderOwnerControlSourceEffect() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
public ReturnToBattlefieldUnderOwnerControlSourceEffect(boolean tapped) {
|
||||
this(tapped, -1);
|
||||
}
|
||||
|
||||
public ReturnToBattlefieldUnderOwnerControlSourceEffect(boolean tapped, int zoneChangeCounter) {
|
||||
super(Outcome.Benefit);
|
||||
this.tapped = tapped;
|
||||
staticText = new StringBuilder("return that card to the battlefield").append(tapped?" tapped":"").append(" under it's owner's control").toString();
|
||||
this.zoneChangeCounter = zoneChangeCounter;
|
||||
staticText = new StringBuilder("return that card to the battlefield").append(tapped ? " tapped" : "").append(" under its owner's control").toString();
|
||||
}
|
||||
|
||||
public ReturnToBattlefieldUnderOwnerControlSourceEffect(final ReturnToBattlefieldUnderOwnerControlSourceEffect effect) {
|
||||
super(effect);
|
||||
this.tapped = effect.tapped;
|
||||
this.zoneChangeCounter = effect.zoneChangeCounter;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -67,12 +73,19 @@ public class ReturnToBattlefieldUnderOwnerControlSourceEffect extends OneShotEff
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Card card = game.getCard(source.getSourceId());
|
||||
if (card != null) {
|
||||
Zone currentZone = game.getState().getZone(card.getId());
|
||||
if (card.putOntoBattlefield(game, currentZone, source.getSourceId(), card.getOwnerId(),tapped)) {
|
||||
return true;
|
||||
// return only from public zones
|
||||
switch (game.getState().getZone(card.getId())) {
|
||||
case EXILED:
|
||||
case COMMAND:
|
||||
case GRAVEYARD:
|
||||
if (zoneChangeCounter < 0 || game.getState().getZoneChangeCounter(card.getId()) == zoneChangeCounter) {
|
||||
Zone currentZone = game.getState().getZone(card.getId());
|
||||
card.putOntoBattlefield(game, currentZone, source.getSourceId(), card.getOwnerId(), tapped);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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 java.util.List;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LoneFox
|
||||
*/
|
||||
public class TapAllTargetPlayerControlsEffect extends OneShotEffect {
|
||||
|
||||
private FilterPermanent filter;
|
||||
|
||||
public TapAllTargetPlayerControlsEffect(FilterPermanent filter) {
|
||||
super(Outcome.Tap);
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
public TapAllTargetPlayerControlsEffect(final TapAllTargetPlayerControlsEffect effect) {
|
||||
super(effect);
|
||||
filter = effect.filter.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(targetPointer.getFirst(game, source));
|
||||
if(player != null) {
|
||||
filter.add(new ControllerIdPredicate(player.getId()));
|
||||
List<Permanent> permanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game);
|
||||
for(Permanent p : permanents) {
|
||||
p.tap(game);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TapAllTargetPlayerControlsEffect copy() {
|
||||
return new TapAllTargetPlayerControlsEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(Mode mode) {
|
||||
if(staticText != null && !staticText.isEmpty()) {
|
||||
return staticText;
|
||||
}
|
||||
return "tap all " + filter.getMessage() + " target player controls";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* 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.combat;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
import mage.abilities.effects.PayCostToAttackBlockEffectImpl;
|
||||
import mage.abilities.effects.PayCostToAttackBlockEffectImpl.RestrictType;
|
||||
import mage.constants.AttachmentType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class CantAttackBlockUnlessPaysAttachedEffect extends PayCostToAttackBlockEffectImpl {
|
||||
|
||||
public CantAttackBlockUnlessPaysAttachedEffect(ManaCosts manaCosts, AttachmentType attachmentType) {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Detriment, RestrictType.ATTACK_AND_BLOCK, manaCosts);
|
||||
staticText = (attachmentType.equals(AttachmentType.AURA) ? "Enchanted " : "Equipped ")
|
||||
+ "creature can't attack or block unless its controller pays "
|
||||
+ (manaCosts == null ? "" : manaCosts.getText());
|
||||
}
|
||||
|
||||
public CantAttackBlockUnlessPaysAttachedEffect(CantAttackBlockUnlessPaysAttachedEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
Permanent enchantment = game.getPermanent(source.getSourceId());
|
||||
if (enchantment != null && enchantment.getAttachedTo() != null) {
|
||||
if (event.getType().equals(EventType.DECLARE_ATTACKER)) {
|
||||
return event.getSourceId().equals(enchantment.getAttachedTo());
|
||||
}
|
||||
if (event.getType().equals(EventType.DECLARE_BLOCKER)) {
|
||||
return event.getSourceId().equals(enchantment.getAttachedTo());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CantAttackBlockUnlessPaysAttachedEffect copy() {
|
||||
return new CantAttackBlockUnlessPaysAttachedEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* 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.combat;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
import mage.abilities.effects.PayCostToAttackBlockEffectImpl;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class CantAttackBlockUnlessPaysSourceEffect extends PayCostToAttackBlockEffectImpl {
|
||||
|
||||
public CantAttackBlockUnlessPaysSourceEffect(Cost cost, RestrictType restrictType) {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Detriment, restrictType, cost);
|
||||
staticText = "{this} can't " + restrictType.toString() + " unless you "
|
||||
+ cost == null ? "" : cost.getText()
|
||||
+ (restrictType.equals(RestrictType.ATTACK) ? " <i>(This cost is paid as attackers are declared.)</i>" : "");
|
||||
}
|
||||
|
||||
public CantAttackBlockUnlessPaysSourceEffect(ManaCosts manaCosts, RestrictType restrictType) {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Detriment, RestrictType.ATTACK_AND_BLOCK, manaCosts);
|
||||
staticText = "{this} can't " + restrictType.toString() + " unless you pay "
|
||||
+ manaCosts == null ? "" : manaCosts.getText();
|
||||
}
|
||||
|
||||
public CantAttackBlockUnlessPaysSourceEffect(CantAttackBlockUnlessPaysSourceEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (!restrictType.equals(RestrictType.BLOCK) && event.getType().equals(EventType.DECLARE_ATTACKER)) {
|
||||
return event.getSourceId().equals(source.getSourceId());
|
||||
}
|
||||
if (!restrictType.equals(RestrictType.ATTACK) && event.getType().equals(EventType.DECLARE_BLOCKER)) {
|
||||
return event.getSourceId().equals(source.getSourceId());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CantAttackBlockUnlessPaysSourceEffect copy() {
|
||||
return new CantAttackBlockUnlessPaysSourceEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* 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.combat;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.RestrictionEffect;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class CantAttackYouAllEffect extends RestrictionEffect {
|
||||
|
||||
private final FilterCreaturePermanent filterAttacker;
|
||||
|
||||
public CantAttackYouAllEffect(Duration duration) {
|
||||
this(duration, new FilterCreaturePermanent());
|
||||
}
|
||||
|
||||
public CantAttackYouAllEffect(Duration duration, FilterCreaturePermanent filter) {
|
||||
super(duration, Outcome.Benefit);
|
||||
this.filterAttacker = filter;
|
||||
staticText = "Creatures can't attack you";
|
||||
}
|
||||
|
||||
CantAttackYouAllEffect(final CantAttackYouAllEffect effect) {
|
||||
super(effect);
|
||||
this.filterAttacker = effect.filterAttacker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(Permanent permanent, Ability source, Game game) {
|
||||
return filterAttacker.match(permanent, source.getSourceId(), source.getControllerId(), game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAttack(UUID defenderId, Ability source, Game game) {
|
||||
return !defenderId.equals(source.getControllerId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CantAttackYouAllEffect copy() {
|
||||
return new CantAttackYouAllEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* 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.combat;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
import mage.abilities.effects.PayCostToAttackBlockEffectImpl;
|
||||
import mage.abilities.effects.PayCostToAttackBlockEffectImpl.RestrictType;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class CantAttackYouUnlessPayManaAllEffect extends PayCostToAttackBlockEffectImpl {
|
||||
|
||||
private final FilterCreaturePermanent filterCreaturePermanent;
|
||||
private final boolean payAlsoForAttackingPlaneswalker;
|
||||
|
||||
public CantAttackYouUnlessPayManaAllEffect(ManaCosts manaCosts) {
|
||||
this(manaCosts, false);
|
||||
}
|
||||
|
||||
public CantAttackYouUnlessPayManaAllEffect(ManaCosts manaCosts, boolean payAlsoForAttackingPlaneswalker) {
|
||||
this(manaCosts, payAlsoForAttackingPlaneswalker, null);
|
||||
}
|
||||
|
||||
public CantAttackYouUnlessPayManaAllEffect(ManaCosts manaCosts, boolean payAlsoForAttackingPlaneswalker, FilterCreaturePermanent filter) {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Detriment, RestrictType.ATTACK, manaCosts);
|
||||
this.payAlsoForAttackingPlaneswalker = payAlsoForAttackingPlaneswalker;
|
||||
this.filterCreaturePermanent = filter;
|
||||
staticText = (filterCreaturePermanent == null ? "Creatures" : filterCreaturePermanent.getMessage())
|
||||
+ " can't attack you "
|
||||
+ (payAlsoForAttackingPlaneswalker ? "or a planeswalker you control " : "")
|
||||
+ "unless their controller pays "
|
||||
+ (manaCosts == null ? "" : manaCosts.getText())
|
||||
+ " for each creature he or she controls that's attacking you";
|
||||
}
|
||||
|
||||
public CantAttackYouUnlessPayManaAllEffect(CantAttackYouUnlessPayManaAllEffect effect) {
|
||||
super(effect);
|
||||
this.payAlsoForAttackingPlaneswalker = effect.payAlsoForAttackingPlaneswalker;
|
||||
this.filterCreaturePermanent = effect.filterCreaturePermanent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
// check if attacking creature fullfills filter criteria
|
||||
if (filterCreaturePermanent != null) {
|
||||
Permanent permanent = game.getPermanent(event.getSourceId());
|
||||
if (!filterCreaturePermanent.match(permanent, source.getSourceId(), source.getControllerId(), game)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// attack target is controlling player
|
||||
if (source.getControllerId().equals(event.getTargetId())) {
|
||||
return true;
|
||||
}
|
||||
// or attack target is a planeswalker of the controlling player
|
||||
if (payAlsoForAttackingPlaneswalker) {
|
||||
Permanent permanent = game.getPermanent(event.getTargetId());
|
||||
if (permanent != null
|
||||
&& permanent.getCardType().contains(CardType.PLANESWALKER)
|
||||
&& permanent.getControllerId().equals(source.getControllerId())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CantAttackYouUnlessPayManaAllEffect copy() {
|
||||
return new CantAttackYouUnlessPayManaAllEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* 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.combat;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
import mage.abilities.effects.PayCostToAttackBlockEffectImpl;
|
||||
import mage.abilities.effects.PayCostToAttackBlockEffectImpl.RestrictType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class CantBlockUnlessPayManaAllEffect extends PayCostToAttackBlockEffectImpl {
|
||||
|
||||
private final FilterCreaturePermanent filterCreaturePermanent;
|
||||
|
||||
public CantBlockUnlessPayManaAllEffect(ManaCosts manaCosts) {
|
||||
this(manaCosts, false);
|
||||
}
|
||||
|
||||
public CantBlockUnlessPayManaAllEffect(ManaCosts manaCosts, boolean payAlsoForAttackingPlaneswalker) {
|
||||
this(manaCosts, payAlsoForAttackingPlaneswalker, null);
|
||||
}
|
||||
|
||||
public CantBlockUnlessPayManaAllEffect(ManaCosts manaCosts, boolean payAlsoForAttackingPlaneswalker, FilterCreaturePermanent filter) {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Detriment, RestrictType.BLOCK, manaCosts);
|
||||
this.filterCreaturePermanent = filter;
|
||||
staticText = (filterCreaturePermanent == null ? "Creatures" : filterCreaturePermanent.getMessage())
|
||||
+ " can't block "
|
||||
+ "unless their controller pays "
|
||||
+ (manaCosts == null ? "" : manaCosts.getText())
|
||||
+ " for each blocking creature he or she controls";
|
||||
}
|
||||
|
||||
public CantBlockUnlessPayManaAllEffect(CantBlockUnlessPayManaAllEffect effect) {
|
||||
super(effect);
|
||||
this.filterCreaturePermanent = effect.filterCreaturePermanent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
// check if blocking creature fullfills filter criteria
|
||||
if (filterCreaturePermanent != null) {
|
||||
Permanent permanent = game.getPermanent(event.getSourceId());
|
||||
if (!filterCreaturePermanent.match(permanent, source.getSourceId(), source.getControllerId(), game)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CantBlockUnlessPayManaAllEffect copy() {
|
||||
return new CantBlockUnlessPayManaAllEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
package mage.abilities.effects.common.continuous;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.repository.CardRepository;
|
||||
import mage.choices.Choice;
|
||||
import mage.choices.ChoiceImpl;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
public class BecomesChosenNonWallCreatureTypeTargetEffect extends OneShotEffect {
|
||||
|
||||
public BecomesChosenNonWallCreatureTypeTargetEffect() {
|
||||
super(Outcome.BoostCreature);
|
||||
staticText = "choose a creature type other than wall, target creature's type becomes that type until end of turn";
|
||||
|
||||
}
|
||||
|
||||
public BecomesChosenNonWallCreatureTypeTargetEffect(final BecomesChosenNonWallCreatureTypeTargetEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
String chosenType = "";
|
||||
if (player != null && permanent != null) {
|
||||
Choice typeChoice = new ChoiceImpl(true);
|
||||
typeChoice.setMessage("Choose creature type other than Wall");
|
||||
Set<String> types = CardRepository.instance.getCreatureTypes();
|
||||
types.remove("Wall");
|
||||
typeChoice.setChoices(types);
|
||||
while (!player.choose(Outcome.BoostCreature, typeChoice, game)) {
|
||||
if (!player.isInGame()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
game.informPlayers(permanent.getName() + ": " + player.getLogName() + " has chosen " + typeChoice.getChoice());
|
||||
chosenType = typeChoice.getChoice();
|
||||
if (chosenType != null && !chosenType.isEmpty()) {
|
||||
// ADD TYPE TO TARGET
|
||||
ContinuousEffect effect = new BecomesSubtypeTargetEffect(Duration.EndOfTurn, chosenType);
|
||||
effect.setTargetPointer(new FixedTarget(getTargetPointer().getFirst(game, source)));
|
||||
game.addEffect(effect, source);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Effect copy() {
|
||||
return new BecomesChosenNonWallCreatureTypeTargetEffect(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
/*
|
||||
* 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
|
||||
|
|
@ -20,12 +20,11 @@
|
|||
* 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.continuous;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
|
|
@ -45,18 +44,23 @@ import mage.game.permanent.token.Token;
|
|||
*/
|
||||
public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl {
|
||||
|
||||
public enum LoseType {
|
||||
|
||||
NONE, ALL, ALL_BUT_COLOR, ABILITIES, ABILITIES_AND_PT
|
||||
};
|
||||
|
||||
protected Token token;
|
||||
protected String type;
|
||||
protected boolean loseOther; // loses all other abilities, card types, and creature types
|
||||
protected LoseType loseType; // what attributes are lost
|
||||
|
||||
public BecomesCreatureAttachedEffect(Token token, String text, Duration duration) {
|
||||
this(token, text, duration, false);
|
||||
this(token, text, duration, LoseType.NONE);
|
||||
}
|
||||
|
||||
public BecomesCreatureAttachedEffect(Token token, String text, Duration duration, boolean loseOther) {
|
||||
super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.BecomeCreature);
|
||||
public BecomesCreatureAttachedEffect(Token token, String text, Duration duration, LoseType loseType) {
|
||||
super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.BecomeCreature);
|
||||
this.token = token;
|
||||
this.loseOther = loseOther;
|
||||
this.loseType = loseType;
|
||||
staticText = text;
|
||||
}
|
||||
|
||||
|
|
@ -64,7 +68,7 @@ public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl {
|
|||
super(effect);
|
||||
this.token = effect.token.copy();
|
||||
this.type = effect.type;
|
||||
this.loseOther = effect.loseOther;
|
||||
this.loseType = effect.loseType;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -89,8 +93,11 @@ public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl {
|
|||
}
|
||||
}
|
||||
// card type
|
||||
if (loseOther) {
|
||||
permanent.getCardType().clear();
|
||||
switch (loseType) {
|
||||
case ALL:
|
||||
case ALL_BUT_COLOR:
|
||||
permanent.getCardType().clear();
|
||||
break;
|
||||
}
|
||||
if (token.getCardType().size() > 0) {
|
||||
for (CardType t : token.getCardType()) {
|
||||
|
|
@ -100,8 +107,11 @@ public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl {
|
|||
}
|
||||
}
|
||||
// sub type
|
||||
if (loseOther) {
|
||||
permanent.getSubtype().clear();
|
||||
switch (loseType) {
|
||||
case ALL:
|
||||
case ALL_BUT_COLOR:
|
||||
permanent.getSubtype().clear();
|
||||
break;
|
||||
}
|
||||
if (token.getSubtype().size() > 0) {
|
||||
for (String t : token.getSubtype()) {
|
||||
|
|
@ -114,7 +124,7 @@ public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl {
|
|||
break;
|
||||
case ColorChangingEffects_5:
|
||||
if (sublayer == SubLayer.NA) {
|
||||
if (loseOther) {
|
||||
if (loseType.equals(LoseType.ALL)) {
|
||||
permanent.getColor(game).setBlack(false);
|
||||
permanent.getColor(game).setGreen(false);
|
||||
permanent.getColor(game).setBlue(false);
|
||||
|
|
@ -128,11 +138,16 @@ public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl {
|
|||
break;
|
||||
case AbilityAddingRemovingEffects_6:
|
||||
if (sublayer == SubLayer.NA) {
|
||||
if (loseOther) {
|
||||
permanent.removeAllAbilities(source.getSourceId(), game);
|
||||
switch (loseType) {
|
||||
case ALL:
|
||||
case ALL_BUT_COLOR:
|
||||
case ABILITIES:
|
||||
case ABILITIES_AND_PT:
|
||||
permanent.removeAllAbilities(source.getSourceId(), game);
|
||||
break;
|
||||
}
|
||||
if (token.getAbilities().size() > 0) {
|
||||
for (Ability ability: token.getAbilities()) {
|
||||
for (Ability ability : token.getAbilities()) {
|
||||
permanent.addAbility(ability, source.getSourceId(), game);
|
||||
}
|
||||
}
|
||||
|
|
@ -142,6 +157,7 @@ public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl {
|
|||
if (sublayer == SubLayer.SetPT_7b) {
|
||||
permanent.getPower().setValue(token.getPower().getValue());
|
||||
permanent.getToughness().setValue(token.getToughness().getValue());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package mage.abilities.effects.common.continuous;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class BecomesSubtypeAllEffect extends ContinuousEffectImpl {
|
||||
|
||||
protected ArrayList<String> subtypes = new ArrayList();
|
||||
protected boolean loseOther; // loses other subtypes
|
||||
|
||||
public BecomesSubtypeAllEffect(Duration duration, String subtype) {
|
||||
this(duration, createArrayList(subtype));
|
||||
}
|
||||
|
||||
public BecomesSubtypeAllEffect(Duration duration, ArrayList<String> subtypes) {
|
||||
this(duration, subtypes, true);
|
||||
}
|
||||
|
||||
public BecomesSubtypeAllEffect(Duration duration,
|
||||
ArrayList<String> subtypes, boolean loseOther) {
|
||||
super(duration, Outcome.Detriment);
|
||||
this.subtypes = subtypes;
|
||||
this.staticText = setText();
|
||||
this.loseOther = loseOther;
|
||||
}
|
||||
|
||||
private static ArrayList<String> createArrayList(String subtype) {
|
||||
ArrayList<String> subtypes = new ArrayList<>();
|
||||
subtypes.add(subtype);
|
||||
return subtypes;
|
||||
}
|
||||
|
||||
public BecomesSubtypeAllEffect(final BecomesSubtypeAllEffect effect) {
|
||||
super(effect);
|
||||
this.subtypes.addAll(effect.subtypes);
|
||||
this.loseOther = effect.loseOther;
|
||||
this.loseOther = effect.loseOther;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BecomesSubtypeAllEffect copy() {
|
||||
return new BecomesSubtypeAllEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Layer layer, SubLayer sublayer, Ability source,
|
||||
Game game) {
|
||||
|
||||
for (Permanent permanent : game.getBattlefield()
|
||||
.getAllActivePermanents(new FilterCreaturePermanent(), game)) {
|
||||
if (permanent != null) {
|
||||
switch (layer) {
|
||||
case TypeChangingEffects_4:
|
||||
if (loseOther) {
|
||||
permanent.getSubtype().clear();
|
||||
permanent.getSubtype().addAll(subtypes);
|
||||
} else {
|
||||
for (String subtype : subtypes) {
|
||||
if (!permanent.getSubtype().contains(subtype)) {
|
||||
permanent.getSubtype().add(subtype);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (duration.equals(Duration.Custom)) {
|
||||
discard();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasLayer(Layer layer) {
|
||||
return layer == Layer.TypeChangingEffects_4;
|
||||
}
|
||||
|
||||
private String setText() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Target creature becomes that type");
|
||||
if (!duration.toString().isEmpty()
|
||||
&& !duration.equals(Duration.EndOfGame)) {
|
||||
sb.append(" ").append(duration.toString());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
/*
|
||||
* 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
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
* 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.
|
||||
|
|
@ -33,6 +33,7 @@ import mage.abilities.Mode;
|
|||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.StaticValue;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
|
|
@ -64,7 +65,8 @@ public class BoostTargetEffect extends ContinuousEffectImpl {
|
|||
* @param power
|
||||
* @param toughness
|
||||
* @param duration
|
||||
* @param lockedIn if true, power and toughness will be calculated only once, when the ability resolves
|
||||
* @param lockedIn if true, power and toughness will be calculated only
|
||||
* once, when the ability resolves
|
||||
*/
|
||||
public BoostTargetEffect(DynamicValue power, DynamicValue toughness, Duration duration, boolean lockedIn) {
|
||||
super(duration, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, isCanKill(toughness) ? Outcome.UnboostCreature : Outcome.BoostCreature);
|
||||
|
|
@ -99,7 +101,7 @@ public class BoostTargetEffect extends ContinuousEffectImpl {
|
|||
int affectedTargets = 0;
|
||||
for (UUID permanentId : targetPointer.getTargets(game, source)) {
|
||||
Permanent target = game.getPermanent(permanentId);
|
||||
if (target != null) {
|
||||
if (target != null && target.getCardType().contains(CardType.CREATURE)) {
|
||||
target.addPower(power.calculate(game, source, this));
|
||||
target.addToughness(toughness.calculate(game, source, this));
|
||||
affectedTargets++;
|
||||
|
|
@ -115,7 +117,7 @@ public class BoostTargetEffect extends ContinuousEffectImpl {
|
|||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Target target = mode.getTargets().get(0);
|
||||
if(target.getMaxNumberOfTargets() > 1){
|
||||
if (target.getMaxNumberOfTargets() > 1) {
|
||||
if (target.getNumberOfTargets() < target.getNumberOfTargets()) {
|
||||
sb.append("up to ");
|
||||
}
|
||||
|
|
@ -127,16 +129,15 @@ public class BoostTargetEffect extends ContinuousEffectImpl {
|
|||
sb.append(target.getTargetName()).append(" gets ");
|
||||
}
|
||||
String p = power.toString();
|
||||
if(!p.startsWith("-")) {
|
||||
if (!p.startsWith("-")) {
|
||||
sb.append("+");
|
||||
}
|
||||
sb.append(p).append("/");
|
||||
String t = toughness.toString();
|
||||
if(!t.startsWith("-")){
|
||||
if(p.startsWith("-")) {
|
||||
if (!t.startsWith("-")) {
|
||||
if (t.equals("0") && p.startsWith("-")) {
|
||||
sb.append("-");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
sb.append("+");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.abilities.effects.common.cost;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
|
|
@ -39,19 +38,17 @@ import mage.constants.Outcome;
|
|||
import mage.game.Game;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
||||
public class SpellCostReductionSourceEffect extends CostModificationEffectImpl {
|
||||
|
||||
private final int amount;
|
||||
private ManaCosts<ManaCost> manaCostsToReduce = null;
|
||||
private final Condition condition;
|
||||
|
||||
public SpellCostReductionSourceEffect(ManaCosts<ManaCost> manaCostsToReduce, Condition condition) {
|
||||
public SpellCostReductionSourceEffect(ManaCosts<ManaCost> manaCostsToReduce, Condition condition) {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST);
|
||||
this.amount = 0;
|
||||
this.manaCostsToReduce = manaCostsToReduce;
|
||||
|
|
@ -59,14 +56,13 @@ public class SpellCostReductionSourceEffect extends CostModificationEffectImpl {
|
|||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("{this} costs ");
|
||||
for (String manaSymbol :manaCostsToReduce.getSymbols()) {
|
||||
for (String manaSymbol : manaCostsToReduce.getSymbols()) {
|
||||
sb.append(manaSymbol);
|
||||
}
|
||||
sb.append(" less to if ").append(this.condition.toString());
|
||||
this.staticText = sb.toString();
|
||||
}
|
||||
|
||||
|
||||
public SpellCostReductionSourceEffect(int amount, Condition condition) {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST);
|
||||
this.amount = amount;
|
||||
|
|
@ -76,7 +72,7 @@ public class SpellCostReductionSourceEffect extends CostModificationEffectImpl {
|
|||
this.staticText = sb.toString();
|
||||
}
|
||||
|
||||
protected SpellCostReductionSourceEffect(SpellCostReductionSourceEffect effect) {
|
||||
protected SpellCostReductionSourceEffect(final SpellCostReductionSourceEffect effect) {
|
||||
super(effect);
|
||||
this.amount = effect.amount;
|
||||
this.manaCostsToReduce = effect.manaCostsToReduce;
|
||||
|
|
@ -85,7 +81,7 @@ public class SpellCostReductionSourceEffect extends CostModificationEffectImpl {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source, Ability abilityToModify) {
|
||||
if (manaCostsToReduce != null){
|
||||
if (manaCostsToReduce != null) {
|
||||
CardUtil.adjustCost((SpellAbility) abilityToModify, manaCostsToReduce, false);
|
||||
} else {
|
||||
CardUtil.reduceCost(abilityToModify, this.amount);
|
||||
|
|
@ -95,7 +91,7 @@ public class SpellCostReductionSourceEffect extends CostModificationEffectImpl {
|
|||
|
||||
@Override
|
||||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||
if (abilityToModify.getSourceId().equals(source.getSourceId()) && (abilityToModify instanceof SpellAbility)) {
|
||||
if (abilityToModify.getSourceId().equals(source.getSourceId()) && (abilityToModify instanceof SpellAbility)) {
|
||||
return condition.apply(game, source);
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -73,9 +73,9 @@ public class DiscardCardYouChooseTargetEffect extends OneShotEffect {
|
|||
public DiscardCardYouChooseTargetEffect(FilterCard filter) {
|
||||
this(filter, TargetController.OPPONENT);
|
||||
}
|
||||
|
||||
|
||||
public DiscardCardYouChooseTargetEffect(TargetController targetController, int numberCardsToReveal) {
|
||||
this(new FilterCard("one card"), targetController,
|
||||
this(new FilterCard("one card"), targetController,
|
||||
new StaticValue(numberCardsToReveal, new StringBuilder(CardUtil.numberToText(numberCardsToReveal)).append(" cards").toString()));
|
||||
}
|
||||
|
||||
|
|
@ -87,28 +87,28 @@ public class DiscardCardYouChooseTargetEffect extends OneShotEffect {
|
|||
super(Outcome.Discard);
|
||||
this.targetController = targetController;
|
||||
this.filter = filter;
|
||||
|
||||
|
||||
this.revealAllCards = false;
|
||||
this.numberCardsToReveal = numberCardsToReveal;
|
||||
this.numberCardsToDiscard = new StaticValue(1);
|
||||
|
||||
staticText = this.setText();
|
||||
|
||||
staticText = this.setText();
|
||||
}
|
||||
|
||||
|
||||
public DiscardCardYouChooseTargetEffect(FilterCard filter, TargetController targetController) {
|
||||
this(new StaticValue(1), filter, targetController);
|
||||
}
|
||||
|
||||
|
||||
public DiscardCardYouChooseTargetEffect(DynamicValue numberCardsToDiscard, FilterCard filter, TargetController targetController) {
|
||||
super(Outcome.Discard);
|
||||
this.targetController = targetController;
|
||||
this.filter = filter;
|
||||
|
||||
|
||||
this.numberCardsToDiscard = numberCardsToDiscard;
|
||||
this.numberCardsToReveal = null;
|
||||
this.revealAllCards = true;
|
||||
|
||||
staticText = this.setText();
|
||||
|
||||
staticText = this.setText();
|
||||
}
|
||||
|
||||
public DiscardCardYouChooseTargetEffect(final DiscardCardYouChooseTargetEffect effect) {
|
||||
|
|
@ -117,12 +117,12 @@ public class DiscardCardYouChooseTargetEffect extends OneShotEffect {
|
|||
this.targetController = effect.targetController;
|
||||
this.numberCardsToDiscard = effect.numberCardsToDiscard;
|
||||
this.numberCardsToReveal = effect.numberCardsToReveal;
|
||||
this.revealAllCards = effect.revealAllCards;
|
||||
this.revealAllCards = effect.revealAllCards;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getFirstTarget());
|
||||
Player player = game.getPlayer(targetPointer.getFirst(game, source));
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Card sourceCard = game.getCard(source.getSourceId());
|
||||
if (player != null && controller != null) {
|
||||
|
|
@ -131,7 +131,7 @@ public class DiscardCardYouChooseTargetEffect extends OneShotEffect {
|
|||
}
|
||||
int numberToReveal = this.numberCardsToReveal.calculate(game, source, this);
|
||||
if (numberToReveal > 0) {
|
||||
Cards revealedCards = new CardsImpl(Zone.HAND);
|
||||
Cards revealedCards = new CardsImpl(Zone.HAND);
|
||||
numberToReveal = Math.min(player.getHand().size(), numberToReveal);
|
||||
if (player.getHand().size() > numberToReveal) {
|
||||
TargetCardInHand chosenCards = new TargetCardInHand(numberToReveal, numberToReveal, new FilterCard("card in "+ player.getLogName() +"'s hand"));
|
||||
|
|
@ -149,10 +149,10 @@ public class DiscardCardYouChooseTargetEffect extends OneShotEffect {
|
|||
}
|
||||
} else {
|
||||
revealedCards.addAll(player.getHand());
|
||||
}
|
||||
}
|
||||
|
||||
player.revealCards(sourceCard != null ? sourceCard.getName() :"Discard", revealedCards, game);
|
||||
|
||||
|
||||
boolean result = true;
|
||||
int filteredCardsCount = revealedCards.count(filter, source.getSourceId(), source.getControllerId(), game);
|
||||
int numberToDiscard = Math.min(this.numberCardsToDiscard.calculate(game, source, this), filteredCardsCount);
|
||||
|
|
@ -220,7 +220,7 @@ public class DiscardCardYouChooseTargetEffect extends OneShotEffect {
|
|||
} else {
|
||||
sb.append(" of them.");
|
||||
}
|
||||
|
||||
|
||||
sb.append(" That player discards ").append(discardMultipleCards ? "those cards" : "that card").toString();
|
||||
return sb.toString();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package mage.abilities.effects.common.replacement;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
import mage.abilities.effects.PayCostToAttackBlockEffectImpl;
|
||||
import mage.abilities.effects.PayCostToAttackBlockEffectImpl.RestrictType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class CantAttackYouUnlessPayManaAllEffect extends PayCostToAttackBlockEffectImpl {
|
||||
|
||||
public CantAttackYouUnlessPayManaAllEffect(ManaCosts manaCosts) {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Detriment, RestrictType.ATTACK, manaCosts);
|
||||
staticText = "Creatures can't attack you unless their controller pays " + manaCosts.getText() + " for each creature he or she controls that's attacking you";
|
||||
}
|
||||
|
||||
CantAttackYouUnlessPayManaAllEffect(CantAttackYouUnlessPayManaAllEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
return source.getControllerId().equals(event.getTargetId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CantAttackYouUnlessPayManaAllEffect copy() {
|
||||
return new CantAttackYouUnlessPayManaAllEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -31,6 +31,7 @@ import java.util.Iterator;
|
|||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.DelayedTriggeredAbility;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.StaticAbility;
|
||||
import mage.abilities.common.EntersBattlefieldAbility;
|
||||
|
|
@ -44,7 +45,7 @@ import mage.abilities.costs.Costs;
|
|||
import mage.abilities.costs.CostsImpl;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.ReturnToHandTargetEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
|
||||
import mage.cards.Card;
|
||||
|
|
@ -76,12 +77,9 @@ public class DashAbility extends StaticAbility implements AlternativeSourceCosts
|
|||
Ability ability = new EntersBattlefieldAbility(
|
||||
new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.Custom, false),
|
||||
DashedCondition.getInstance(), false, "", "");
|
||||
Effect effect = new ReturnToHandTargetEffect();
|
||||
effect.setText("return the dashed creature from the battlefield to its owner's hand");
|
||||
effect.setTargetPointer(new FixedTarget(card.getId()));
|
||||
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect), false));
|
||||
ability.addEffect(new DashAddDelayedTriggeredAbilityEffect());
|
||||
addSubAbility(ability);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public DashAbility(final DashAbility ability) {
|
||||
|
|
@ -134,7 +132,7 @@ public class DashAbility extends StaticAbility implements AlternativeSourceCosts
|
|||
this.resetDash();
|
||||
for (AlternativeCost2 dashCost : alternativeSourceCosts) {
|
||||
if (dashCost.canPay(ability, sourceId, controllerId, game)
|
||||
&& player.chooseUse(Outcome.Benefit, new StringBuilder(KEYWORD).append(" the creature for ").append(dashCost.getText(true)).append(" ?").toString(), ability, game)) {
|
||||
&& player.chooseUse(Outcome.Benefit, KEYWORD + " the creature for " + dashCost.getText(true) + " ?", ability, game)) {
|
||||
activateDash(dashCost, game);
|
||||
ability.getManaCostsToPay().clear();
|
||||
ability.getCosts().clear();
|
||||
|
|
@ -209,3 +207,35 @@ public class DashAbility extends StaticAbility implements AlternativeSourceCosts
|
|||
return alterCosts;
|
||||
}
|
||||
}
|
||||
|
||||
class DashAddDelayedTriggeredAbilityEffect extends OneShotEffect {
|
||||
|
||||
public DashAddDelayedTriggeredAbilityEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "return the dashed creature from the battlefield to its owner's hand";
|
||||
}
|
||||
|
||||
public DashAddDelayedTriggeredAbilityEffect(final DashAddDelayedTriggeredAbilityEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DashAddDelayedTriggeredAbilityEffect copy() {
|
||||
return new DashAddDelayedTriggeredAbilityEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Effect effect = new ReturnToHandTargetEffect();
|
||||
effect.setText("return the dashed creature from the battlefield to its owner's hand");
|
||||
effect.setTargetPointer(new FixedTarget(source.getSourceId()));
|
||||
// init target pointer now because the dashed creature will only be returned from current zone
|
||||
effect.getTargetPointer().init(game, source);
|
||||
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect);
|
||||
delayedAbility.setSourceId(source.getSourceId());
|
||||
delayedAbility.setControllerId(source.getControllerId());
|
||||
delayedAbility.setSourceObject(source.getSourceObject(game), game);
|
||||
game.addDelayedTriggeredAbility(delayedAbility);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,40 +1,38 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
* 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.keyword;
|
||||
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Zone;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
/**
|
||||
|
|
@ -63,7 +61,7 @@ public class ExaltedAbility extends TriggeredAbilityImpl {
|
|||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (game.getActivePlayerId().equals(this.controllerId) ) {
|
||||
if (game.getActivePlayerId().equals(this.controllerId)) {
|
||||
if (game.getCombat().attacksAlone()) {
|
||||
this.getEffects().get(0).setTargetPointer(new FixedTarget(game.getCombat().getAttackers().get(0)));
|
||||
return true;
|
||||
|
|
@ -74,7 +72,7 @@ public class ExaltedAbility extends TriggeredAbilityImpl {
|
|||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Exalted";
|
||||
return "Exalted <i>(Whenever a creature you control attacks alone, that creature gets +1/+1 until end of turn.)</i>";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,8 +139,6 @@ public class KickerAbility extends StaticAbility implements OptionalAdditionalSo
|
|||
}
|
||||
|
||||
public void resetKicker(Game game, Ability source) {
|
||||
String key = getActivationKey(source, "", game);
|
||||
activations.remove(key);
|
||||
for (OptionalAdditionalCost cost : kickerCosts) {
|
||||
cost.reset();
|
||||
}
|
||||
|
|
@ -180,8 +178,11 @@ public class KickerAbility extends StaticAbility implements OptionalAdditionalSo
|
|||
}
|
||||
|
||||
private String getActivationKey(Ability source, String costText, Game game) {
|
||||
int zcc = source.getSourceObjectZoneChangeCounter();
|
||||
if (source.getSourceObjectZoneChangeCounter() == 0) {
|
||||
int zcc = 0;
|
||||
if (source.getAbilityType().equals(AbilityType.TRIGGERED)) {
|
||||
zcc = source.getSourceObjectZoneChangeCounter();
|
||||
}
|
||||
if (zcc == 0) {
|
||||
zcc = game.getState().getZoneChangeCounter(source.getSourceId());
|
||||
}
|
||||
if (zcc > 0 && (source.getAbilityType().equals(AbilityType.TRIGGERED) || source.getAbilityType().equals(AbilityType.STATIC))) {
|
||||
|
|
|
|||
|
|
@ -1,38 +1,37 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package mage.abilities.keyword;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.StaticAbility;
|
||||
import mage.abilities.effects.common.combat.CantBeBlockedByMoreThanOneSourceEffect;
|
||||
import mage.abilities.effects.common.combat.CantBeBlockedByOneEffect;
|
||||
import mage.constants.Zone;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class MenaceAbility extends StaticAbility {
|
||||
|
||||
public MenaceAbility() {
|
||||
super(Zone.BATTLEFIELD, new CantBeBlockedByOneEffect(2));
|
||||
}
|
||||
|
||||
public MenaceAbility(MenaceAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ability copy() {
|
||||
return new MenaceAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Menace <i>(This creature can't be blocked except by two or more creatures.)</i>";
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package mage.abilities.keyword;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.StaticAbility;
|
||||
import mage.abilities.effects.common.combat.CantBeBlockedByOneEffect;
|
||||
import mage.constants.Zone;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class MenaceAbility extends StaticAbility {
|
||||
|
||||
public MenaceAbility() {
|
||||
super(Zone.BATTLEFIELD, new CantBeBlockedByOneEffect(2));
|
||||
}
|
||||
|
||||
public MenaceAbility(final MenaceAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ability copy() {
|
||||
return new MenaceAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Menace <i>(This creature can't be blocked except by two or more creatures.)</i>";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ import mage.watchers.common.MiracleWatcher;
|
|||
public class MiracleAbility extends TriggeredAbilityImpl {
|
||||
private static final String staticRule = " <i>(You may cast this card for its miracle cost when you draw it if it's the first card you drew this turn.)<i/>";
|
||||
private String ruleText;
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public MiracleAbility(Card card, ManaCosts miracleCosts) {
|
||||
super(Zone.HAND, new MiracleEffect((ManaCosts<ManaCost>)miracleCosts), true);
|
||||
|
|
@ -141,7 +141,7 @@ class MiracleEffect extends OneShotEffect {
|
|||
|
||||
public MiracleEffect(ManaCosts<ManaCost> miracleCosts) {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "cast this card for it's miracle cost";
|
||||
this.staticText = "cast this card for its miracle cost";
|
||||
this.miracleCosts = miracleCosts;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,14 +22,12 @@ import mage.util.CardUtil;
|
|||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
||||
|
||||
public class RenownAbility extends TriggeredAbilityImpl {
|
||||
|
||||
private int renownValue;
|
||||
|
||||
|
||||
public RenownAbility(int renownValue) {
|
||||
super(Zone.BATTLEFIELD, new BecomeRenownSourceEffect(renownValue), false);
|
||||
super(Zone.BATTLEFIELD, new BecomesRenownedSourceEffect(renownValue), false);
|
||||
this.renownValue = renownValue;
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +48,8 @@ public class RenownAbility extends TriggeredAbilityImpl {
|
|||
|
||||
@Override
|
||||
public boolean checkInterveningIfClause(Game game) {
|
||||
return getSourceObject(game) != null && !((Permanent)getSourceObject(game)).isRenown();
|
||||
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(getSourceId());
|
||||
return sourcePermanent != null && !sourcePermanent.isRenowned();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -59,45 +58,40 @@ public class RenownAbility extends TriggeredAbilityImpl {
|
|||
&& ((DamagedPlayerEvent) event).isCombatDamage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever {this} deals combat damage to a player, " + super.getRule();
|
||||
}
|
||||
|
||||
public int getRenownValue() {
|
||||
return renownValue;
|
||||
}
|
||||
}
|
||||
|
||||
class BecomeRenownSourceEffect extends OneShotEffect {
|
||||
class BecomesRenownedSourceEffect extends OneShotEffect {
|
||||
|
||||
public BecomeRenownSourceEffect(int renownValue) {
|
||||
public BecomesRenownedSourceEffect(int renownValue) {
|
||||
super(Outcome.BoostCreature);
|
||||
this.staticText = setText(renownValue);
|
||||
}
|
||||
|
||||
public BecomeRenownSourceEffect(final BecomeRenownSourceEffect effect) {
|
||||
public BecomesRenownedSourceEffect(final BecomesRenownedSourceEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BecomeRenownSourceEffect copy() {
|
||||
return new BecomeRenownSourceEffect(this);
|
||||
public BecomesRenownedSourceEffect copy() {
|
||||
return new BecomesRenownedSourceEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null && source instanceof RenownAbility) {
|
||||
game.informPlayers(permanent.getLogName() + " is now renown");
|
||||
game.informPlayers(permanent.getLogName() + " is now renowned");
|
||||
int renownValue = ((RenownAbility) source).getRenownValue();
|
||||
// handle renown = X
|
||||
if (renownValue == Integer.MAX_VALUE) {
|
||||
renownValue = source.getManaCostsToPay().getX();
|
||||
}
|
||||
new AddCountersSourceEffect(CounterType.P1P1.createInstance(renownValue),true).apply(game, source);
|
||||
permanent.setRenown(true);
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BECOMES_RENOWN, source.getSourceId(), source.getSourceId(), source.getControllerId(), renownValue));
|
||||
new AddCountersSourceEffect(CounterType.P1P1.createInstance(renownValue), true).apply(game, source);
|
||||
permanent.setRenowned(true);
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BECOMES_RENOWNED, source.getSourceId(), source.getSourceId(), source.getControllerId(), renownValue));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -106,9 +100,9 @@ class BecomeRenownSourceEffect extends OneShotEffect {
|
|||
private String setText(int renownValue) {
|
||||
// Renown 1 (When this creature deals combat damage to a player, if it isn't renowned, put a +1/+1 counter on it and it becomes renowned.)
|
||||
StringBuilder sb = new StringBuilder("Renown ");
|
||||
sb.append(renownValue == Integer.MAX_VALUE ? "X":renownValue)
|
||||
sb.append(renownValue == Integer.MAX_VALUE ? "X" : renownValue)
|
||||
.append(". <i>(When this creature deals combat damage to a player, if it isn't renowned, put ")
|
||||
.append(renownValue == Integer.MAX_VALUE ? "X":CardUtil.numberToText(renownValue, "a"))
|
||||
.append(renownValue == Integer.MAX_VALUE ? "X" : CardUtil.numberToText(renownValue, "a"))
|
||||
.append(" +1/+1 counter on it and it becomes renowned.)</i>").toString();
|
||||
return sb.toString();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -292,7 +292,9 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
if (spellAbility == null) {
|
||||
for (Ability ability : abilities.getActivatedAbilities(Zone.HAND)) {
|
||||
// name check prevents that alternate casting methods (like "cast [card name] using bestow") are returned here
|
||||
if (ability instanceof SpellAbility && ability.toString().endsWith(getName())) {
|
||||
// BUG #1024: Bestow bug
|
||||
//if (ability instanceof SpellAbility && ability.toString().endsWith(getName())) {
|
||||
if (ability instanceof SpellAbility) {
|
||||
spellAbility = (SpellAbility) ability;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,9 +58,9 @@ public enum CardRepository {
|
|||
private static final String JDBC_URL = "jdbc:h2:file:./db/cards.h2;AUTO_SERVER=TRUE";
|
||||
private static final String VERSION_ENTITY_NAME = "card";
|
||||
// raise this if db structure was changed
|
||||
private static final long CARD_DB_VERSION = 39;
|
||||
private static final long CARD_DB_VERSION = 41;
|
||||
// raise this if new cards were added to the server
|
||||
private static final long CARD_CONTENT_VERSION = 20;
|
||||
private static final long CARD_CONTENT_VERSION = 26;
|
||||
|
||||
private final Random random = new Random();
|
||||
private Dao<CardInfo, Object> cardDao;
|
||||
|
|
@ -135,7 +135,7 @@ public enum CardRepository {
|
|||
int result = card.getName().indexOf(" // ");
|
||||
if (result > 0) {
|
||||
names.add(card.getName().substring(0, result));
|
||||
names.add(card.getName().substring(result+4));
|
||||
names.add(card.getName().substring(result + 4));
|
||||
} else {
|
||||
names.add(card.getName());
|
||||
}
|
||||
|
|
@ -156,7 +156,7 @@ public enum CardRepository {
|
|||
int result = card.getName().indexOf(" // ");
|
||||
if (result > 0) {
|
||||
names.add(card.getName().substring(0, result));
|
||||
names.add(card.getName().substring(result+4));
|
||||
names.add(card.getName().substring(result + 4));
|
||||
} else {
|
||||
names.add(card.getName());
|
||||
}
|
||||
|
|
@ -165,7 +165,7 @@ public enum CardRepository {
|
|||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
|
||||
public Set<String> getCreatureNames() {
|
||||
Set<String> names = new TreeSet<>();
|
||||
try {
|
||||
|
|
@ -177,7 +177,7 @@ public enum CardRepository {
|
|||
int result = card.getName().indexOf(" // ");
|
||||
if (result > 0) {
|
||||
names.add(card.getName().substring(0, result));
|
||||
names.add(card.getName().substring(result+4));
|
||||
names.add(card.getName().substring(result + 4));
|
||||
} else {
|
||||
names.add(card.getName());
|
||||
}
|
||||
|
|
@ -193,7 +193,7 @@ public enum CardRepository {
|
|||
QueryBuilder<CardInfo, Object> qb = cardDao.queryBuilder();
|
||||
qb.distinct().selectColumns("name");
|
||||
Where where = qb.where();
|
||||
where.and(where.not().like("types", '%' + CardType.CREATURE.name() +'%'),where.not().like("types", '%' + CardType.LAND.name() + '%'));
|
||||
where.and(where.not().like("types", '%' + CardType.CREATURE.name() + '%'), where.not().like("types", '%' + CardType.LAND.name() + '%'));
|
||||
List<CardInfo> results = cardDao.query(qb.prepare());
|
||||
for (CardInfo card : results) {
|
||||
int result = card.getName().indexOf(" // ");
|
||||
|
|
@ -261,7 +261,6 @@ public enum CardRepository {
|
|||
return null;
|
||||
}
|
||||
|
||||
|
||||
public List<String> getClassNames() {
|
||||
List<String> names = new ArrayList<>();
|
||||
try {
|
||||
|
|
@ -313,7 +312,7 @@ public enum CardRepository {
|
|||
try {
|
||||
QueryBuilder<CardInfo, Object> queryBuilder = cardDao.queryBuilder();
|
||||
criteria.buildQuery(queryBuilder);
|
||||
|
||||
|
||||
return cardDao.query(queryBuilder.prepare());
|
||||
} catch (SQLException ex) {
|
||||
}
|
||||
|
|
@ -333,7 +332,7 @@ public enum CardRepository {
|
|||
public void setContentVersion(long version) {
|
||||
try {
|
||||
ConnectionSource connectionSource = new JdbcConnectionSource(JDBC_URL);
|
||||
RepositoryUtil.updateVersion(connectionSource, VERSION_ENTITY_NAME + "Content", version);
|
||||
RepositoryUtil.updateVersion(connectionSource, VERSION_ENTITY_NAME + "Content", version);
|
||||
} catch (SQLException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,13 +21,13 @@ import org.apache.log4j.Logger;
|
|||
public enum ExpansionRepository {
|
||||
|
||||
instance;
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ExpansionRepository.class);
|
||||
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ExpansionRepository.class);
|
||||
|
||||
private static final String JDBC_URL = "jdbc:h2:file:./db/cards.h2;AUTO_SERVER=TRUE";
|
||||
private static final String VERSION_ENTITY_NAME = "expansion";
|
||||
private static final long EXPANSION_DB_VERSION = 5;
|
||||
private static final long EXPANSION_CONTENT_VERSION = 8;
|
||||
private static final long EXPANSION_CONTENT_VERSION = 9;
|
||||
|
||||
private Dao<ExpansionInfo, Object> expansionDao;
|
||||
|
||||
|
|
@ -73,7 +73,7 @@ public enum ExpansionRepository {
|
|||
}
|
||||
|
||||
public ExpansionInfo[] getWithBoostersSortedByReleaseDate() {
|
||||
ExpansionInfo[] sets = new ExpansionInfo[0];
|
||||
ExpansionInfo[] sets = new ExpansionInfo[0];
|
||||
try {
|
||||
QueryBuilder<ExpansionInfo, Object> qb = expansionDao.queryBuilder();
|
||||
qb.orderBy("releaseDate", false);
|
||||
|
|
@ -96,9 +96,9 @@ public enum ExpansionRepository {
|
|||
}
|
||||
return sets;
|
||||
}
|
||||
|
||||
|
||||
public List<ExpansionInfo> getSetsFromBlock(String blockName) {
|
||||
List<ExpansionInfo> sets = new LinkedList<>();
|
||||
List<ExpansionInfo> sets = new LinkedList<>();
|
||||
try {
|
||||
QueryBuilder<ExpansionInfo, Object> qb = expansionDao.queryBuilder();
|
||||
qb.where().eq("blockName", new SelectArg(blockName));
|
||||
|
|
@ -119,9 +119,9 @@ public enum ExpansionRepository {
|
|||
}
|
||||
} catch (SQLException ex) {
|
||||
}
|
||||
return set;
|
||||
return set;
|
||||
}
|
||||
|
||||
|
||||
public ExpansionInfo getSetByName(String setName) {
|
||||
ExpansionInfo set = null;
|
||||
try {
|
||||
|
|
@ -133,7 +133,7 @@ public enum ExpansionRepository {
|
|||
}
|
||||
} catch (SQLException ex) {
|
||||
}
|
||||
return set;
|
||||
return set;
|
||||
}
|
||||
|
||||
public List<ExpansionInfo> getAll() {
|
||||
|
|
@ -145,7 +145,7 @@ public enum ExpansionRepository {
|
|||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
|
||||
public List<String> getAllSetNames() {
|
||||
try {
|
||||
QueryBuilder<ExpansionInfo, Object> qb = expansionDao.queryBuilder();
|
||||
|
|
@ -153,14 +153,14 @@ public enum ExpansionRepository {
|
|||
List<ExpansionInfo> expansions = expansionDao.query(qb.prepare());
|
||||
List<String> setNames = new LinkedList<>();
|
||||
for (ExpansionInfo expansionInfo : expansions) {
|
||||
setNames.add(expansionInfo.getName());
|
||||
}
|
||||
setNames.add(expansionInfo.getName());
|
||||
}
|
||||
return setNames;
|
||||
} catch (SQLException ex) {
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
|
||||
public long getContentVersionFromDB() {
|
||||
try {
|
||||
ConnectionSource connectionSource = new JdbcConnectionSource(JDBC_URL);
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
/*
|
||||
* 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
|
||||
|
|
@ -20,12 +20,11 @@
|
|||
* 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.filter.common;
|
||||
|
||||
import mage.constants.CardType;
|
||||
|
|
@ -40,7 +39,11 @@ import mage.filter.predicate.mageobject.SupertypePredicate;
|
|||
public class FilterBasicLandCard extends FilterCard {
|
||||
|
||||
public FilterBasicLandCard() {
|
||||
super("basic land card");
|
||||
this("basic land card");
|
||||
}
|
||||
|
||||
public FilterBasicLandCard(String name) {
|
||||
super(name);
|
||||
this.add(new CardTypePredicate(CardType.LAND));
|
||||
this.add(new SupertypePredicate("Basic"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@ public interface Game extends MageItem, Serializable {
|
|||
|
||||
void firePriorityEvent(UUID playerId);
|
||||
|
||||
void firePlayManaEvent(UUID playerId, String message);
|
||||
void firePlayManaEvent(UUID playerId, String message, Map<String, Serializable> options);
|
||||
|
||||
void firePlayXManaEvent(UUID playerId, String message);
|
||||
|
||||
|
|
@ -322,7 +322,6 @@ public interface Game extends MageItem, Serializable {
|
|||
void endMulligan(UUID playerId);
|
||||
|
||||
// void quit(UUID playerId);
|
||||
|
||||
void timerTimeout(UUID playerId);
|
||||
|
||||
void idleTimeout(UUID playerId);
|
||||
|
|
|
|||
|
|
@ -1155,6 +1155,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
public synchronized void setManaPaymentMode(UUID playerId, boolean autoPayment) {
|
||||
Player player = state.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
player.getUserData().setManaPoolAutomatic(autoPayment);
|
||||
player.getManaPool().setAutoPayment(autoPayment);
|
||||
}
|
||||
}
|
||||
|
|
@ -1163,6 +1164,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
public synchronized void setManaPaymentModeRestricted(UUID playerId, boolean autoPaymentRestricted) {
|
||||
Player player = state.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
player.getUserData().setManaPoolAutomaticRestricted(autoPaymentRestricted);
|
||||
player.getManaPool().setAutoPaymentRestricted(autoPaymentRestricted);
|
||||
}
|
||||
}
|
||||
|
|
@ -1866,11 +1868,11 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void firePlayManaEvent(UUID playerId, String message) {
|
||||
public void firePlayManaEvent(UUID playerId, String message, Map<String, Serializable> options) {
|
||||
if (simulation) {
|
||||
return;
|
||||
}
|
||||
playerQueryEventSource.playMana(playerId, message);
|
||||
playerQueryEventSource.playMana(playerId, message, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -2122,7 +2124,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
// check if it's a creature and must be removed from combat
|
||||
if (perm.getCardType().contains(CardType.CREATURE) && this.getCombat() != null) {
|
||||
this.getCombat().removeFromCombat(perm.getId(), this);
|
||||
perm.removeFromCombat(this, true);
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -534,9 +534,10 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
player.reset();
|
||||
}
|
||||
battlefield.reset(game);
|
||||
combat.reset();
|
||||
combat.reset(game);
|
||||
this.reset();
|
||||
effects.apply(game);
|
||||
combat.checkForRemoveFromCombat(game);
|
||||
}
|
||||
|
||||
// Remove End of Combat effects
|
||||
|
|
@ -757,6 +758,13 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all waiting triggers (needed for turn end effects)
|
||||
*/
|
||||
public void clearTriggeredAbilities() {
|
||||
this.triggered.clear();
|
||||
}
|
||||
|
||||
public void addTriggeredAbility(TriggeredAbility ability) {
|
||||
this.triggered.add(ability);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ import mage.abilities.effects.RestrictionEffect;
|
|||
import mage.abilities.keyword.CanAttackOnlyAloneAbility;
|
||||
import mage.abilities.keyword.CantAttackAloneAbility;
|
||||
import mage.abilities.keyword.VigilanceAbility;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
|
|
@ -71,6 +72,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
|
||||
protected List<CombatGroup> groups = new ArrayList<>();
|
||||
protected Map<UUID, CombatGroup> blockingGroups = new HashMap<>();
|
||||
// player and plainswalker ids
|
||||
protected Set<UUID> defenders = new HashSet<>();
|
||||
// how many creatures attack defending player
|
||||
protected Map<UUID, Set<UUID>> numberCreaturesDefenderAttackedBy = new HashMap<>();
|
||||
|
|
@ -156,11 +158,26 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
this.useToughnessForDamageFilters.add(filter);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
public void reset(Game game) {
|
||||
this.useToughnessForDamage = false;
|
||||
this.useToughnessForDamageFilters.clear();
|
||||
}
|
||||
|
||||
public void checkForRemoveFromCombat(Game game) {
|
||||
for (UUID creatureId : getAttackers()) {
|
||||
Permanent creature = game.getPermanent(creatureId);
|
||||
if (!creature.getCardType().contains(CardType.CREATURE)) {
|
||||
removeFromCombat(creatureId, game, true);
|
||||
}
|
||||
}
|
||||
for (UUID creatureId : getBlockers()) {
|
||||
Permanent creature = game.getPermanent(creatureId);
|
||||
if (!creature.getCardType().contains(CardType.CREATURE)) {
|
||||
removeFromCombat(creatureId, game, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
groups.clear();
|
||||
blockingGroups.clear();
|
||||
|
|
@ -262,7 +279,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
}
|
||||
}
|
||||
if (mustAttack) {
|
||||
// check which defenders the forced to attck creature can attack without paying a cost
|
||||
// check which defenders the forced to attack creature can attack without paying a cost
|
||||
HashSet<UUID> defendersCostlessAttackable = new HashSet<>();
|
||||
defendersCostlessAttackable.addAll(defenders);
|
||||
for (UUID defenderId : defenders) {
|
||||
|
|
@ -500,6 +517,12 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
UUID attackingCreatureId = requirementEntry.getKey().mustBlockAttacker(ability, game);
|
||||
Player defender = game.getPlayer(possibleBlocker.getControllerId());
|
||||
if (attackingCreatureId != null && defender != null && possibleBlocker.canBlock(attackingCreatureId, game)) {
|
||||
// check if the possible blocker has to pay cost to block, if so don't force
|
||||
if (game.getContinuousEffects().checkIfThereArePayCostToAttackBlockEffects(
|
||||
GameEvent.getEvent(GameEvent.EventType.DECLARE_BLOCKER, attackingCreatureId, possibleBlocker.getId(), possibleBlocker.getControllerId()), game)) {
|
||||
// has cost to block to pay so remove this attacker
|
||||
continue;
|
||||
}
|
||||
if (creatureMustBlockAttackers.containsKey(possibleBlocker.getId())) {
|
||||
creatureMustBlockAttackers.get(possibleBlocker.getId()).add(attackingCreatureId);
|
||||
} else {
|
||||
|
|
@ -658,7 +681,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
|
||||
}
|
||||
|
||||
// check attacking creature mustBeBlockedByAtLeastOne
|
||||
// check if for attacking creatures with mustBeBlockedByAtLeastOne requirements are fulfilled
|
||||
for (UUID toBeBlockedCreatureId : mustBeBlockedByAtLeastOne.keySet()) {
|
||||
for (CombatGroup combatGroup : game.getCombat().getGroups()) {
|
||||
if (combatGroup.getBlockers().isEmpty() && combatGroup.getAttackers().contains(toBeBlockedCreatureId)) {
|
||||
|
|
@ -668,56 +691,27 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
if (toBeBlockedCreature != null) {
|
||||
// check if all possible blocker block other creatures they are forced to block
|
||||
// read through all possible blockers
|
||||
boolean possibleBlockerAvailable = false;
|
||||
for (UUID possibleBlockerId : mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId)) {
|
||||
Set<UUID> forcingAttackers = creatureMustBlockAttackers.get(possibleBlockerId);
|
||||
if (forcingAttackers == null) {
|
||||
// no other creature forces the blocker to block -> it's available
|
||||
possibleBlockerAvailable = true;
|
||||
break;
|
||||
String blockRequiredMessage = isCreatureDoingARequiredBlock(possibleBlockerId, mustBeBlockedByAtLeastOne, game);
|
||||
if (blockRequiredMessage != null) { // message means not required
|
||||
game.informPlayer(controller, blockRequiredMessage + "It's a requirement to block " + toBeBlockedCreature.getIdName());
|
||||
return false;
|
||||
}
|
||||
// get the attackers he blocks
|
||||
List<UUID> blockedAttackers = null;
|
||||
for (CombatGroup combatGroupToCheck : game.getCombat().getGroups()) {
|
||||
if (combatGroupToCheck.getBlockers().contains(possibleBlockerId)) {
|
||||
blockedAttackers = combatGroupToCheck.getAttackers();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (blockedAttackers == null) {
|
||||
// he blocks no other creature -> it's available
|
||||
possibleBlockerAvailable = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// get attackers forcing the possible blocker to block
|
||||
possibleBlockerAvailable = true;
|
||||
for (UUID blockedAttackerId : blockedAttackers) {
|
||||
if (creatureMustBlockAttackers.get(possibleBlockerId).contains(blockedAttackerId)) {
|
||||
possibleBlockerAvailable = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (possibleBlockerAvailable) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (possibleBlockerAvailable) {
|
||||
if (!game.isSimulation()) {
|
||||
game.informPlayer(controller, new StringBuilder(toBeBlockedCreature.getLogName()).append(" has to be blocked by at least one creature.").toString());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// take the first potential blocker from the set to block for the AI
|
||||
UUID blockingCreatureId = mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId).iterator().next();
|
||||
Permanent blockingCreature = game.getPermanent(blockingCreatureId);
|
||||
if (blockingCreature != null) {
|
||||
Player defender = game.getPlayer(blockingCreature.getControllerId());
|
||||
if (defender != null) {
|
||||
defender.declareBlocker(defender.getId(), blockingCreatureId, toBeBlockedCreatureId, game);
|
||||
for (UUID possibleBlockerId : mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId)) {
|
||||
String blockRequiredMessage = isCreatureDoingARequiredBlock(possibleBlockerId, mustBeBlockedByAtLeastOne, game);
|
||||
if (blockRequiredMessage != null) {
|
||||
// set the block
|
||||
Permanent possibleBlocker = game.getPermanent(possibleBlockerId);
|
||||
Player defender = game.getPlayer(possibleBlocker.getControllerId());
|
||||
if (defender != null) {
|
||||
defender.declareBlocker(defender.getId(), possibleBlockerId, toBeBlockedCreatureId, game);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -733,6 +727,21 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
if (creatureForcedToBlock == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
// // check if creature has to pay a cost to block so it's not mandatory to block
|
||||
// boolean removedAttacker = false;
|
||||
// for (Iterator<UUID> iterator = entry.getValue().iterator(); iterator.hasNext();) {
|
||||
// UUID possibleAttackerId = iterator.next();
|
||||
// if (game.getContinuousEffects().checkIfThereArePayCostToAttackBlockEffects(
|
||||
// GameEvent.getEvent(GameEvent.EventType.DECLARE_BLOCKER, possibleAttackerId, creatureForcedToBlock.getId(), creatureForcedToBlock.getControllerId()), game)) {
|
||||
// // has cost to block to pay so remove this attacker
|
||||
// iterator.remove();
|
||||
// removedAttacker = true;
|
||||
// }
|
||||
// }
|
||||
// if (removedAttacker && entry.getValue().isEmpty()) {
|
||||
// continue;
|
||||
// }
|
||||
// creature does not block -> not allowed
|
||||
if (creatureForcedToBlock.getBlocking() == 0) {
|
||||
blockIsValid = false;
|
||||
|
|
@ -764,7 +773,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
|
||||
}
|
||||
if (!blockIsValid) {
|
||||
sb.append(" ").append(creatureForcedToBlock.getLogName());
|
||||
sb.append(" ").append(creatureForcedToBlock.getIdName());
|
||||
}
|
||||
}
|
||||
if (sb.length() > 0) {
|
||||
|
|
@ -778,6 +787,48 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a possible creature for a block is already doing another
|
||||
* required block
|
||||
*
|
||||
* @param possibleBlockerId
|
||||
* @param mustBeBlockedByAtLeastOne
|
||||
* @param game
|
||||
* @return null block is required otherwise message with reason why not
|
||||
*/
|
||||
protected String isCreatureDoingARequiredBlock(UUID possibleBlockerId, Map<UUID, Set<UUID>> mustBeBlockedByAtLeastOne, Game game) {
|
||||
Permanent possibleBlocker = game.getPermanent(possibleBlockerId);
|
||||
if (possibleBlocker != null) {
|
||||
if (possibleBlocker.getBlocking() == 0) {
|
||||
return possibleBlocker.getIdName() + " does not block, but could block creatures with requirement to be blocked.";
|
||||
}
|
||||
Set<UUID> forcingAttackers = creatureMustBlockAttackers.get(possibleBlockerId);
|
||||
if (forcingAttackers == null) {
|
||||
// no other creature forces the blocker to block -> it's available
|
||||
// check now, if it already blocks a creature that mustBeBlockedByAtLeastOne
|
||||
if (possibleBlocker.getBlocking() > 0) {
|
||||
CombatGroup combatGroupOfPossibleBlocker = findGroupOfBlocker(possibleBlockerId);
|
||||
for (UUID blockedAttackerId : combatGroupOfPossibleBlocker.getAttackers()) {
|
||||
if (mustBeBlockedByAtLeastOne.containsKey(blockedAttackerId)) {
|
||||
// blocks a creature that has to be blocked by at least one
|
||||
if (combatGroupOfPossibleBlocker.getBlockers().size() == 1) {
|
||||
// the creature blocks alone already a creature that has to be blocked by at least one,
|
||||
// so this is ok
|
||||
return null;
|
||||
}
|
||||
// TODO: Check if the attacker is already blocked by another creature
|
||||
// and despite there is need that this attacker blocks this attacker also
|
||||
// I don't know why
|
||||
Permanent blockedAttacker = game.getPermanent(blockedAttackerId);
|
||||
return possibleBlocker.getIdName() + " blocks with other creatures " + blockedAttacker.getIdName() + ", which has to be blocked by only one creature. ";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the canBeBlockedCheckAfter RestrictionEffect Is the block still
|
||||
* valid after all block decisions are done
|
||||
|
|
@ -958,7 +1009,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean removeFromCombat(UUID creatureId, Game game) {
|
||||
public boolean removeFromCombat(UUID creatureId, Game game, boolean withInfo) {
|
||||
boolean result = false;
|
||||
Permanent creature = game.getPermanent(creatureId);
|
||||
if (creature != null) {
|
||||
|
|
@ -968,6 +1019,9 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
for (CombatGroup group : groups) {
|
||||
result |= group.remove(creatureId);
|
||||
}
|
||||
if (result && withInfo) {
|
||||
game.informPlayers(creature.getLogName() + " removed from combat");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -1015,6 +1069,15 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
return null;
|
||||
}
|
||||
|
||||
public CombatGroup findGroupOfBlocker(UUID blockerId) {
|
||||
for (CombatGroup group : groups) {
|
||||
if (group.getBlockers().contains(blockerId)) {
|
||||
return group;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// public int totalUnblockedDamage(Game game) {
|
||||
// int total = 0;
|
||||
// for (CombatGroup group : groups) {
|
||||
|
|
|
|||
|
|
@ -1,31 +1,30 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
* 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.io.Serializable;
|
||||
|
|
@ -52,9 +51,9 @@ public class GameEvent implements Serializable {
|
|||
public enum EventType {
|
||||
|
||||
//Game events
|
||||
//Game events
|
||||
BEGINNING,
|
||||
PREVENT_DAMAGE, PREVENTED_DAMAGE,
|
||||
|
||||
//Turn-based events
|
||||
PLAY_TURN, EXTRA_TURN,
|
||||
CHANGE_PHASE, PHASE_CHANGED,
|
||||
|
|
@ -78,15 +77,14 @@ public class GameEvent implements Serializable {
|
|||
CLEANUP_STEP_PRE, CLEANUP_STEP, CLEANUP_STEP_POST,
|
||||
EMPTY_MANA_POOL,
|
||||
AT_END_OF_TURN,
|
||||
|
||||
//player events
|
||||
/* ZONE_CHANGE
|
||||
targetId id of the zone changing object
|
||||
sourceId sourceId of the ability with the object moving effect
|
||||
playerId controller of the moved object
|
||||
amount not used for this event
|
||||
flag not used for this event
|
||||
*/
|
||||
targetId id of the zone changing object
|
||||
sourceId sourceId of the ability with the object moving effect
|
||||
playerId controller of the moved object
|
||||
amount not used for this event
|
||||
flag not used for this event
|
||||
*/
|
||||
ZONE_CHANGE,
|
||||
ZONE_CHANGE_GROUP,
|
||||
EMPTY_DRAW,
|
||||
|
|
@ -96,77 +94,69 @@ public class GameEvent implements Serializable {
|
|||
DISCARDED_CARD,
|
||||
CYCLE_CARD, CYCLED_CARD,
|
||||
CLASH, CLASHED,
|
||||
DAMAGE_PLAYER,
|
||||
|
||||
DAMAGE_PLAYER,
|
||||
/* DAMAGED_PLAYER
|
||||
targetId the id of the damged player
|
||||
sourceId sourceId of the ability which caused the damage
|
||||
playerId the id of the damged player
|
||||
amount amount of damage
|
||||
flag true = comabat damage - other damage = false
|
||||
*/
|
||||
targetId the id of the damged player
|
||||
sourceId sourceId of the ability which caused the damage
|
||||
playerId the id of the damged player
|
||||
amount amount of damage
|
||||
flag true = comabat damage - other damage = false
|
||||
*/
|
||||
DAMAGED_PLAYER,
|
||||
|
||||
DAMAGE_CAUSES_LIFE_LOSS,
|
||||
PLAYER_LIFE_CHANGE,
|
||||
GAIN_LIFE, GAINED_LIFE,
|
||||
LOSE_LIFE, LOST_LIFE,
|
||||
PLAY_LAND, LAND_PLAYED,
|
||||
CAST_SPELL,
|
||||
|
||||
CAST_SPELL,
|
||||
/* SPELL_CAST
|
||||
targetId id of the spell that's cast
|
||||
sourceId sourceId of the spell that's cast
|
||||
playerId player that casts the spell
|
||||
amount not used for this event
|
||||
flag not used for this event
|
||||
zone zone the spell is cast from
|
||||
*/
|
||||
targetId id of the spell that's cast
|
||||
sourceId sourceId of the spell that's cast
|
||||
playerId player that casts the spell
|
||||
amount not used for this event
|
||||
flag not used for this event
|
||||
zone zone the spell is cast from
|
||||
*/
|
||||
SPELL_CAST,
|
||||
|
||||
ACTIVATE_ABILITY, ACTIVATED_ABILITY,
|
||||
ADD_MANA, MANA_ADDED,
|
||||
|
||||
ADD_MANA, MANA_ADDED,
|
||||
/* MANA_PAYED
|
||||
targetId id if the ability the mana was paid for (not the sourceId)
|
||||
sourceId sourceId of the mana source
|
||||
playerId controller of the ability the mana was paid for
|
||||
amount not used for this event
|
||||
flag indicates a special condition
|
||||
*/
|
||||
MANA_PAYED,
|
||||
|
||||
targetId id if the ability the mana was paid for (not the sourceId)
|
||||
sourceId sourceId of the mana source
|
||||
playerId controller of the ability the mana was paid for
|
||||
amount not used for this event
|
||||
flag indicates a special condition
|
||||
data originalId of the mana producing ability
|
||||
*/
|
||||
MANA_PAYED,
|
||||
LOSES, LOST, WINS,
|
||||
TARGET, TARGETED,
|
||||
|
||||
/* COUNTER
|
||||
targetId id of the spell or id of stack ability
|
||||
sourceId sourceId of the ability countering the spell or stack ability
|
||||
playerId controller of the countered spell or stack ability
|
||||
amount not used for this event
|
||||
flag not used for this event
|
||||
*/
|
||||
targetId id of the spell or id of stack ability
|
||||
sourceId sourceId of the ability countering the spell or stack ability
|
||||
playerId controller of the countered spell or stack ability
|
||||
amount not used for this event
|
||||
flag not used for this event
|
||||
*/
|
||||
COUNTER,
|
||||
COUNTERED,
|
||||
DECLARING_ATTACKERS, DECLARED_ATTACKERS,
|
||||
DECLARE_ATTACKER,
|
||||
|
||||
/* ATTACKER_DECLARED
|
||||
targetId id of the defending player or planeswalker attacked
|
||||
sourceId id of the attacking creature
|
||||
playerId player defining the attacking creatures
|
||||
amount not used for this event
|
||||
flag not used for this event
|
||||
*/
|
||||
targetId id of the defending player or planeswalker attacked
|
||||
sourceId id of the attacking creature
|
||||
playerId player defining the attacking creatures
|
||||
amount not used for this event
|
||||
flag not used for this event
|
||||
*/
|
||||
ATTACKER_DECLARED,
|
||||
|
||||
/* DECLARING_BLOCKERS
|
||||
targetId attackerId
|
||||
sourceId not used for this event
|
||||
playerId attackerId
|
||||
amount not used for this event
|
||||
flag not used for this event
|
||||
*/
|
||||
targetId attackerId
|
||||
sourceId not used for this event
|
||||
playerId attackerId
|
||||
amount not used for this event
|
||||
flag not used for this event
|
||||
*/
|
||||
DECLARING_BLOCKERS,
|
||||
DECLARED_BLOCKERS,
|
||||
DECLARE_BLOCKER, BLOCKER_DECLARED,
|
||||
|
|
@ -176,7 +166,6 @@ public class GameEvent implements Serializable {
|
|||
ENCHANT_PLAYER, ENCHANTED_PLAYER,
|
||||
CAN_TAKE_MULLIGAN,
|
||||
FLIP_COIN, COIN_FLIPPED, SCRY, FATESEAL,
|
||||
|
||||
//permanent events
|
||||
ENTERS_THE_BATTLEFIELD,
|
||||
TAP, TAPPED, TAPPED_FOR_MANA,
|
||||
|
|
@ -185,24 +174,22 @@ public class GameEvent implements Serializable {
|
|||
UNFLIP, UNFLIPPED,
|
||||
TRANSFORM, TRANSFORMED,
|
||||
BECOMES_MONSTROUS,
|
||||
BECOMES_RENOWN,
|
||||
BECOMES_RENOWNED,
|
||||
PHASE_OUT, PHASED_OUT,
|
||||
PHASE_IN, PHASED_IN,
|
||||
TURNFACEUP, TURNEDFACEUP,
|
||||
TURNFACEDOWN, TURNEDFACEDOWN,
|
||||
DAMAGE_CREATURE, DAMAGED_CREATURE,
|
||||
DAMAGE_PLANESWALKER, DAMAGED_PLANESWALKER,
|
||||
DESTROY_PERMANENT,
|
||||
|
||||
DESTROY_PERMANENT,
|
||||
/* DESTROYED_PERMANENT
|
||||
targetId id of the destroyed creature
|
||||
sourceId sourceId of the ability with the destroy effect
|
||||
playerId controller of the creature
|
||||
amount not used for this event
|
||||
flag true if no regeneration is allowed
|
||||
*/
|
||||
targetId id of the destroyed creature
|
||||
sourceId sourceId of the ability with the destroy effect
|
||||
playerId controller of the creature
|
||||
amount not used for this event
|
||||
flag true if no regeneration is allowed
|
||||
*/
|
||||
DESTROYED_PERMANENT,
|
||||
|
||||
SACRIFICE_PERMANENT, SACRIFICED_PERMANENT,
|
||||
FIGHTED_PERMANENT,
|
||||
EXPLOITED_CREATURE,
|
||||
|
|
@ -211,31 +198,27 @@ public class GameEvent implements Serializable {
|
|||
ADD_COUNTER, COUNTER_ADDED,
|
||||
ADD_COUNTERS, COUNTERS_ADDED,
|
||||
COUNTER_REMOVED,
|
||||
LOSE_CONTROL,
|
||||
|
||||
LOSE_CONTROL,
|
||||
/* LOST_CONTROL
|
||||
targetId id of the creature that lost control
|
||||
sourceId id of the creature that lost control
|
||||
playerId player that controlles the creature before
|
||||
amount not used for this event
|
||||
flag not used for this event
|
||||
*/
|
||||
targetId id of the creature that lost control
|
||||
sourceId id of the creature that lost control
|
||||
playerId player that controlles the creature before
|
||||
amount not used for this event
|
||||
flag not used for this event
|
||||
*/
|
||||
LOST_CONTROL,
|
||||
GAIN_CONTROL, GAINED_CONTROL,
|
||||
CREATE_TOKEN,
|
||||
|
||||
/* REGENERATE
|
||||
targetId id of the creature to regenerate
|
||||
sourceId sourceId of the effect doing the regeneration
|
||||
playerId controller of the creature
|
||||
amount not used for this event
|
||||
flag not used for this event
|
||||
*/
|
||||
targetId id of the creature to regenerate
|
||||
sourceId sourceId of the effect doing the regeneration
|
||||
playerId controller of the creature
|
||||
amount not used for this event
|
||||
flag not used for this event
|
||||
*/
|
||||
REGENERATE,
|
||||
|
||||
REGENERATED,
|
||||
CHANGE_COLOR, COLOR_CHANGED,
|
||||
|
||||
//combat events
|
||||
COMBAT_DAMAGE_APPLIED,
|
||||
SELECTED_ATTACKER, SELECTED_BLOCKER;
|
||||
|
|
@ -268,7 +251,7 @@ public class GameEvent implements Serializable {
|
|||
}
|
||||
|
||||
public static GameEvent getEvent(EventType type, UUID targetId, UUID playerId, String data, int amount) {
|
||||
GameEvent event = getEvent(type, targetId,playerId);
|
||||
GameEvent event = getEvent(type, targetId, playerId);
|
||||
event.setAmount(amount);
|
||||
event.setData(data);
|
||||
return event;
|
||||
|
|
@ -310,7 +293,6 @@ public class GameEvent implements Serializable {
|
|||
this.flag = flag;
|
||||
}
|
||||
|
||||
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
|
|
@ -326,17 +308,18 @@ public class GameEvent implements Serializable {
|
|||
public void setZone(Zone zone) {
|
||||
this.zone = zone;
|
||||
}
|
||||
|
||||
/**
|
||||
* used to store which replacement effects were already applied to an event
|
||||
* or or any modified events that may replace it
|
||||
*
|
||||
* 614.5. A replacement effect doesn't invoke itself repeatedly; it gets only one
|
||||
* opportunity to affect an event or any modified events that may replace it.
|
||||
* Example: A player controls two permanents, each with an ability that reads
|
||||
* "If a creature you control would deal damage to a creature or player, it
|
||||
* deals double that damage to that creature or player instead." A creature
|
||||
* that normally deals 2 damage will deal 8 damage--not just 4, and not an
|
||||
* infinite amount.
|
||||
* 614.5. A replacement effect doesn't invoke itself repeatedly; it gets
|
||||
* only one opportunity to affect an event or any modified events that may
|
||||
* replace it. Example: A player controls two permanents, each with an
|
||||
* ability that reads "If a creature you control would deal damage to a
|
||||
* creature or player, it deals double that damage to that creature or
|
||||
* player instead." A creature that normally deals 2 damage will deal 8
|
||||
* damage--not just 4, and not an infinite amount.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,43 +1,46 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
* 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.io.Serializable;
|
||||
import java.util.EventObject;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.ActivatedAbility;
|
||||
import mage.abilities.TriggeredAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.Cards;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import mage.choices.Choice;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -46,6 +49,7 @@ import mage.choices.Choice;
|
|||
public class PlayerQueryEvent extends EventObject implements ExternalEvent, Serializable {
|
||||
|
||||
public enum QueryType {
|
||||
|
||||
ASK, CHOOSE_CHOICE, CHOOSE_ABILITY, CHOOSE_MODE, PICK_TARGET, PICK_ABILITY, SELECT, PLAY_MANA, PLAY_X_MANA, AMOUNT, PICK_CARD, CONSTRUCT, CHOOSE_PILE, PERSONAL_MESSAGE
|
||||
}
|
||||
|
||||
|
|
@ -67,7 +71,6 @@ public class PlayerQueryEvent extends EventObject implements ExternalEvent, Seri
|
|||
private List<? extends Card> pile2;
|
||||
private Choice choice;
|
||||
|
||||
|
||||
private PlayerQueryEvent(UUID playerId, String message, List<? extends Ability> abilities, Set<String> choices, Set<UUID> targets, Cards cards, QueryType queryType, int min, int max, boolean required, Map<String, Serializable> options) {
|
||||
this(playerId, message, abilities, choices, targets, cards, queryType, min, max, required);
|
||||
this.options = options;
|
||||
|
|
@ -197,15 +200,15 @@ public class PlayerQueryEvent extends EventObject implements ExternalEvent, Seri
|
|||
return new PlayerQueryEvent(playerId, message, null, null, null, null, QueryType.SELECT, 0, 0, false, options);
|
||||
}
|
||||
|
||||
public static PlayerQueryEvent playManaEvent(UUID playerId, String message) {
|
||||
return new PlayerQueryEvent(playerId, message, null, null, null, null, QueryType.PLAY_MANA, 0, 0, false);
|
||||
public static PlayerQueryEvent playManaEvent(UUID playerId, String message, Map<String, Serializable> options) {
|
||||
return new PlayerQueryEvent(playerId, message, null, null, null, null, QueryType.PLAY_MANA, 0, 0, false, options);
|
||||
}
|
||||
|
||||
public static PlayerQueryEvent playXManaEvent(UUID playerId, String message) {
|
||||
return new PlayerQueryEvent(playerId, message, null, null, null, null, QueryType.PLAY_X_MANA, 0, 0, false);
|
||||
}
|
||||
|
||||
public static PlayerQueryEvent amountEvent(UUID playerId, String message, int min , int max) {
|
||||
public static PlayerQueryEvent amountEvent(UUID playerId, String message, int min, int max) {
|
||||
return new PlayerQueryEvent(playerId, message, null, null, null, null, QueryType.AMOUNT, min, max, false);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,42 +1,43 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
* 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.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.ActivatedAbility;
|
||||
import mage.abilities.TriggeredAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.Cards;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import mage.choices.Choice;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -44,7 +45,8 @@ import mage.choices.Choice;
|
|||
*/
|
||||
public class PlayerQueryEventSource implements EventSource<PlayerQueryEvent>, Serializable {
|
||||
|
||||
protected final EventDispatcher<PlayerQueryEvent> dispatcher = new EventDispatcher<PlayerQueryEvent>() {};
|
||||
protected final EventDispatcher<PlayerQueryEvent> dispatcher = new EventDispatcher<PlayerQueryEvent>() {
|
||||
};
|
||||
|
||||
@Override
|
||||
public void addListener(Listener<PlayerQueryEvent> listener) {
|
||||
|
|
@ -100,8 +102,8 @@ public class PlayerQueryEventSource implements EventSource<PlayerQueryEvent>, Se
|
|||
dispatcher.fireEvent(PlayerQueryEvent.targetEvent(playerId, message, perms, required));
|
||||
}
|
||||
|
||||
public void playMana(UUID playerId, String message) {
|
||||
dispatcher.fireEvent(PlayerQueryEvent.playManaEvent(playerId, message));
|
||||
public void playMana(UUID playerId, String message, Map<String, Serializable> options) {
|
||||
dispatcher.fireEvent(PlayerQueryEvent.playManaEvent(playerId, message, options));
|
||||
}
|
||||
|
||||
public void amount(UUID playerId, String message, int min, int max) {
|
||||
|
|
|
|||
|
|
@ -75,8 +75,8 @@ public interface Permanent extends Card, Controllable {
|
|||
boolean isMonstrous();
|
||||
void setMonstrous(boolean value);
|
||||
|
||||
boolean isRenown();
|
||||
void setRenown(boolean value);
|
||||
boolean isRenowned();
|
||||
void setRenowned(boolean value);
|
||||
|
||||
void setCardNumber(int cid);
|
||||
void setExpansionSetCode(String expansionSetCode);
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
protected boolean flipped;
|
||||
protected boolean transformed;
|
||||
protected boolean monstrous;
|
||||
protected boolean renown;
|
||||
protected boolean renowned;
|
||||
protected boolean manifested = false;
|
||||
protected boolean morphed = false;
|
||||
protected UUID originalControllerId;
|
||||
|
|
@ -176,6 +176,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
this.maxBlockedBy = permanent.maxBlockedBy;
|
||||
this.transformed = permanent.transformed;
|
||||
this.monstrous = permanent.monstrous;
|
||||
this.renowned = permanent.renowned;
|
||||
this.pairedCard = permanent.pairedCard;
|
||||
this.timesLoyaltyUsed = permanent.timesLoyaltyUsed;
|
||||
|
||||
|
|
@ -1199,11 +1200,9 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
@Override
|
||||
public boolean removeFromCombat(Game game, boolean withInfo) {
|
||||
if (this.isAttacking() || this.blocking > 0) {
|
||||
if (game.getCombat().removeFromCombat(objectId, game) && withInfo && !game.isSimulation()) {
|
||||
game.informPlayers(new StringBuilder(this.getLogName()).append(" removed from combat").toString());
|
||||
}
|
||||
return game.getCombat().removeFromCombat(objectId, game, withInfo);
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -1267,13 +1266,13 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isRenown() {
|
||||
return this.renown;
|
||||
public boolean isRenowned() {
|
||||
return this.renowned;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRenown(boolean value) {
|
||||
this.renown = value;
|
||||
public void setRenowned(boolean value) {
|
||||
this.renowned = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -1,31 +1,30 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
* 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.stack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -101,10 +100,10 @@ public class Spell extends StackObjImpl implements Card {
|
|||
|
||||
public Spell(final Spell spell) {
|
||||
this.id = spell.id;
|
||||
for (SpellAbility spellAbility: spell.spellAbilities) {
|
||||
for (SpellAbility spellAbility : spell.spellAbilities) {
|
||||
this.spellAbilities.add(spellAbility.copy());
|
||||
}
|
||||
for (Card spellCard: spell.spellCards) {
|
||||
for (Card spellCard : spell.spellCards) {
|
||||
this.spellCards.add(spellCard.copy());
|
||||
}
|
||||
if (spell.spellAbilities.get(0).equals(spell.ability)) {
|
||||
|
|
@ -124,7 +123,6 @@ public class Spell extends StackObjImpl implements Card {
|
|||
this.color = spell.color.copy();
|
||||
}
|
||||
|
||||
|
||||
public boolean activate(Game game, boolean noMana) {
|
||||
if (!spellAbilities.get(0).activate(game, noMana)) {
|
||||
return false;
|
||||
|
|
@ -132,7 +130,7 @@ public class Spell extends StackObjImpl implements Card {
|
|||
// if there are more abilities (fused split spell) or first ability added new abilities (splice), activate the additional abilities
|
||||
boolean ignoreAbility = true;
|
||||
boolean payNoMana = noMana;
|
||||
for (SpellAbility spellAbility: spellAbilities) {
|
||||
for (SpellAbility spellAbility : spellAbilities) {
|
||||
// costs for spliced abilities were added to main spellAbility, so pay no mana for spliced abilities
|
||||
payNoMana |= spellAbility.getSpellAbilityType().equals(SpellAbilityType.SPLICE);
|
||||
if (ignoreAbility) {
|
||||
|
|
@ -174,19 +172,19 @@ public class Spell extends StackObjImpl implements Card {
|
|||
result = false;
|
||||
boolean legalParts = false;
|
||||
// check for legal parts
|
||||
for(SpellAbility spellAbility: this.spellAbilities) {
|
||||
// if muliple modes are selected, and there are modes with targets, then at least one mode has to have a legal target or
|
||||
// When resolving a fused split spell with multiple targets, treat it as you would any spell with multiple targets.
|
||||
// If all targets are illegal when the spell tries to resolve, the spell is countered and none of its effects happen.
|
||||
for (SpellAbility spellAbility : this.spellAbilities) {
|
||||
// if muliple modes are selected, and there are modes with targets, then at least one mode has to have a legal target or
|
||||
// When resolving a fused split spell with multiple targets, treat it as you would any spell with multiple targets.
|
||||
// If all targets are illegal when the spell tries to resolve, the spell is countered and none of its effects happen.
|
||||
// If at least one target is still legal at that time, the spell resolves, but an illegal target can't perform any actions
|
||||
// or have any actions performed on it.
|
||||
// or have any actions performed on it.
|
||||
legalParts |= spellAbilityHasLegalParts(spellAbility, game);
|
||||
}
|
||||
// resolve if legal parts
|
||||
if (legalParts) {
|
||||
for(SpellAbility spellAbility: this.spellAbilities) {
|
||||
for (SpellAbility spellAbility : this.spellAbilities) {
|
||||
if (spellAbilityHasLegalParts(spellAbility, game)) {
|
||||
for (UUID modeId :spellAbility.getModes().getSelectedModes()) {
|
||||
for (UUID modeId : spellAbility.getModes().getSelectedModes()) {
|
||||
spellAbility.getModes().setActiveMode(modeId);
|
||||
if (spellAbility.getTargets().stillLegal(spellAbility, game)) {
|
||||
if (!spellAbility.getSpellAbilityType().equals(SpellAbilityType.SPLICE)) {
|
||||
|
|
@ -216,14 +214,14 @@ public class Spell extends StackObjImpl implements Card {
|
|||
if (ability.getTargets().stillLegal(ability, game)) {
|
||||
updateOptionalCosts(0);
|
||||
boolean bestow = this.getSpellAbility() instanceof BestowAbility;
|
||||
if (bestow) {
|
||||
if (bestow) {
|
||||
// Must be removed first time, after that will be removed by continous effect
|
||||
// Otherwise effects like evolve trigger from creature comes into play event
|
||||
card.getCardType().remove(CardType.CREATURE);
|
||||
card.getSubtype().add("Aura");
|
||||
card.getSubtype().add("Aura");
|
||||
}
|
||||
if (card.putOntoBattlefield(game, fromZone, ability.getSourceId(), controllerId)) {
|
||||
if (bestow) {
|
||||
if (bestow) {
|
||||
// card will be copied during putOntoBattlefield, so the card of CardPermanent has to be changed
|
||||
// TODO: Find a better way to prevent bestow creatures from being effected by creature affecting abilities
|
||||
Permanent permanent = game.getPermanent(card.getId());
|
||||
|
|
@ -234,16 +232,16 @@ public class Spell extends StackObjImpl implements Card {
|
|||
}
|
||||
card.getCardType().add(CardType.CREATURE);
|
||||
card.getSubtype().remove("Aura");
|
||||
}
|
||||
}
|
||||
return ability.resolve(game);
|
||||
}
|
||||
if (bestow) {
|
||||
if (bestow) {
|
||||
card.getCardType().add(CardType.CREATURE);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Aura has no legal target and its a bestow enchantment -> Add it to battlefield as creature
|
||||
if (this.getSpellAbility() instanceof BestowAbility) {
|
||||
if (this.getSpellAbility() instanceof BestowAbility) {
|
||||
updateOptionalCosts(0);
|
||||
result = card.putOntoBattlefield(game, fromZone, ability.getSourceId(), controllerId);
|
||||
return result;
|
||||
|
|
@ -263,17 +261,17 @@ public class Spell extends StackObjImpl implements Card {
|
|||
}
|
||||
|
||||
private boolean spellAbilityHasLegalParts(SpellAbility spellAbility, Game game) {
|
||||
if (spellAbility.getModes().getSelectedModes().size() > 1) {
|
||||
if (spellAbility.getModes().getSelectedModes().size() > 1) {
|
||||
boolean targetedMode = false;
|
||||
boolean legalTargetedMode = false;
|
||||
for (UUID modeId :spellAbility.getModes().getSelectedModes()) {
|
||||
for (UUID modeId : spellAbility.getModes().getSelectedModes()) {
|
||||
spellAbility.getModes().setActiveMode(modeId);
|
||||
if (spellAbility.getTargets().size() > 0) {
|
||||
targetedMode = true;
|
||||
if (spellAbility.getTargets().stillLegal(spellAbility, game)) {
|
||||
legalTargetedMode = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (targetedMode) {
|
||||
return legalTargetedMode;
|
||||
|
|
@ -283,11 +281,11 @@ public class Spell extends StackObjImpl implements Card {
|
|||
return spellAbility.getTargets().stillLegal(spellAbility, game);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* As we have ability in the stack, we need to update optional costs in original card.
|
||||
* This information will be used later by effects, e.g. to determine whether card was kicked or not.
|
||||
* E.g. Desolation Angel
|
||||
* As we have ability in the stack, we need to update optional costs in
|
||||
* original card. This information will be used later by effects, e.g. to
|
||||
* determine whether card was kicked or not. E.g. Desolation Angel
|
||||
*/
|
||||
private void updateOptionalCosts(int index) {
|
||||
Ability abilityOrig = spellCards.get(index).getAbilities().get(spellAbilities.get(index).getId());
|
||||
|
|
@ -307,9 +305,7 @@ public class Spell extends StackObjImpl implements Card {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void counter(UUID sourceId, Game game) {
|
||||
this.countered = true;
|
||||
|
|
@ -319,10 +315,10 @@ public class Spell extends StackObjImpl implements Card {
|
|||
Ability counteringAbility = null;
|
||||
MageObject counteringObject = game.getObject(sourceId);
|
||||
if (counteringObject instanceof StackObject) {
|
||||
counteringAbility = ((StackObject)counteringObject).getStackAbility();
|
||||
counteringAbility = ((StackObject) counteringObject).getStackAbility();
|
||||
}
|
||||
player.moveCards(card, Zone.STACK, Zone.GRAVEYARD, counteringAbility, game);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -340,18 +336,18 @@ public class Spell extends StackObjImpl implements Card {
|
|||
public String getName() {
|
||||
return card.getName();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getIdName() {
|
||||
String idName;
|
||||
if (card != null) {
|
||||
idName = card.getId().toString().substring(0,3);
|
||||
idName = card.getId().toString().substring(0, 3);
|
||||
} else {
|
||||
idName = getId().toString().substring(0,3);
|
||||
idName = getId().toString().substring(0, 3);
|
||||
}
|
||||
return getName() + " ["+idName+"]";
|
||||
return getName() + " [" + idName + "]";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getLogName() {
|
||||
return GameLog.getColoredObjectIdName(card);
|
||||
|
|
@ -363,7 +359,8 @@ public class Spell extends StackObjImpl implements Card {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) {}
|
||||
public void setName(String name) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rarity getRarity() {
|
||||
|
|
@ -415,7 +412,6 @@ public class Spell extends StackObjImpl implements Card {
|
|||
return card.getSupertype();
|
||||
}
|
||||
|
||||
|
||||
public List<SpellAbility> getSpellAbilities() {
|
||||
return spellAbilities;
|
||||
}
|
||||
|
|
@ -429,7 +425,7 @@ public class Spell extends StackObjImpl implements Card {
|
|||
public Abilities<Ability> getAbilities(Game game) {
|
||||
return card.getAbilities(game);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasAbility(UUID abilityId, Game game) {
|
||||
return card.hasAbility(abilityId, game);
|
||||
|
|
@ -446,9 +442,11 @@ public class Spell extends StackObjImpl implements Card {
|
|||
}
|
||||
|
||||
/**
|
||||
* 202.3b When calculating the converted mana cost of an object with an {X} in its
|
||||
* mana cost, X is treated as 0 while the object is not on the stack, and X is
|
||||
* treated as the number chosen for it while the object is on the stack.
|
||||
* 202.3b When calculating the converted mana cost of an object with an {X}
|
||||
* in its mana cost, X is treated as 0 while the object is not on the stack,
|
||||
* and X is treated as the number chosen for it while the object is on the
|
||||
* stack.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
|
|
@ -457,9 +455,9 @@ public class Spell extends StackObjImpl implements Card {
|
|||
if (faceDown) {
|
||||
return 0;
|
||||
}
|
||||
for (Ability spellAbility: spellAbilities) {
|
||||
for (Ability spellAbility : spellAbilities) {
|
||||
int xMultiplier = 0;
|
||||
for (String symbolString :spellAbility.getManaCosts().getSymbols()) {
|
||||
for (String symbolString : spellAbility.getManaCosts().getSymbols()) {
|
||||
int index = symbolString.indexOf("{X}");
|
||||
while (index != -1) {
|
||||
xMultiplier++;
|
||||
|
|
@ -471,14 +469,14 @@ public class Spell extends StackObjImpl implements Card {
|
|||
cmc += spellAbility.getManaCostsToPay().getX() * xMultiplier;
|
||||
} else {
|
||||
cmc += spellAbility.getManaCosts().convertedManaCost() + spellAbility.getManaCostsToPay().getX() * xMultiplier;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.getSpellAbility().getSpellAbilityType().equals(SpellAbilityType.BASE_ALTERNATE)) {
|
||||
cmc += getCard().getManaCost().convertedManaCost();
|
||||
}
|
||||
return cmc;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MageInt getPower() {
|
||||
return card.getPower();
|
||||
|
|
@ -503,7 +501,8 @@ public class Spell extends StackObjImpl implements Card {
|
|||
spellAbilities.add(spellAbility);
|
||||
}
|
||||
|
||||
public void addAbility(Ability ability) {}
|
||||
public void addAbility(Ability ability) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpellAbility getSpellAbility() {
|
||||
|
|
@ -512,14 +511,15 @@ public class Spell extends StackObjImpl implements Card {
|
|||
|
||||
public void setControllerId(UUID controllerId) {
|
||||
this.ability.setControllerId(controllerId);
|
||||
for (SpellAbility spellAbility: spellAbilities) {
|
||||
for (SpellAbility spellAbility : spellAbilities) {
|
||||
spellAbility.setControllerId(controllerId);
|
||||
}
|
||||
this.controllerId = controllerId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOwnerId(UUID controllerId) {}
|
||||
public void setOwnerId(UUID controllerId) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRules() {
|
||||
|
|
@ -608,7 +608,7 @@ public class Spell extends StackObjImpl implements Card {
|
|||
card.adjustChoices(ability, game);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void adjustCosts(Ability ability, Game game) {
|
||||
if (card != null) {
|
||||
|
|
@ -623,7 +623,6 @@ public class Spell extends StackObjImpl implements Card {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean moveToZone(Zone zone, UUID sourceId, Game game, boolean flag) {
|
||||
return moveToZone(zone, sourceId, game, flag, null);
|
||||
|
|
@ -635,7 +634,7 @@ public class Spell extends StackObjImpl implements Card {
|
|||
// If a copy of a card is in any zone other than the stack or the battlefield, it ceases to exist.
|
||||
// These are state-based actions. See rule 704.
|
||||
if (this.isCopiedSpell() && !zone.equals(Zone.STACK)) {
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
throw new UnsupportedOperationException("Unsupported operation");
|
||||
}
|
||||
|
|
@ -646,7 +645,7 @@ public class Spell extends StackObjImpl implements Card {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, ArrayList<UUID> appliedEffects) {
|
||||
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, ArrayList<UUID> appliedEffects) {
|
||||
ZoneChangeEvent event = new ZoneChangeEvent(this.getId(), sourceId, this.getOwnerId(), Zone.STACK, Zone.EXILED, appliedEffects);
|
||||
if (!game.replaceEvent(event)) {
|
||||
game.getStack().remove(this);
|
||||
|
|
@ -667,8 +666,6 @@ public class Spell extends StackObjImpl implements Card {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId) {
|
||||
throw new UnsupportedOperationException("Unsupported operation");
|
||||
|
|
@ -711,7 +708,7 @@ public class Spell extends StackObjImpl implements Card {
|
|||
|
||||
@Override
|
||||
public void updateZoneChangeCounter(Game game) {
|
||||
throw new UnsupportedOperationException("Unsupported operation");
|
||||
throw new UnsupportedOperationException("Unsupported operation");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -762,7 +759,8 @@ public class Spell extends StackObjImpl implements Card {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void build() {}
|
||||
public void build() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Counters getCounters(Game game) {
|
||||
|
|
@ -815,7 +813,7 @@ public class Spell extends StackObjImpl implements Card {
|
|||
|
||||
@Override
|
||||
public void setSpellAbility(SpellAbility ability) {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
}
|
||||
|
||||
public boolean isCountered() {
|
||||
|
|
|
|||
|
|
@ -1,31 +1,30 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
* 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.stack;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
|
|
@ -44,11 +43,12 @@ public class SpellStack extends ArrayDeque<StackObject> {
|
|||
|
||||
protected Date dateLastAdded;
|
||||
|
||||
public SpellStack () {}
|
||||
public SpellStack() {
|
||||
}
|
||||
|
||||
public SpellStack(final SpellStack stack) {
|
||||
|
||||
for (StackObject spell: stack) {
|
||||
|
||||
for (StackObject spell : stack) {
|
||||
this.addLast(spell.copy());
|
||||
}
|
||||
}
|
||||
|
|
@ -67,7 +67,7 @@ public class SpellStack extends ArrayDeque<StackObject> {
|
|||
}
|
||||
|
||||
public void remove(StackObject object) {
|
||||
for (StackObject spell: this) {
|
||||
for (StackObject spell : this) {
|
||||
if (spell.getId().equals(object.getId())) {
|
||||
super.remove(spell);
|
||||
return;
|
||||
|
|
@ -77,7 +77,7 @@ public class SpellStack extends ArrayDeque<StackObject> {
|
|||
|
||||
public boolean counter(UUID objectId, UUID sourceId, Game game) {
|
||||
// the counter logic is copied by some spells to handle replacement effects of the countered spell
|
||||
// so if logic is changed here check those spells for needed changes too
|
||||
// so if logic is changed here check those spells for needed changes too
|
||||
// Concerned cards to check: Hinder, Spell Crumple
|
||||
StackObject stackObject = getStackObject(objectId);
|
||||
MageObject sourceObject = game.getObject(sourceId);
|
||||
|
|
@ -87,7 +87,7 @@ public class SpellStack extends ArrayDeque<StackObject> {
|
|||
if (targetSourceObject == null) {
|
||||
targetSourceName = "[Object not found]";
|
||||
} else {
|
||||
targetSourceName = game.getObject(stackObject.getSourceId()).getName();
|
||||
targetSourceName = game.getObject(stackObject.getSourceId()).getLogName();
|
||||
}
|
||||
if (stackObject instanceof Spell) {
|
||||
counteredObjectName = targetSourceName;
|
||||
|
|
@ -95,12 +95,12 @@ public class SpellStack extends ArrayDeque<StackObject> {
|
|||
counteredObjectName = "Ability (" + stackObject.getStackAbility().getRule(targetSourceName) + ") of " + targetSourceName;
|
||||
}
|
||||
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.COUNTER, objectId, sourceId, stackObject.getControllerId()))) {
|
||||
if ( stackObject instanceof Spell ) {
|
||||
game.rememberLKI(objectId, Zone.STACK, (Spell)stackObject);
|
||||
if (stackObject instanceof Spell) {
|
||||
game.rememberLKI(objectId, Zone.STACK, (Spell) stackObject);
|
||||
} else {
|
||||
this.remove(stackObject);
|
||||
this.remove(stackObject);
|
||||
}
|
||||
stackObject.counter(sourceId, game);
|
||||
stackObject.counter(sourceId, game);
|
||||
if (!game.isSimulation()) {
|
||||
game.informPlayers(counteredObjectName + " is countered by " + sourceObject.getLogName());
|
||||
}
|
||||
|
|
@ -114,7 +114,7 @@ public class SpellStack extends ArrayDeque<StackObject> {
|
|||
}
|
||||
|
||||
public StackObject getStackObject(UUID id) {
|
||||
for (StackObject stackObject: this) {
|
||||
for (StackObject stackObject : this) {
|
||||
UUID objectId = stackObject.getId();
|
||||
if (objectId.equals(id)) {
|
||||
return stackObject;
|
||||
|
|
@ -128,10 +128,10 @@ public class SpellStack extends ArrayDeque<StackObject> {
|
|||
}
|
||||
|
||||
public Spell getSpell(UUID id) {
|
||||
for (StackObject stackObject: this) {
|
||||
for (StackObject stackObject : this) {
|
||||
if (stackObject instanceof Spell) {
|
||||
if (stackObject.getId().equals(id) || stackObject.getSourceId().equals(id)) {
|
||||
return (Spell)stackObject;
|
||||
return (Spell) stackObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,31 +1,30 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
* 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.turn;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
|
@ -56,7 +55,7 @@ public class Turn implements Serializable {
|
|||
private final List<Phase> phases = new ArrayList<>();
|
||||
private boolean declareAttackersStepStarted = false;
|
||||
private boolean endTurn; // indicates that an end turn effect has resolved.
|
||||
|
||||
|
||||
public Turn() {
|
||||
endTurn = false;
|
||||
phases.add(new BeginningPhase());
|
||||
|
|
@ -71,7 +70,7 @@ public class Turn implements Serializable {
|
|||
this.currentPhase = turn.currentPhase.copy();
|
||||
}
|
||||
this.activePlayerId = turn.activePlayerId;
|
||||
for (Phase phase: turn.phases) {
|
||||
for (Phase phase : turn.phases) {
|
||||
this.phases.add(phase.copy());
|
||||
}
|
||||
this.declareAttackersStepStarted = turn.declareAttackersStepStarted;
|
||||
|
|
@ -91,7 +90,7 @@ public class Turn implements Serializable {
|
|||
}
|
||||
|
||||
public Phase getPhase(TurnPhase turnPhase) {
|
||||
for (Phase phase: phases) {
|
||||
for (Phase phase : phases) {
|
||||
if (phase.getType() == turnPhase) {
|
||||
return phase;
|
||||
}
|
||||
|
|
@ -133,7 +132,7 @@ public class Turn implements Serializable {
|
|||
this.activePlayerId = activePlayer.getId();
|
||||
resetCounts();
|
||||
game.getPlayer(activePlayer.getId()).beginTurn(game);
|
||||
for (Phase phase: phases) {
|
||||
for (Phase phase : phases) {
|
||||
if (game.isPaused() || game.gameOver(null)) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -142,11 +141,11 @@ public class Turn implements Serializable {
|
|||
game.fireEvent(new GameEvent(GameEvent.EventType.PHASE_CHANGED, activePlayer.getId(), null, activePlayer.getId()));
|
||||
if (!game.getState().getTurnMods().skipPhase(activePlayer.getId(), currentPhase.getType())) {
|
||||
if (phase.play(game, activePlayer.getId())) {
|
||||
if(game.executingRollback()) {
|
||||
if (game.executingRollback()) {
|
||||
return;
|
||||
}
|
||||
//20091005 - 500.4/703.4n
|
||||
game.emptyManaPools();
|
||||
game.emptyManaPools();
|
||||
game.saveState(false);
|
||||
|
||||
//20091005 - 500.8
|
||||
|
|
@ -208,7 +207,7 @@ public class Turn implements Serializable {
|
|||
}
|
||||
|
||||
private void resetCounts() {
|
||||
for (Phase phase: phases) {
|
||||
for (Phase phase : phases) {
|
||||
phase.resetCount();
|
||||
}
|
||||
}
|
||||
|
|
@ -223,7 +222,7 @@ public class Turn implements Serializable {
|
|||
return false;
|
||||
}
|
||||
Phase phase;
|
||||
switch(extraPhase) {
|
||||
switch (extraPhase) {
|
||||
case BEGINNING:
|
||||
phase = new BeginningPhase();
|
||||
break;
|
||||
|
|
@ -251,52 +250,51 @@ public class Turn implements Serializable {
|
|||
}
|
||||
|
||||
/*protected void playExtraTurns(Game game) {
|
||||
while (game.getState().getTurnMods().extraTurn(activePlayerId)) {
|
||||
this.play(game, activePlayerId);
|
||||
}
|
||||
}*/
|
||||
/**
|
||||
* Used for some spells with end turn effect (e.g. Time Stop).
|
||||
*
|
||||
* @param game
|
||||
* @param activePlayerId
|
||||
*/
|
||||
while (game.getState().getTurnMods().extraTurn(activePlayerId)) {
|
||||
this.play(game, activePlayerId);
|
||||
}
|
||||
}*/
|
||||
/**
|
||||
* Used for some spells with end turn effect (e.g. Time Stop).
|
||||
*
|
||||
* @param game
|
||||
* @param activePlayerId
|
||||
*/
|
||||
public void endTurn(Game game, UUID activePlayerId) {
|
||||
// Ending the turn this way (Time Stop) means the following things happen in order:
|
||||
|
||||
// Ending the turn this way (Time Stop) means the following things happen in order:
|
||||
|
||||
setEndTurnRequested(true);
|
||||
|
||||
// 1) All spells and abilities on the stack are exiled. This includes Time Stop, though it will continue to resolve.
|
||||
// It also includes spells and abilities that can't be countered.
|
||||
|
||||
// 1) All spells and abilities on the stack are exiled. This includes Time Stop, though it will continue to resolve.
|
||||
// It also includes spells and abilities that can't be countered.
|
||||
while (!game.getStack().isEmpty()) {
|
||||
StackObject stackObject = game.getStack().removeLast();
|
||||
if (stackObject instanceof Spell) {
|
||||
((Spell) stackObject).moveToExile(null, "", null, game);
|
||||
}
|
||||
}
|
||||
// 2) All attacking and blocking creatures are removed from combat.
|
||||
for (UUID attackerId: game.getCombat().getAttackers()) {
|
||||
// 2) All attacking and blocking creatures are removed from combat.
|
||||
for (UUID attackerId : game.getCombat().getAttackers()) {
|
||||
Permanent permanent = game.getPermanent(attackerId);
|
||||
if (permanent != null) {
|
||||
permanent.removeFromCombat(game);
|
||||
}
|
||||
game.getCombat().removeAttacker(attackerId, game);
|
||||
}
|
||||
for (UUID blockerId: game.getCombat().getBlockers()) {
|
||||
for (UUID blockerId : game.getCombat().getBlockers()) {
|
||||
Permanent permanent = game.getPermanent(blockerId);
|
||||
if (permanent != null) {
|
||||
permanent.removeFromCombat(game);
|
||||
}
|
||||
}
|
||||
|
||||
// 3) State-based actions are checked. No player gets priority, and no triggered abilities are put onto the stack.
|
||||
|
||||
// 3) State-based actions are checked. No player gets priority, and no triggered abilities are put onto the stack.
|
||||
// seems like trigger events have to be removed: http://tabakrules.tumblr.com/post/122350751009/days-undoing-has-been-officially-spoiled-on
|
||||
game.getState().clearTriggeredAbilities();
|
||||
game.checkStateAndTriggered(); // triggered effects don't go to stack because check of endTurnRequested
|
||||
|
||||
// 4) The current phase and/or step ends.
|
||||
|
||||
// 4) The current phase and/or step ends.
|
||||
// The game skips straight to the cleanup step. The cleanup step happens in its entirety.
|
||||
// this is caused by the endTurnRequest state
|
||||
|
||||
}
|
||||
|
||||
public boolean isDeclareAttackersStepStarted() {
|
||||
|
|
@ -310,23 +308,23 @@ public class Turn implements Serializable {
|
|||
public void setEndTurnRequested(boolean endTurn) {
|
||||
this.endTurn = endTurn;
|
||||
}
|
||||
|
||||
|
||||
public boolean isEndTurnRequested() {
|
||||
return endTurn;
|
||||
}
|
||||
|
||||
|
||||
public Turn copy() {
|
||||
return new Turn(this);
|
||||
}
|
||||
|
||||
|
||||
public String getValue(int turnNum) {
|
||||
StringBuilder sb = threadLocalBuilder.get();
|
||||
sb.append("[").append(turnNum)
|
||||
.append(":").append(currentPhase.getType())
|
||||
.append(":").append(currentPhase.getStep().getType())
|
||||
.append("]");
|
||||
.append(":").append(currentPhase.getType())
|
||||
.append(":").append(currentPhase.getStep().getType())
|
||||
.append("]");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -227,8 +227,6 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
protected UserData userData;
|
||||
protected MatchPlayer matchPlayer;
|
||||
|
||||
protected String flagName;
|
||||
|
||||
/**
|
||||
* During some steps we can't play anything
|
||||
*/
|
||||
|
|
@ -2043,6 +2041,9 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
|
||||
@Override
|
||||
public void declareBlocker(UUID defenderId, UUID blockerId, UUID attackerId, Game game) {
|
||||
if (isHuman()) {
|
||||
setStoredBookmark(game.bookmarkState());
|
||||
}
|
||||
Permanent blocker = game.getPermanent(blockerId);
|
||||
CombatGroup group = game.getCombat().findGroup(attackerId);
|
||||
if (blocker != null && group != null && group.canBlock(blocker, game)) {
|
||||
|
|
@ -2459,6 +2460,22 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
}
|
||||
}
|
||||
// check if it's possible to play the top card of a library
|
||||
for (UUID playerInRangeId : game.getState().getPlayersInRange(getId(), game)) {
|
||||
Player player = game.getPlayer(playerInRangeId);
|
||||
if (player != null) {
|
||||
if (player.isTopCardRevealed() && player.getLibrary().size() > 0) {
|
||||
Card card = player.getLibrary().getFromTop(game);
|
||||
if (game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, getId(), game)) {
|
||||
for (ActivatedAbility ability : card.getAbilities().getActivatedAbilities(Zone.HAND)) {
|
||||
if (ability instanceof SpellAbility || ability instanceof PlayLandAbility) {
|
||||
playable.add(ability);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// eliminate duplicate activated abilities
|
||||
Map<String, Ability> playableActivated = new HashMap<>();
|
||||
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(playerId)) {
|
||||
|
|
@ -2697,6 +2714,8 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
@Override
|
||||
public void setUserData(UserData userData) {
|
||||
this.userData = userData;
|
||||
getManaPool().setAutoPayment(userData.isManaPoolAutomatic());
|
||||
getManaPool().setAutoPaymentRestricted(userData.isManaPoolAutomaticRestricted());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -2895,6 +2914,12 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
result |= moveCardToHandWithInfo(card, source == null ? null : source.getSourceId(), game, fromZone);
|
||||
}
|
||||
return result;
|
||||
case BATTLEFIELD:
|
||||
result = false;
|
||||
for (Card card : cards) {
|
||||
result |= putOntoBattlefieldWithInfo(card, game, fromZone, source == null ? null : source.getSourceId());
|
||||
}
|
||||
return result;
|
||||
default:
|
||||
throw new UnsupportedOperationException("to Zone not supported yet");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,10 +17,12 @@ public class UserData implements Serializable {
|
|||
protected UserSkipPrioritySteps userSkipPrioritySteps;
|
||||
protected String flagName;
|
||||
protected boolean askMoveToGraveOrder;
|
||||
protected boolean manaPoolAutomatic;
|
||||
protected boolean manaPoolAutomaticRestricted;
|
||||
|
||||
public UserData(UserGroup userGroup, int avatarId, boolean showAbilityPickerForced,
|
||||
boolean allowRequestShowHandCards, boolean confirmEmptyManaPool, UserSkipPrioritySteps userSkipPrioritySteps,
|
||||
String flagName, boolean askMoveToGraveOrder) {
|
||||
String flagName, boolean askMoveToGraveOrder, boolean manaPoolAutomatic, boolean manaPoolAutomaticRestricted) {
|
||||
this.groupId = userGroup.getGroupId();
|
||||
this.avatarId = avatarId;
|
||||
this.showAbilityPickerForced = showAbilityPickerForced;
|
||||
|
|
@ -29,6 +31,8 @@ public class UserData implements Serializable {
|
|||
this.confirmEmptyManaPool = confirmEmptyManaPool;
|
||||
this.flagName = flagName;
|
||||
this.askMoveToGraveOrder = askMoveToGraveOrder;
|
||||
this.manaPoolAutomatic = manaPoolAutomatic;
|
||||
this.manaPoolAutomaticRestricted = manaPoolAutomaticRestricted;
|
||||
}
|
||||
|
||||
public void update(UserData userData) {
|
||||
|
|
@ -40,10 +44,12 @@ public class UserData implements Serializable {
|
|||
this.confirmEmptyManaPool = userData.confirmEmptyManaPool;
|
||||
this.flagName = userData.flagName;
|
||||
this.askMoveToGraveOrder = userData.askMoveToGraveOrder;
|
||||
this.manaPoolAutomatic = userData.manaPoolAutomatic;
|
||||
this.manaPoolAutomaticRestricted = userData.manaPoolAutomaticRestricted;
|
||||
}
|
||||
|
||||
public static UserData getDefaultUserDataView() {
|
||||
return new UserData(UserGroup.DEFAULT, 0, false, false, true, null, "world.png", false);
|
||||
return new UserData(UserGroup.DEFAULT, 0, false, false, true, null, "world.png", false, true, true);
|
||||
}
|
||||
|
||||
public void setGroupId(int groupId) {
|
||||
|
|
@ -98,6 +104,10 @@ public class UserData implements Serializable {
|
|||
return flagName;
|
||||
}
|
||||
|
||||
public void setFlagName(String flagName) {
|
||||
this.flagName = flagName;
|
||||
}
|
||||
|
||||
public boolean askMoveToGraveOrder() {
|
||||
return askMoveToGraveOrder;
|
||||
}
|
||||
|
|
@ -106,4 +116,20 @@ public class UserData implements Serializable {
|
|||
this.askMoveToGraveOrder = askMoveToGraveOrder;
|
||||
}
|
||||
|
||||
public boolean isManaPoolAutomatic() {
|
||||
return manaPoolAutomatic;
|
||||
}
|
||||
|
||||
public void setManaPoolAutomatic(boolean manaPoolAutomatic) {
|
||||
this.manaPoolAutomatic = manaPoolAutomatic;
|
||||
}
|
||||
|
||||
public boolean isManaPoolAutomaticRestricted() {
|
||||
return manaPoolAutomaticRestricted;
|
||||
}
|
||||
|
||||
public void setManaPoolAutomaticRestricted(boolean manaPoolAutomaticRestricted) {
|
||||
this.manaPoolAutomaticRestricted = manaPoolAutomaticRestricted;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
93
Mage/src/mage/watchers/common/CreatureWasCastWatcher.java
Normal file
93
Mage/src/mage/watchers/common/CreatureWasCastWatcher.java
Normal file
|
|
@ -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.watchers.common;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class CreatureWasCastWatcher extends Watcher {
|
||||
|
||||
private final Set<UUID> creaturesCasted = new HashSet<>();
|
||||
|
||||
public CreatureWasCastWatcher() {
|
||||
super("CreatureWasCast", WatcherScope.GAME);
|
||||
}
|
||||
|
||||
public CreatureWasCastWatcher(final CreatureWasCastWatcher watcher) {
|
||||
super(watcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.SPELL_CAST) {
|
||||
Spell spell = (Spell) game.getObject(event.getTargetId());
|
||||
if (spell != null) {
|
||||
Card card = game.getCard(spell.getSourceId());
|
||||
if (card != null && card.getCardType().contains(CardType.CREATURE)) {
|
||||
creaturesCasted.add(card.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (event.getType() == GameEvent.EventType.ZONE_CHANGE
|
||||
&& ((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) {
|
||||
Card card = game.getCard(event.getTargetId());
|
||||
if (card != null && card.getCardType().contains(CardType.CREATURE)) {
|
||||
creaturesCasted.remove(card.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean wasCreatureCastThisTurn(UUID creatureSourceId) {
|
||||
return creaturesCasted.contains(creatureSourceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
creaturesCasted.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CreatureWasCastWatcher copy() {
|
||||
return new CreatureWasCastWatcher(this);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue