mirror of
https://github.com/magefree/mage.git
synced 2025-12-28 22:42:03 -08:00
Merge branch 'master' of https://github.com/magefree/mage
This commit is contained in:
commit
0ddc11f4dc
85 changed files with 3845 additions and 759 deletions
98
Mage/src/mage/abilities/dynamicvalue/common/ParleyCount.java
Normal file
98
Mage/src/mage/abilities/dynamicvalue/common/ParleyCount.java
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* 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.dynamicvalue.common;
|
||||
|
||||
import java.io.ObjectStreamException;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.MageSingleton;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
* Don't use this for continuous effects because it applies a reveal effect!
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class ParleyCount implements DynamicValue, MageSingleton {
|
||||
|
||||
private static final ParleyCount fINSTANCE = new ParleyCount();
|
||||
|
||||
private Object readResolve() throws ObjectStreamException {
|
||||
return fINSTANCE;
|
||||
}
|
||||
|
||||
public static ParleyCount getInstance() {
|
||||
return fINSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||
// Each player reveals the top card of his or her library. For each nonland card revealed this way
|
||||
int parleyValue = 0;
|
||||
MageObject sourceObject = game.getObject(sourceAbility.getSourceId());
|
||||
if (sourceObject != null) {
|
||||
for (UUID playerId : game.getState().getPlayerList(sourceAbility.getControllerId())) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
Card card = player.getLibrary().getFromTop(game);
|
||||
if (card != null) {
|
||||
if (!card.getCardType().contains(CardType.LAND)) {
|
||||
parleyValue++;
|
||||
}
|
||||
player.revealCards(sourceObject.getIdName() + " (" + player.getName() + ")", new CardsImpl(card), game);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return parleyValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamicValue copy() {
|
||||
return fINSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "1";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "Parley";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -51,13 +51,15 @@ import mage.target.common.TargetCardInGraveyard;
|
|||
/**
|
||||
* Cards with the Aura subtype don't change the zone they are in, if there is no
|
||||
* valid target on the battlefield. Also, when entering the battlefield and it
|
||||
* was not cast (so from Zone != Hand), this effect gets the target to whitch to attach it
|
||||
* and adds the Aura the the battlefield and attachs it to the target.
|
||||
* was not cast (so from Zone != Hand), this effect gets the target to whitch to
|
||||
* attach it and adds the Aura the the battlefield and attachs it to the target.
|
||||
* The "attachTo:" value in game state has to be set therefore.
|
||||
*
|
||||
* If no "attachTo:" value is defined, the controlling player has to chose the aura target.
|
||||
*
|
||||
* This effect is automatically added to ContinuousEffects at the start of a game
|
||||
* If no "attachTo:" value is defined, the controlling player has to chose the
|
||||
* aura target.
|
||||
*
|
||||
* This effect is automatically added to ContinuousEffects at the start of a
|
||||
* game
|
||||
*
|
||||
* @author North
|
||||
*/
|
||||
|
|
@ -93,7 +95,7 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
|
|||
return false;
|
||||
}
|
||||
// Aura enters the battlefield attached
|
||||
Object object = game.getState().getValue("attachTo:"+card.getId());
|
||||
Object object = game.getState().getValue("attachTo:" + card.getId());
|
||||
if (object != null && object instanceof PermanentCard) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -113,7 +115,7 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
|
|||
targetId = stackAbility.getEffects().get(0).getTargetPointer().getFirst(game, stackAbility);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (targetId == null) {
|
||||
Target target = card.getSpellAbility().getTargets().get(0);
|
||||
enchantCardInGraveyard = target instanceof TargetCardInGraveyard;
|
||||
|
|
@ -122,9 +124,10 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
|
|||
}
|
||||
Player player = game.getPlayer(card.getOwnerId());
|
||||
Outcome auraOutcome = Outcome.BoostCreature;
|
||||
Ability: for (Ability ability:card.getAbilities()) {
|
||||
Ability:
|
||||
for (Ability ability : card.getAbilities()) {
|
||||
if (ability instanceof SpellAbility) {
|
||||
for (Effect effect: ability.getEffects()) {
|
||||
for (Effect effect : ability.getEffects()) {
|
||||
if (effect instanceof AttachEffect) {
|
||||
auraOutcome = effect.getOutcome();
|
||||
break Ability;
|
||||
|
|
@ -167,13 +170,16 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
|
|||
game.getBattlefield().addPermanent(permanent);
|
||||
card.setZone(Zone.BATTLEFIELD, game);
|
||||
game.applyEffects();
|
||||
permanent.entersBattlefield(event.getSourceId(), game, fromZone, true);
|
||||
boolean entered = permanent.entersBattlefield(event.getSourceId(), game, fromZone, true);
|
||||
game.applyEffects();
|
||||
if (!entered) {
|
||||
return false;
|
||||
}
|
||||
game.fireEvent(new ZoneChangeEvent(permanent, controllerId, fromZone, Zone.BATTLEFIELD));
|
||||
|
||||
if (targetCard != null) {
|
||||
permanent.attachTo(targetCard.getId(), game);
|
||||
}
|
||||
}
|
||||
if (targetPermanent != null) {
|
||||
targetPermanent.addAttachment(permanent.getId(), game);
|
||||
}
|
||||
|
|
@ -183,7 +189,7 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
|
||||
|
|
@ -192,7 +198,7 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
|
|||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (((ZoneChangeEvent) event).getToZone().equals(Zone.BATTLEFIELD)
|
||||
&& !(((ZoneChangeEvent) event).getFromZone().equals(Zone.HAND)) ) {
|
||||
&& !(((ZoneChangeEvent) event).getFromZone().equals(Zone.HAND))) {
|
||||
Card card = game.getCard(event.getTargetId());
|
||||
if (card != null && card.getCardType().contains(CardType.ENCHANTMENT) && card.hasSubtype("Aura")) {
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* 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.Mode;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.StaticValue;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LoneFox
|
||||
*/
|
||||
public class DamageTargetControllerEffect extends OneShotEffect {
|
||||
|
||||
protected DynamicValue amount;
|
||||
protected boolean preventable;
|
||||
|
||||
public DamageTargetControllerEffect(int amount) {
|
||||
this(new StaticValue(amount), true);
|
||||
}
|
||||
|
||||
public DamageTargetControllerEffect(int amount, boolean preventable) {
|
||||
this(new StaticValue(amount), preventable);
|
||||
}
|
||||
|
||||
public DamageTargetControllerEffect(DynamicValue amount) {
|
||||
this(amount, true);
|
||||
}
|
||||
|
||||
public DamageTargetControllerEffect(DynamicValue amount, boolean preventable) {
|
||||
super(Outcome.Damage);
|
||||
this.amount = amount;
|
||||
this.preventable = preventable;
|
||||
}
|
||||
|
||||
public DamageTargetControllerEffect(final DamageTargetControllerEffect effect) {
|
||||
super(effect);
|
||||
amount = effect.amount.copy();
|
||||
preventable = effect.preventable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DamageTargetControllerEffect copy() {
|
||||
return new DamageTargetControllerEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if(permanent != null) {
|
||||
Player targetController = game.getPlayer(permanent.getControllerId());
|
||||
if(targetController != null) {
|
||||
targetController.damage(amount.calculate(game, source, this), source.getSourceId(), game, false, preventable);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(Mode mode) {
|
||||
if (staticText != null && !staticText.isEmpty()) {
|
||||
return staticText;
|
||||
}
|
||||
String text = "{this} deals " + amount.getMessage() + " damage to target "
|
||||
+ mode.getTargets().get(0).getTargetName() + "'s controller";
|
||||
if(!preventable) {
|
||||
text += ". The damage can't be prevented";
|
||||
}
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* 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.effects.ReplacementEffectImpl;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LoneFox
|
||||
*/
|
||||
public class DiscardOntoBattlefieldEffect extends ReplacementEffectImpl {
|
||||
|
||||
public DiscardOntoBattlefieldEffect() {
|
||||
super(Duration.EndOfGame, Outcome.PutCardInPlay);
|
||||
staticText = "If a spell or ability an opponent controls causes you to discard {this}, put it onto the battlefield instead of putting it into your graveyard";
|
||||
}
|
||||
|
||||
public DiscardOntoBattlefieldEffect(final DiscardOntoBattlefieldEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiscardOntoBattlefieldEffect copy() {
|
||||
return new DiscardOntoBattlefieldEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == EventType.ZONE_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (event.getTargetId().equals(source.getSourceId())) {
|
||||
ZoneChangeEvent zcEvent = (ZoneChangeEvent) event;
|
||||
if (zcEvent.getFromZone() == Zone.HAND && zcEvent.getToZone() == Zone.GRAVEYARD) {
|
||||
StackObject spell = game.getStack().getStackObject(event.getSourceId());
|
||||
if (spell != null && game.getOpponents(source.getControllerId()).contains(spell.getControllerId())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
Card card = game.getCard(source.getSourceId());
|
||||
if (card != null) {
|
||||
Player owner = game.getPlayer(card.getOwnerId());
|
||||
if (owner != null) {
|
||||
if (owner.putOntoBattlefieldWithInfo(card, game, Zone.HAND, source.getSourceId())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
69
Mage/src/mage/abilities/effects/common/UntapAllEffect.java
Normal file
69
Mage/src/mage/abilities/effects/common/UntapAllEffect.java
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class UntapAllEffect extends OneShotEffect {
|
||||
|
||||
private final FilterPermanent filter;
|
||||
|
||||
public UntapAllEffect(FilterPermanent filter) {
|
||||
super(Outcome.Untap);
|
||||
staticText = "untap all " + filter.getMessage();
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
public UntapAllEffect(final UntapAllEffect effect) {
|
||||
super(effect);
|
||||
this.filter = effect.filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
|
||||
permanent.untap(game);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UntapAllEffect copy() {
|
||||
return new UntapAllEffect(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* 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.continuous;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.constants.TargetController;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LoneFox
|
||||
*/
|
||||
public class PlayWithHandRevealedEffect extends ContinuousEffectImpl {
|
||||
|
||||
private TargetController who;
|
||||
|
||||
public PlayWithHandRevealedEffect(TargetController who) {
|
||||
super(Duration.WhileOnBattlefield, Layer.PlayerEffects, SubLayer.NA, Outcome.Detriment);
|
||||
this.who = who;
|
||||
}
|
||||
|
||||
public PlayWithHandRevealedEffect(final PlayWithHandRevealedEffect effect) {
|
||||
super(effect);
|
||||
who = effect.who;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
Iterable<UUID> affectedPlayers;
|
||||
switch(who) {
|
||||
case ANY:
|
||||
affectedPlayers = controller.getInRange();
|
||||
break;
|
||||
case OPPONENT:
|
||||
affectedPlayers = game.getOpponents(source.getControllerId());
|
||||
break;
|
||||
case YOU:
|
||||
ArrayList tmp = new ArrayList<UUID>();
|
||||
tmp.add(source.getControllerId());
|
||||
affectedPlayers = tmp;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
for(UUID playerID: affectedPlayers) {
|
||||
Player player = game.getPlayer(playerID);
|
||||
if (player != null) {
|
||||
player.revealCards(player.getName() + "'s hand cards", player.getHand(), game, false);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlayWithHandRevealedEffect copy() {
|
||||
return new PlayWithHandRevealedEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(Mode mode) {
|
||||
if (staticText != null && !staticText.isEmpty()) {
|
||||
return staticText;
|
||||
}
|
||||
switch(who) {
|
||||
case ANY:
|
||||
return "Players play with their hands revealed";
|
||||
case OPPONENT:
|
||||
return "Your opponents play with their hands revealed";
|
||||
case YOU:
|
||||
return "Play with your hand revealed";
|
||||
default:
|
||||
return "Unknown TargetController for PlayWithHandRevealedEffect";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -27,12 +27,12 @@
|
|||
*/
|
||||
package mage.abilities.effects.common.discard;
|
||||
|
||||
import mage.constants.Outcome;
|
||||
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.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
|
@ -98,7 +98,7 @@ public class DiscardControllerEffect extends OneShotEffect {
|
|||
}
|
||||
|
||||
private void setText() {
|
||||
StringBuilder sb = new StringBuilder("Discard ");
|
||||
StringBuilder sb = new StringBuilder("discard ");
|
||||
if (amount.toString().equals("1")) {
|
||||
sb.append("a");
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -10,20 +10,29 @@ import mage.abilities.effects.OneShotEffect;
|
|||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.game.turn.TurnMod;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Mael
|
||||
*/
|
||||
public class SkipNextTurnSourceEffect extends OneShotEffect {
|
||||
|
||||
|
||||
int numberOfTurns;
|
||||
|
||||
public SkipNextTurnSourceEffect() {
|
||||
this(1);
|
||||
}
|
||||
|
||||
public SkipNextTurnSourceEffect(int numberOfTurns) {
|
||||
super(Outcome.Neutral);
|
||||
staticText = "You skip your next turn";
|
||||
this.numberOfTurns = numberOfTurns;
|
||||
staticText = "you skip your next " + (numberOfTurns == 1 ? "turn" : CardUtil.numberToText(numberOfTurns) + " turns");
|
||||
}
|
||||
|
||||
public SkipNextTurnSourceEffect(final SkipNextTurnSourceEffect effect) {
|
||||
super(effect);
|
||||
this.numberOfTurns = effect.numberOfTurns;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -33,7 +42,9 @@ public class SkipNextTurnSourceEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
game.getState().getTurnMods().add(new TurnMod(source.getControllerId(), true));
|
||||
for (int i = 0; i < numberOfTurns; i++) {
|
||||
game.getState().getTurnMods().add(new TurnMod(source.getControllerId(), true));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -421,13 +421,17 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
game.setZone(objectId, Zone.BATTLEFIELD);
|
||||
game.setScopeRelevant(true);
|
||||
game.applyEffects();
|
||||
permanent.entersBattlefield(sourceId, game, event.getFromZone(), true);
|
||||
boolean entered = permanent.entersBattlefield(sourceId, game, event.getFromZone(), true);
|
||||
game.setScopeRelevant(false);
|
||||
game.applyEffects();
|
||||
if (flag) {
|
||||
permanent.setTapped(true);
|
||||
if (entered) {
|
||||
if (flag) {
|
||||
permanent.setTapped(true);
|
||||
}
|
||||
event.setTarget(permanent);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
event.setTarget(permanent);
|
||||
break;
|
||||
default:
|
||||
Card sourceCard = game.getCard(sourceId);
|
||||
|
|
@ -603,11 +607,13 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
game.setScopeRelevant(true);
|
||||
permanent.setTapped(tapped);
|
||||
permanent.setFaceDown(facedown, game);
|
||||
permanent.entersBattlefield(sourceId, game, event.getFromZone(), true);
|
||||
boolean entered = permanent.entersBattlefield(sourceId, game, event.getFromZone(), true);
|
||||
game.setScopeRelevant(false);
|
||||
game.applyEffects();
|
||||
game.addSimultaneousEvent(new ZoneChangeEvent(permanent, event.getPlayerId(), fromZone, Zone.BATTLEFIELD));
|
||||
return true;
|
||||
if (entered) {
|
||||
game.addSimultaneousEvent(new ZoneChangeEvent(permanent, event.getPlayerId(), fromZone, Zone.BATTLEFIELD));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (facedown) {
|
||||
this.setFaceDown(false, game);
|
||||
|
|
|
|||
|
|
@ -117,16 +117,11 @@ public abstract class ExpansionSet implements Serializable {
|
|||
// if the packs are too big, it removes the first cards.
|
||||
// since it adds lands then commons before uncommons
|
||||
// and rares this should be the least disruptive.
|
||||
|
||||
List<Card> theBooster = this.createBooster();
|
||||
List<CardInfo> commons = getCardsByRarity(Rarity.COMMON);
|
||||
int iterations = 0;
|
||||
while (15 > theBooster.size() && !commons.isEmpty()) {
|
||||
|
||||
while (15 > theBooster.size()) {
|
||||
addToBooster(theBooster, commons);
|
||||
iterations++;
|
||||
if (iterations > 14) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (theBooster.size() > 15) {
|
||||
|
|
@ -301,9 +296,8 @@ public abstract class ExpansionSet implements Serializable {
|
|||
savedCardsInfos = CardRepository.instance.findCards(criteria);
|
||||
savedCards.put(rarity, savedCardsInfos);
|
||||
}
|
||||
List<CardInfo> cards = new ArrayList<>();
|
||||
cards.addAll(savedCardsInfos);
|
||||
return cards;
|
||||
// Return a copy of the saved cards information, as not to modify the original.
|
||||
return new ArrayList<>(savedCardsInfos);
|
||||
}
|
||||
|
||||
public List<CardInfo> getSpecialCommon() {
|
||||
|
|
|
|||
|
|
@ -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.constants;
|
||||
|
||||
/**
|
||||
|
|
@ -33,15 +32,17 @@ package mage.constants;
|
|||
* @author LevelX2
|
||||
*/
|
||||
public enum AbilityWord {
|
||||
|
||||
BLOODRUSH("Bloodrush"),
|
||||
CONSTELLATION("Constellation"),
|
||||
FEROCIOUS("Ferocious"),
|
||||
FEROCIOUS("Ferocious"),
|
||||
FORMIDABLE("Formidable"),
|
||||
GRANDEUR("Grandeur"),
|
||||
HELLBENT("Hellbent"),
|
||||
HEROIC("Heroic"),
|
||||
FORMIDABLE("Formidable"),
|
||||
LANDFALL("Landfall"),
|
||||
METALCRAFT("Metalcraft"),
|
||||
GRANDEUR("Grandeur"),
|
||||
PARLEY("Parley"),
|
||||
RAID("Raid");
|
||||
|
||||
private final String text;
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
protected GameState state;
|
||||
private transient Stack<Integer> savedStates = new Stack<>();
|
||||
protected transient GameStates gameStates = new GameStates();
|
||||
// game states to allow player roll back
|
||||
// game states to allow player rollback
|
||||
protected transient Map<Integer, GameState> gameStatesRollBack = new HashMap<>();
|
||||
protected boolean executingRollback;
|
||||
|
||||
|
|
@ -700,7 +700,6 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
if (!playTurn(playerByOrder)) {
|
||||
break;
|
||||
}
|
||||
state.setTurnNum(state.getTurnNum() + 1);
|
||||
}
|
||||
playExtraTurns();
|
||||
playerByOrder = playerList.getNext(this);
|
||||
|
|
@ -741,7 +740,6 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
informPlayers(extraPlayer.getLogName() + " takes an extra turn");
|
||||
}
|
||||
playTurn(extraPlayer);
|
||||
state.setTurnNum(state.getTurnNum() + 1);
|
||||
}
|
||||
}
|
||||
extraTurn = getNextExtraTurn();
|
||||
|
|
@ -768,6 +766,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
|
||||
private boolean playTurn(Player player) {
|
||||
boolean skipTurn = false;
|
||||
do {
|
||||
if (executingRollback) {
|
||||
executingRollback = false;
|
||||
|
|
@ -781,41 +780,23 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
state.setActivePlayerId(player.getId());
|
||||
saveRollBackGameState();
|
||||
}
|
||||
this.logStartOfTurn(player);
|
||||
if (checkStopOnTurnOption()) {
|
||||
return false;
|
||||
}
|
||||
state.getTurn().play(this, player);
|
||||
skipTurn = state.getTurn().play(this, player);
|
||||
} while (executingRollback);
|
||||
|
||||
if (isPaused() || gameOver(null)) {
|
||||
return false;
|
||||
}
|
||||
endOfTurn();
|
||||
if (!skipTurn) {
|
||||
endOfTurn();
|
||||
state.setTurnNum(state.getTurnNum() + 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void logStartOfTurn(Player player) {
|
||||
StringBuilder sb = new StringBuilder("Turn ").append(state.getTurnNum()).append(" ");
|
||||
sb.append(player.getLogName());
|
||||
sb.append(" (");
|
||||
int delimiter = this.getPlayers().size() - 1;
|
||||
for (Player gamePlayer : this.getPlayers().values()) {
|
||||
sb.append(gamePlayer.getLife());
|
||||
int poison = gamePlayer.getCounters().getCount(CounterType.POISON);
|
||||
if (poison > 0) {
|
||||
sb.append("[P:").append(poison).append("]");
|
||||
}
|
||||
if (delimiter > 0) {
|
||||
sb.append(" - ");
|
||||
delimiter--;
|
||||
}
|
||||
}
|
||||
sb.append(")");
|
||||
fireStatusEvent(sb.toString(), true);
|
||||
}
|
||||
|
||||
private boolean checkStopOnTurnOption() {
|
||||
if (gameOptions.stopOnTurn != null && gameOptions.stopAtStep == PhaseStep.UNTAP) {
|
||||
if (gameOptions.stopOnTurn.equals(state.getTurnNum())) {
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import java.io.Serializable;
|
|||
import mage.constants.PhaseStep;
|
||||
|
||||
/**
|
||||
* Game options for Mage game.
|
||||
* Mainly used in tests to configure {@link GameImpl} with specific params.
|
||||
* Game options for Mage game. Mainly used in tests to configure
|
||||
* {@link GameImpl} with specific params.
|
||||
*
|
||||
* @author ayratn
|
||||
*/
|
||||
|
|
@ -23,8 +23,8 @@ public class GameOptions implements Serializable {
|
|||
public boolean testMode = false;
|
||||
|
||||
/**
|
||||
* Defines the turn number game should stop on.
|
||||
* By default, is null meaning that game shouldn't stop on any specific turn.
|
||||
* Defines the turn number game should stop on. By default, is null meaning
|
||||
* that game shouldn't stop on any specific turn.
|
||||
*/
|
||||
public Integer stopOnTurn = null;
|
||||
|
||||
|
|
@ -37,9 +37,9 @@ public class GameOptions implements Serializable {
|
|||
* If true, library won't be shuffled at the beginning of the game
|
||||
*/
|
||||
public boolean skipInitShuffling = false;
|
||||
|
||||
|
||||
/**
|
||||
* If true, players can roll back turn if all players agree
|
||||
* If true, players can rollback turn if all players agree
|
||||
*/
|
||||
public boolean rollbackTurnsAllowed = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.ActivatedAbility;
|
||||
import mage.abilities.DelayedTriggeredAbilities;
|
||||
import mage.abilities.DelayedTriggeredAbility;
|
||||
import mage.abilities.MageSingleton;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.SpecialActions;
|
||||
import mage.abilities.StaticAbility;
|
||||
|
|
@ -856,13 +857,19 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
* @param ability
|
||||
*/
|
||||
public void addOtherAbility(Card attachedTo, Ability ability) {
|
||||
ability.setSourceId(attachedTo.getId());
|
||||
ability.setControllerId(attachedTo.getOwnerId());
|
||||
Ability newAbility;
|
||||
if (ability instanceof MageSingleton) {
|
||||
newAbility = ability;
|
||||
} else {
|
||||
newAbility = ability.copy();
|
||||
}
|
||||
newAbility.setSourceId(attachedTo.getId());
|
||||
newAbility.setControllerId(attachedTo.getOwnerId());
|
||||
if (!cardState.containsKey(attachedTo.getId())) {
|
||||
cardState.put(attachedTo.getId(), new CardState());
|
||||
}
|
||||
cardState.get(attachedTo.getId()).addAbility(ability);
|
||||
addAbility(ability, attachedTo.getId(), attachedTo);
|
||||
cardState.get(attachedTo.getId()).addAbility(newAbility);
|
||||
addAbility(newAbility, attachedTo.getId(), attachedTo);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -810,19 +810,21 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
// 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;
|
||||
if (combatGroupOfPossibleBlocker != null) {
|
||||
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. ";
|
||||
}
|
||||
// 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. ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -947,9 +949,12 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
if (!canDefenderBeAttacked(attackerId, defenderId, game)) {
|
||||
return false;
|
||||
}
|
||||
Permanent attacker = game.getPermanent(attackerId);
|
||||
if (attacker == null) {
|
||||
return false;
|
||||
}
|
||||
CombatGroup newGroup = new CombatGroup(defenderId, defender != null, defender != null ? defender.getControllerId() : defenderId);
|
||||
newGroup.attackers.add(attackerId);
|
||||
Permanent attacker = game.getPermanent(attackerId);
|
||||
attacker.setAttacking(true);
|
||||
groups.add(newGroup);
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -119,7 +119,20 @@ public class GameEvent implements Serializable {
|
|||
*/
|
||||
SPELL_CAST,
|
||||
ACTIVATE_ABILITY, ACTIVATED_ABILITY,
|
||||
ADD_MANA, MANA_ADDED,
|
||||
/* ADD_MANA
|
||||
targetId id of the ability that added the mana
|
||||
sourceId sourceId of the ability that added the mana
|
||||
playerId player the mana is added to the mana pool for
|
||||
mana the mana added
|
||||
*/
|
||||
ADD_MANA,
|
||||
/* MANA_ADDED
|
||||
targetId id of the ability that added the mana
|
||||
sourceId sourceId of the ability that added the mana
|
||||
playerId player the mana is added to the mana pool for
|
||||
mana the mana added
|
||||
*/
|
||||
MANA_ADDED,
|
||||
/* MANA_PAYED
|
||||
targetId id if the ability the mana was paid for (not the sourceId)
|
||||
sourceId sourceId of the mana source
|
||||
|
|
|
|||
|
|
@ -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.permanent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -45,60 +44,89 @@ import mage.game.Game;
|
|||
public interface Permanent extends Card, Controllable {
|
||||
|
||||
void setControllerId(UUID controllerId);
|
||||
|
||||
boolean isTapped();
|
||||
|
||||
boolean untap(Game game);
|
||||
|
||||
boolean tap(Game game);
|
||||
|
||||
/**
|
||||
* use tap(game)
|
||||
* <p>setTapped doesn't trigger TAPPED event and should be used
|
||||
* only if you want permanent to enter battlefield tapped</p>
|
||||
* <p>
|
||||
* setTapped doesn't trigger TAPPED event and should be used only if you
|
||||
* want permanent to enter battlefield tapped</p>
|
||||
*
|
||||
* @param tapped
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
void setTapped(boolean tapped);
|
||||
|
||||
boolean canTap();
|
||||
|
||||
boolean isFlipped();
|
||||
|
||||
boolean unflip(Game game);
|
||||
|
||||
boolean flip(Game game);
|
||||
|
||||
boolean transform(Game game);
|
||||
|
||||
boolean isTransformed();
|
||||
|
||||
void setTransformed(boolean value);
|
||||
|
||||
boolean isPhasedIn();
|
||||
|
||||
boolean phaseIn(Game game);
|
||||
|
||||
boolean phaseOut(Game game);
|
||||
|
||||
boolean isMonstrous();
|
||||
|
||||
void setMonstrous(boolean value);
|
||||
|
||||
boolean isRenowned();
|
||||
|
||||
void setRenowned(boolean value);
|
||||
|
||||
void setCardNumber(int cid);
|
||||
|
||||
void setExpansionSetCode(String expansionSetCode);
|
||||
|
||||
void setRarity(Rarity rarity);
|
||||
|
||||
void setFlipCard(boolean flipCard);
|
||||
|
||||
void setFlipCardName(String flipCardName);
|
||||
|
||||
void setSecondCardFace(Card card);
|
||||
|
||||
Counters getCounters();
|
||||
|
||||
List<UUID> getAttachments();
|
||||
|
||||
UUID getAttachedTo();
|
||||
|
||||
void attachTo(UUID permanentId, Game game);
|
||||
|
||||
boolean addAttachment(UUID permanentId, Game game);
|
||||
|
||||
boolean removeAttachment(UUID permanentId, Game game);
|
||||
|
||||
boolean canBeTargetedBy(MageObject source, UUID controllerId, Game game);
|
||||
|
||||
boolean hasProtectionFrom(MageObject source, Game game);
|
||||
|
||||
boolean cantBeEnchantedBy(MageObject source, Game game);
|
||||
|
||||
boolean wasControlledFromStartOfControllerTurn();
|
||||
|
||||
boolean hasSummoningSickness();
|
||||
|
||||
int getDamage();
|
||||
|
||||
int damage(int damage, UUID sourceId, Game game, boolean combat, boolean preventable);
|
||||
|
||||
int damage(int damage, UUID sourceId, Game game, boolean combat, boolean preventable, ArrayList<UUID> appliedEffects);
|
||||
|
|
@ -114,58 +142,83 @@ public interface Permanent extends Card, Controllable {
|
|||
* @return
|
||||
*/
|
||||
int markDamage(int damage, UUID sourceId, Game game, boolean preventable, boolean combat);
|
||||
|
||||
int applyDamage(Game game);
|
||||
|
||||
void removeAllDamage(Game game);
|
||||
|
||||
void reset(Game game);
|
||||
|
||||
boolean destroy(UUID sourceId, Game game, boolean noRegen);
|
||||
|
||||
boolean sacrifice(UUID sourceId, Game game);
|
||||
|
||||
boolean regenerate(UUID sourceId, Game game);
|
||||
|
||||
boolean fight(Permanent fightTarget, Ability source, Game game);
|
||||
|
||||
void entersBattlefield(UUID sourceId, Game game, Zone fromZone, boolean fireEvent);
|
||||
boolean entersBattlefield(UUID sourceId, Game game, Zone fromZone, boolean fireEvent);
|
||||
|
||||
String getValue();
|
||||
|
||||
@Deprecated
|
||||
void addAbility(Ability ability);
|
||||
|
||||
@Deprecated
|
||||
void addAbility(Ability ability, Game game);
|
||||
|
||||
void addAbility(Ability ability, UUID sourceId, Game game);
|
||||
|
||||
void addAbility(Ability ability, UUID sourceId, Game game, boolean createNewId);
|
||||
|
||||
void removeAllAbilities(UUID sourceId, Game game);
|
||||
|
||||
void addLoyaltyUsed();
|
||||
|
||||
boolean canLoyaltyBeUsed(Game game);
|
||||
|
||||
|
||||
public void resetControl();
|
||||
|
||||
boolean changeControllerId(UUID controllerId, Game game);
|
||||
|
||||
boolean checkControlChanged(Game game);
|
||||
|
||||
void beginningOfTurn(Game game);
|
||||
|
||||
void endOfTurn(Game game);
|
||||
|
||||
int getTurnsOnBattlefield();
|
||||
|
||||
void addPower(int power);
|
||||
|
||||
void addToughness(int toughness);
|
||||
|
||||
boolean isAttacking();
|
||||
|
||||
int getBlocking();
|
||||
|
||||
void setAttacking(boolean attacking);
|
||||
|
||||
void setBlocking(int blocking);
|
||||
|
||||
int getMaxBlocks();
|
||||
|
||||
void setMaxBlocks(int maxBlocks);
|
||||
|
||||
int getMinBlockedBy();
|
||||
|
||||
void setMinBlockedBy(int minBlockedBy);
|
||||
|
||||
int getMaxBlockedBy();
|
||||
|
||||
boolean isRemovedFromCombat();
|
||||
|
||||
void setRemovedFromCombat(boolean removedFromCombat);
|
||||
|
||||
/**
|
||||
* Sets the maximum number of blockers the creature can be blocked by.
|
||||
* Default = 0 which means there is no restriction in the number of blockers.
|
||||
* Default = 0 which means there is no restriction in the number of
|
||||
* blockers.
|
||||
*
|
||||
* @param maxBlockedBy maximum number of blockers
|
||||
*/
|
||||
|
|
@ -180,11 +233,14 @@ public interface Permanent extends Card, Controllable {
|
|||
* @return
|
||||
*/
|
||||
boolean canAttack(UUID defenderId, Game game);
|
||||
|
||||
boolean canBlock(UUID attackerId, Game game);
|
||||
|
||||
boolean canBlockAny(Game game);
|
||||
|
||||
/**
|
||||
* Checks by restriction effects if the permanent can use activated abilities
|
||||
* Checks by restriction effects if the permanent can use activated
|
||||
* abilities
|
||||
*
|
||||
* @param game
|
||||
* @return true - permanent can use activated abilities
|
||||
|
|
@ -192,11 +248,15 @@ public interface Permanent extends Card, Controllable {
|
|||
boolean canUseActivatedAbilities(Game game);
|
||||
|
||||
boolean removeFromCombat(Game game);
|
||||
|
||||
boolean removeFromCombat(Game game, boolean withInfo);
|
||||
|
||||
boolean isDeathtouched();
|
||||
|
||||
/**
|
||||
* Returns a list of object refrences that dealt damage this turn to this permanent
|
||||
* Returns a list of object refrences that dealt damage this turn to this
|
||||
* permanent
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
HashSet<MageObjectReference> getDealtDamageByThisTurn();
|
||||
|
|
@ -222,13 +282,14 @@ public interface Permanent extends Card, Controllable {
|
|||
* Get card that was imprinted on this one.
|
||||
*
|
||||
* Can be null if no card was imprinted.
|
||||
*
|
||||
* @return Imprinted card UUID.
|
||||
*/
|
||||
List<UUID> getImprinted();
|
||||
|
||||
/**
|
||||
* Allows to connect any card to permanent.
|
||||
* Very similar to Imprint except that it is for internal use only.
|
||||
* Allows to connect any card to permanent. Very similar to Imprint except
|
||||
* that it is for internal use only.
|
||||
*
|
||||
* @param key
|
||||
* @param connectedCard
|
||||
|
|
@ -236,8 +297,9 @@ public interface Permanent extends Card, Controllable {
|
|||
void addConnectedCard(String key, UUID connectedCard);
|
||||
|
||||
/**
|
||||
* Returns connected cards.
|
||||
* Very similar to Imprint except that it is for internal use only.
|
||||
* Returns connected cards. Very similar to Imprint except that it is for
|
||||
* internal use only.
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
|
|
@ -245,6 +307,7 @@ public interface Permanent extends Card, Controllable {
|
|||
|
||||
/**
|
||||
* Clear all connected cards.
|
||||
*
|
||||
* @param key
|
||||
*/
|
||||
void clearConnectedCards(String key);
|
||||
|
|
@ -269,9 +332,11 @@ public interface Permanent extends Card, Controllable {
|
|||
void clearPairedCard();
|
||||
|
||||
void setMorphed(boolean value);
|
||||
|
||||
boolean isMorphed();
|
||||
|
||||
void setManifested(boolean value);
|
||||
|
||||
boolean isManifested();
|
||||
|
||||
@Override
|
||||
|
|
@ -280,5 +345,6 @@ public interface Permanent extends Card, Controllable {
|
|||
// Simple int counter to set a timewise create order , the lower the number the earlier the object was created
|
||||
// if objects enter the battlefield at the same time they can get (and should) get the same number.
|
||||
int getCreateOrder();
|
||||
|
||||
void setCreateOrder(int createOrder);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -899,10 +899,10 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void entersBattlefield(UUID sourceId, Game game, Zone fromZone, boolean fireEvent) {
|
||||
public boolean entersBattlefield(UUID sourceId, Game game, Zone fromZone, boolean fireEvent) {
|
||||
controlledFromStartOfControllerTurn = false;
|
||||
if (this.isFaceDown(game)) {
|
||||
// remove some attributes here, bceause first apply effects comes later otherwise abilities (e.g. color related) will unintended trigger
|
||||
// remove some attributes here, because first apply effects comes later otherwise abilities (e.g. color related) will unintended trigger
|
||||
MorphAbility.setPermanentToFaceDownCreature(this);
|
||||
}
|
||||
EntersTheBattlefieldEvent event = new EntersTheBattlefieldEvent(this, sourceId, getControllerId(), fromZone);
|
||||
|
|
@ -914,7 +914,9 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
game.addSimultaneousEvent(event);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -159,15 +159,17 @@ public class Token extends MageObjectImpl {
|
|||
this.lastAddedTokenId = newToken.getId();
|
||||
game.setScopeRelevant(true);
|
||||
game.applyEffects();
|
||||
newToken.entersBattlefield(sourceId, game, Zone.OUTSIDE, true);
|
||||
boolean entered = newToken.entersBattlefield(sourceId, game, Zone.OUTSIDE, true);
|
||||
game.setScopeRelevant(false);
|
||||
game.applyEffects();
|
||||
game.fireEvent(new ZoneChangeEvent(newToken, event.getPlayerId(), Zone.OUTSIDE, Zone.BATTLEFIELD));
|
||||
if (attacking && game.getCombat() != null) {
|
||||
game.getCombat().addAttackingCreature(newToken.getId(), game);
|
||||
}
|
||||
if (!game.isSimulation()) {
|
||||
game.informPlayers(controller.getLogName() + " puts a " + newToken.getLogName() + " token onto the battlefield");
|
||||
if (entered) {
|
||||
game.fireEvent(new ZoneChangeEvent(newToken, event.getPlayerId(), Zone.OUTSIDE, Zone.BATTLEFIELD));
|
||||
if (attacking && game.getCombat() != null) {
|
||||
game.getCombat().addAttackingCreature(newToken.getId(), game);
|
||||
}
|
||||
if (!game.isSimulation()) {
|
||||
game.informPlayers(controller.getLogName() + " puts a " + newToken.getLogName() + " token onto the battlefield");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import java.util.List;
|
|||
import java.util.UUID;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.TurnPhase;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
|
@ -116,16 +117,24 @@ public class Turn implements Serializable {
|
|||
return null;
|
||||
}
|
||||
|
||||
public void play(Game game, Player activePlayer) {
|
||||
/**
|
||||
*
|
||||
* @param game
|
||||
* @param activePlayer
|
||||
* @return true if turn is skipped
|
||||
*/
|
||||
public boolean play(Game game, Player activePlayer) {
|
||||
activePlayer.becomesActivePlayer();
|
||||
this.setDeclareAttackersStepStarted(false);
|
||||
if (game.isPaused() || game.gameOver(null)) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (game.getState().getTurnMods().skipTurn(activePlayer.getId())) {
|
||||
return;
|
||||
game.informPlayers(activePlayer.getLogName() + " skips his or her turn.");
|
||||
return true;
|
||||
}
|
||||
logStartOfTurn(game, activePlayer);
|
||||
|
||||
checkTurnIsControlledByOtherPlayer(game, activePlayer.getId());
|
||||
|
||||
|
|
@ -134,7 +143,7 @@ public class Turn implements Serializable {
|
|||
game.getPlayer(activePlayer.getId()).beginTurn(game);
|
||||
for (Phase phase : phases) {
|
||||
if (game.isPaused() || game.gameOver(null)) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
if (!isEndTurnRequested() || phase.getType().equals(TurnPhase.END)) {
|
||||
currentPhase = phase;
|
||||
|
|
@ -142,7 +151,7 @@ public class Turn implements Serializable {
|
|||
if (!game.getState().getTurnMods().skipPhase(activePlayer.getId(), currentPhase.getType())) {
|
||||
if (phase.play(game, activePlayer.getId())) {
|
||||
if (game.executingRollback()) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
//20091005 - 500.4/703.4n
|
||||
game.emptyManaPools();
|
||||
|
|
@ -155,7 +164,7 @@ public class Turn implements Serializable {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void resumePlay(Game game, boolean wasPaused) {
|
||||
|
|
@ -327,4 +336,23 @@ public class Turn implements Serializable {
|
|||
return sb.toString();
|
||||
}
|
||||
|
||||
private void logStartOfTurn(Game game, Player player) {
|
||||
StringBuilder sb = new StringBuilder("Turn ").append(game.getState().getTurnNum()).append(" ");
|
||||
sb.append(player.getLogName());
|
||||
sb.append(" (");
|
||||
int delimiter = game.getPlayers().size() - 1;
|
||||
for (Player gamePlayer : game.getPlayers().values()) {
|
||||
sb.append(gamePlayer.getLife());
|
||||
int poison = gamePlayer.getCounters().getCount(CounterType.POISON);
|
||||
if (poison > 0) {
|
||||
sb.append("[P:").append(poison).append("]");
|
||||
}
|
||||
if (delimiter > 0) {
|
||||
sb.append(" - ");
|
||||
delimiter--;
|
||||
}
|
||||
}
|
||||
sb.append(")");
|
||||
game.fireStatusEvent(sb.toString(), true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.players;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
|
@ -63,7 +62,7 @@ public class ManaPool implements Serializable {
|
|||
private boolean autoPayment; // auto payment from mana pool: true - mode is active
|
||||
private boolean autoPaymentRestricted; // auto payment from mana pool: true - if auto Payment is on, it will only pay if one kind of mana is in the pool
|
||||
private ManaType unlockedManaType; // type of mana that was selected to pay manually
|
||||
|
||||
|
||||
private final Set<ManaType> doNotEmptyManaTypes = new HashSet<>();
|
||||
|
||||
public ManaPool(UUID playerId) {
|
||||
|
|
@ -75,7 +74,7 @@ public class ManaPool implements Serializable {
|
|||
|
||||
public ManaPool(final ManaPool pool) {
|
||||
this.playerId = pool.playerId;
|
||||
for (ManaPoolItem item: pool.manaItems) {
|
||||
for (ManaPoolItem item : pool.manaItems) {
|
||||
manaItems.add(item.copy());
|
||||
}
|
||||
this.autoPayment = pool.autoPayment;
|
||||
|
|
@ -105,24 +104,24 @@ public class ManaPool implements Serializable {
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param manaType the mana type that should be paid
|
||||
* @param ability
|
||||
* @param filter
|
||||
* @param game
|
||||
* @return
|
||||
* @return
|
||||
*/
|
||||
public boolean pay(ManaType manaType, Ability ability, Filter filter, Game game) {
|
||||
if (!autoPayment && !manaType.equals(unlockedManaType)) {
|
||||
// if manual payment and the needed mana type was not unlocked, nothing will be paid
|
||||
return false;
|
||||
}
|
||||
if (autoPayment && autoPaymentRestricted && !wasManaAddedBeyondStock() && !manaType.equals(unlockedManaType)) {
|
||||
if (autoPayment && autoPaymentRestricted && !wasManaAddedBeyondStock() && !manaType.equals(unlockedManaType)) {
|
||||
// if automatic restricted payment and there is laready mana in the pool
|
||||
// and the needed mana type was not unlocked, nothing will be paid
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (getConditional(manaType, ability, filter, game) > 0) {
|
||||
removeConditional(manaType, ability, game);
|
||||
lockManaType(); // pay only one mana if mana payment is set to manually
|
||||
|
|
@ -134,7 +133,7 @@ public class ManaPool implements Serializable {
|
|||
if (!filter.match(sourceObject, game)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!manaType.equals(unlockedManaType) && autoPayment && autoPaymentRestricted && mana.count() == mana.getStock()) {
|
||||
// no mana added beyond the stock so don't auto pay this
|
||||
continue;
|
||||
|
|
@ -202,7 +201,7 @@ public class ManaPool implements Serializable {
|
|||
public void clearEmptyManaPoolRules() {
|
||||
doNotEmptyManaTypes.clear();
|
||||
}
|
||||
|
||||
|
||||
public void addDoNotEmptyManaType(ManaType manaType) {
|
||||
doNotEmptyManaTypes.add(manaType);
|
||||
}
|
||||
|
|
@ -217,7 +216,7 @@ public class ManaPool implements Serializable {
|
|||
if (!doNotEmptyManaTypes.contains(manaType)) {
|
||||
if (item.get(manaType) > 0) {
|
||||
if (!item.getDuration().equals(Duration.EndOfTurn) || game.getPhase().getType().equals(TurnPhase.END)) {
|
||||
if (game.replaceEvent(new GameEvent(GameEvent.EventType.EMPTY_MANA_POOL, playerId, null, playerId))) {
|
||||
if (game.replaceEvent(new GameEvent(GameEvent.EventType.EMPTY_MANA_POOL, playerId, null, playerId))) {
|
||||
int amount = item.get(manaType);
|
||||
item.clear(manaType);
|
||||
item.add(ManaType.COLORLESS, amount);
|
||||
|
|
@ -230,7 +229,7 @@ public class ManaPool implements Serializable {
|
|||
if (conditionalItem != null) {
|
||||
if (conditionalItem.get(manaType) > 0) {
|
||||
if (!item.getDuration().equals(Duration.EndOfTurn) || game.getPhase().getType().equals(TurnPhase.END)) {
|
||||
if (game.replaceEvent(new GameEvent(GameEvent.EventType.EMPTY_MANA_POOL, playerId, null, playerId))) {
|
||||
if (game.replaceEvent(new GameEvent(GameEvent.EventType.EMPTY_MANA_POOL, playerId, null, playerId))) {
|
||||
int amount = conditionalItem.get(manaType);
|
||||
conditionalItem.clear(manaType);
|
||||
conditionalItem.add(ManaType.COLORLESS, amount);
|
||||
|
|
@ -246,8 +245,8 @@ public class ManaPool implements Serializable {
|
|||
if (item.count() == 0) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
private int payX(Ability ability, Game game) {
|
||||
|
|
@ -261,8 +260,7 @@ public class ManaPool implements Serializable {
|
|||
total += item.count();
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
total += item.count();
|
||||
it.remove();
|
||||
}
|
||||
|
|
@ -272,10 +270,11 @@ public class ManaPool implements Serializable {
|
|||
|
||||
/**
|
||||
* remove all mana from pool that applies and that matches filter
|
||||
*
|
||||
* @param ability
|
||||
* @param game
|
||||
* @param filter
|
||||
* @return
|
||||
* @return
|
||||
*/
|
||||
public int payX(Ability ability, Game game, FilterMana filter) {
|
||||
if (filter == null) {
|
||||
|
|
@ -297,8 +296,7 @@ public class ManaPool implements Serializable {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (filter.isBlack()) {
|
||||
total += item.getBlack();
|
||||
item.removeBlack();
|
||||
|
|
@ -333,7 +331,7 @@ public class ManaPool implements Serializable {
|
|||
|
||||
public Mana getMana() {
|
||||
Mana m = new Mana();
|
||||
for (ManaPoolItem item: manaItems) {
|
||||
for (ManaPoolItem item : manaItems) {
|
||||
m.add(item.getMana());
|
||||
}
|
||||
return m;
|
||||
|
|
@ -375,12 +373,12 @@ public class ManaPool implements Serializable {
|
|||
public void addMana(Mana manaToAdd, Game game, Ability source) {
|
||||
addMana(manaToAdd, game, source, false);
|
||||
}
|
||||
|
||||
|
||||
public void addMana(Mana manaToAdd, Game game, Ability source, boolean emptyOnTurnsEnd) {
|
||||
Mana mana = manaToAdd.copy();
|
||||
if (!game.replaceEvent(new ManaEvent(EventType.ADD_MANA, source.getId(), source.getSourceId(), source.getControllerId(), mana))) {
|
||||
if (!game.replaceEvent(new ManaEvent(EventType.ADD_MANA, source.getId(), source.getSourceId(), playerId, mana))) {
|
||||
if (mana instanceof ConditionalMana) {
|
||||
ManaPoolItem item = new ManaPoolItem((ConditionalMana)mana, source.getSourceId(), source.getOriginalId());
|
||||
ManaPoolItem item = new ManaPoolItem((ConditionalMana) mana, source.getSourceId(), source.getOriginalId());
|
||||
if (emptyOnTurnsEnd) {
|
||||
item.setDuration(Duration.EndOfTurn);
|
||||
}
|
||||
|
|
@ -389,18 +387,18 @@ public class ManaPool implements Serializable {
|
|||
ManaPoolItem item = new ManaPoolItem(mana.getRed(), mana.getGreen(), mana.getBlue(), mana.getWhite(), mana.getBlack(), mana.getColorless(), source.getSourceId(), source.getOriginalId(), mana.getFlag());
|
||||
if (emptyOnTurnsEnd) {
|
||||
item.setDuration(Duration.EndOfTurn);
|
||||
}
|
||||
}
|
||||
this.manaItems.add(item);
|
||||
}
|
||||
GameEvent event = GameEvent.getEvent(GameEvent.EventType.MANA_ADDED, source.getId(), source.getSourceId(), source.getControllerId());
|
||||
event.setData(mana.toString());
|
||||
game.fireEvent(event);
|
||||
ManaEvent manaEvent = new ManaEvent(EventType.MANA_ADDED, source.getId(), source.getSourceId(), playerId, mana);
|
||||
manaEvent.setData(mana.toString());
|
||||
game.fireEvent(manaEvent);
|
||||
}
|
||||
}
|
||||
|
||||
public List<ConditionalMana> getConditionalMana() {
|
||||
List<ConditionalMana> conditionalMana = new ArrayList<>();
|
||||
for (ManaPoolItem item: manaItems) {
|
||||
for (ManaPoolItem item : manaItems) {
|
||||
if (item.isConditional()) {
|
||||
conditionalMana.add(item.getConditionalMana());
|
||||
}
|
||||
|
|
@ -410,7 +408,7 @@ public class ManaPool implements Serializable {
|
|||
|
||||
public int count() {
|
||||
int x = 0;
|
||||
for (ManaPoolItem item: manaItems) {
|
||||
for (ManaPoolItem item : manaItems) {
|
||||
x += item.count();
|
||||
}
|
||||
return x;
|
||||
|
|
@ -465,7 +463,7 @@ public class ManaPool implements Serializable {
|
|||
mana.setStock(mana.count());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean wasManaAddedBeyondStock() {
|
||||
for (ManaPoolItem mana : manaItems) {
|
||||
if (mana.getStock() < mana.count()) {
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ public class GameLog {
|
|||
static final String LOG_COLOR_PLAYER = "#20B2AA"; // LightSeaGreen
|
||||
static final String LOG_COLOR_PLAYER_REQUEST = "#D2691E"; // Chocolate
|
||||
static final String LOG_COLOR_PLAYER_CONFIRM = "#D2691E"; // Chocolate
|
||||
// colors for more dark background
|
||||
static final String LOG_COLOR_GREEN = "#90EE90"; // LightGreen
|
||||
static final String LOG_COLOR_RED = "#FF6347"; // Tomato
|
||||
static final String LOG_COLOR_BLUE = "#87CEFA"; // LightSkyBlue
|
||||
|
|
@ -46,6 +47,14 @@ public class GameLog {
|
|||
static final String LOG_COLOR_WHITE = "#F0E68C"; // Khaki
|
||||
static final String LOG_COLOR_MULTI = "#DAA520"; // GoldenRod
|
||||
static final String LOG_COLOR_COLORLESS = "#B0C4DE"; // LightSteelBlue
|
||||
// colors for tooltip (light background)
|
||||
static final String LOG_TT_COLOR_RED = "Red"; // Tomato
|
||||
static final String LOG_TT_COLOR_GREEN = "Green"; // LightGreen
|
||||
static final String LOG_TT_COLOR_BLUE = "Blue";
|
||||
static final String LOG_TT_COLOR_BLACK = "Black";
|
||||
static final String LOG_TT_COLOR_WHITE = "#CCDB00";
|
||||
static final String LOG_TT_COLOR_MULTI = "#FFAC40";
|
||||
static final String LOG_TT_COLOR_COLORLESS = "#94A4BA";
|
||||
static final String LOG_COLOR_NEUTRAL = "#F0F8FF"; // AliceBlue
|
||||
|
||||
public static String replaceNameByColoredName(MageObject mageObject, String text) {
|
||||
|
|
@ -60,6 +69,10 @@ public class GameLog {
|
|||
return "<font color=\'" + getColorName(mageObject.getColor(null)) + "\'>" + mageObject.getName() + " [" + mageObject.getId().toString().substring(0, 3) + "]</font>";
|
||||
}
|
||||
|
||||
public static String getColoredObjectIdNameForTooltip(MageObject mageObject) {
|
||||
return "<font color=\'" + getTooltipColorName(mageObject.getColor(null)) + "\'>" + mageObject.getName() + " [" + mageObject.getId().toString().substring(0, 3) + "]</font>";
|
||||
}
|
||||
|
||||
public static String getNeutralColoredText(String text) {
|
||||
return "<font color=\'" + LOG_COLOR_NEUTRAL + "\'>" + text + "</font>";
|
||||
}
|
||||
|
|
@ -97,4 +110,22 @@ public class GameLog {
|
|||
return LOG_COLOR_BLACK;
|
||||
}
|
||||
}
|
||||
|
||||
private static String getTooltipColorName(ObjectColor objectColor) {
|
||||
if (objectColor.isMulticolored()) {
|
||||
return LOG_TT_COLOR_MULTI;
|
||||
} else if (objectColor.isColorless()) {
|
||||
return LOG_TT_COLOR_COLORLESS;
|
||||
} else if (objectColor.isRed()) {
|
||||
return LOG_TT_COLOR_RED;
|
||||
} else if (objectColor.isGreen()) {
|
||||
return LOG_TT_COLOR_GREEN;
|
||||
} else if (objectColor.isBlue()) {
|
||||
return LOG_TT_COLOR_BLUE;
|
||||
} else if (objectColor.isWhite()) {
|
||||
return LOG_TT_COLOR_WHITE;
|
||||
} else {
|
||||
return LOG_TT_COLOR_BLACK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue