mirror of
https://github.com/magefree/mage.git
synced 2026-01-10 04:42:07 -08:00
Merge branch 'master' of https://github.com/magefree/mage
Conflicts: Mage.Sets/src/mage/sets/avacynrestored/CavernOfSouls.java Mage.Sets/src/mage/sets/shadowmoor/ManaReflection.java
This commit is contained in:
commit
5c746e8ec2
137 changed files with 4932 additions and 633 deletions
|
|
@ -39,6 +39,7 @@ import mage.filter.Filter;
|
|||
import mage.game.Game;
|
||||
import mage.players.ManaPool;
|
||||
import mage.players.Player;
|
||||
import mage.util.ManaUtil;
|
||||
|
||||
|
||||
public abstract class ManaCostImpl extends CostImpl implements ManaCost {
|
||||
|
|
@ -218,12 +219,15 @@ public abstract class ManaCostImpl extends CostImpl implements ManaCost {
|
|||
Player player = game.getPlayer(controllerId);
|
||||
assignPayment(game, ability, player.getManaPool());
|
||||
while (!isPaid()) {
|
||||
if (player.playMana(this, game)) {
|
||||
ManaCost unpaid = this.getUnpaid();
|
||||
String promptText = ManaUtil.addSpecialManaPayAbilities(ability, game, unpaid);
|
||||
if (player.playMana(unpaid, promptText, game)) {
|
||||
assignPayment(game, ability, player.getManaPool());
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
game.getState().getSpecialActions().removeManaActions();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ import mage.MageObject;
|
|||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.VariableCost;
|
||||
import mage.abilities.keyword.DelveAbility;
|
||||
import mage.abilities.mana.ManaOptions;
|
||||
import mage.constants.ColoredManaSymbol;
|
||||
import mage.filter.Filter;
|
||||
|
|
@ -45,6 +44,7 @@ import mage.game.Game;
|
|||
import mage.players.ManaPool;
|
||||
import mage.players.Player;
|
||||
import mage.target.Targets;
|
||||
import mage.util.ManaUtil;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
|
@ -121,8 +121,9 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
|
|||
Player player = game.getPlayer(controllerId);
|
||||
assignPayment(game, ability, player.getManaPool());
|
||||
while (!isPaid()) {
|
||||
addSpecialManaPayAbilities(ability, game);
|
||||
if (player.playMana(this.getUnpaid(), game)) {
|
||||
ManaCost unpaid = this.getUnpaid();
|
||||
String promptText = ManaUtil.addSpecialManaPayAbilities(ability, game, unpaid);
|
||||
if (player.playMana(unpaid, promptText, game)) {
|
||||
assignPayment(game, ability, player.getManaPool());
|
||||
} else {
|
||||
return false;
|
||||
|
|
@ -132,25 +133,6 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This activates the special button if there exists special ways to pay the mana (Delve, Convoke)
|
||||
*
|
||||
* @param ability
|
||||
* @param game
|
||||
*/
|
||||
private void addSpecialManaPayAbilities(Ability source, Game game) {
|
||||
// check for special mana payment possibilities
|
||||
MageObject mageObject = source.getSourceObject(game);
|
||||
if (mageObject != null) {
|
||||
for (Ability ability :mageObject.getAbilities()) {
|
||||
if (ability instanceof AlternateManaPaymentAbility) {
|
||||
((AlternateManaPaymentAbility) ability).addSpecialAction(source, game, getUnpaid());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* bookmarks the current state and restores it if player doesn't pay the mana cost
|
||||
*
|
||||
|
|
|
|||
|
|
@ -331,6 +331,7 @@ public class ContinuousEffects implements Serializable {
|
|||
if(auraReplacementEffect.checksEventType(event, game) && auraReplacementEffect.applies(event, null, game)){
|
||||
replaceEffects.put(auraReplacementEffect, null);
|
||||
}
|
||||
boolean checkLKI = event.getType().equals(EventType.ZONE_CHANGE) || event.getType().equals(EventType.DESTROYED_PERMANENT);
|
||||
//get all applicable transient Replacement effects
|
||||
for (ReplacementEffect effect: replacementEffects) {
|
||||
if (!effect.checksEventType(event, game)) {
|
||||
|
|
@ -344,7 +345,7 @@ public class ContinuousEffects implements Serializable {
|
|||
HashSet<Ability> abilities = replacementEffects.getAbility(effect.getId());
|
||||
HashSet<Ability> applicableAbilities = new HashSet<>();
|
||||
for (Ability ability : abilities) {
|
||||
if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, false)) {
|
||||
if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, checkLKI)) {
|
||||
if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) {
|
||||
if (!game.getScopeRelevant() || effect.hasSelfScope() || !event.getTargetId().equals(ability.getSourceId())) {
|
||||
if (checkAbilityStillExists(ability, effect, event, game)) {
|
||||
|
|
|
|||
|
|
@ -39,9 +39,7 @@ import mage.game.Game;
|
|||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.target.common.TargetControlledPermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
|
|
@ -54,19 +52,19 @@ public class SacrificeEffect extends OneShotEffect{
|
|||
private String preText;
|
||||
private DynamicValue count;
|
||||
|
||||
public SacrificeEffect ( FilterPermanent filter, DynamicValue count, String preText ) {
|
||||
public SacrificeEffect (FilterPermanent filter, int count, String preText ) {
|
||||
this(filter, new StaticValue(count), preText);
|
||||
}
|
||||
|
||||
public SacrificeEffect (FilterPermanent filter, DynamicValue count, String preText ) {
|
||||
super(Outcome.Sacrifice);
|
||||
this.filter = filter;
|
||||
this.count = count;
|
||||
this.preText = preText;
|
||||
setText();
|
||||
}
|
||||
|
||||
public SacrificeEffect ( FilterPermanent filter, int count, String preText ) {
|
||||
this(filter, new StaticValue(count), preText);
|
||||
}
|
||||
|
||||
public SacrificeEffect ( final SacrificeEffect effect ) {
|
||||
|
||||
public SacrificeEffect (final SacrificeEffect effect ) {
|
||||
super(effect);
|
||||
this.filter = effect.filter;
|
||||
this.count = effect.count;
|
||||
|
|
@ -87,14 +85,14 @@ public class SacrificeEffect extends OneShotEffect{
|
|||
int realCount = game.getBattlefield().countAll(filter, player.getId(), game);
|
||||
amount = Math.min(amount, realCount);
|
||||
|
||||
Target target = new TargetControlledPermanent(amount, amount, filter, true);
|
||||
Target target = new TargetPermanent(amount, amount, filter, true);
|
||||
|
||||
// A spell or ability could have removed the only legal target this player
|
||||
// had, if thats the case this ability should fizzle.
|
||||
if (amount > 0 && target.canChoose(source.getSourceId(), player.getId(), game)) {
|
||||
boolean abilityApplied = false;
|
||||
while (!target.isChosen() && target.canChoose(player.getId(), game) && player.isInGame()) {
|
||||
player.choose(Outcome.Sacrifice, target, source.getSourceId(), game);
|
||||
player.chooseTarget(Outcome.Sacrifice, target, source, game);
|
||||
}
|
||||
|
||||
for ( int idx = 0; idx < target.getTargets().size(); idx++) {
|
||||
|
|
|
|||
|
|
@ -36,11 +36,13 @@ import mage.abilities.dynamicvalue.DynamicValue;
|
|||
import mage.abilities.dynamicvalue.common.StaticValue;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.TargetController;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.predicate.permanent.ControllerPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetControlledPermanent;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
|
|
@ -81,15 +83,17 @@ public class SacrificeOpponentsEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
List<UUID> perms = new ArrayList<UUID>();
|
||||
List<UUID> perms = new ArrayList<>();
|
||||
filter.add(new ControllerPredicate(TargetController.YOU));
|
||||
for (UUID playerId : game.getOpponents(source.getControllerId())) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
|
||||
int numTargets = Math.min(amount.calculate(game, source, this), game.getBattlefield().countAll(filter, player.getId(), game));
|
||||
TargetControlledPermanent target = new TargetControlledPermanent(numTargets, numTargets, filter, false);
|
||||
TargetPermanent target = new TargetPermanent(numTargets, numTargets, filter, false);
|
||||
if (target.canChoose(player.getId(), game)) {
|
||||
while (!target.isChosen() && player.isInGame()) {
|
||||
player.choose(Outcome.Sacrifice, target, source.getSourceId(), game);
|
||||
player.chooseTarget(Outcome.Sacrifice, target, source, game);
|
||||
}
|
||||
perms.addAll(target.getTargets());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ import mage.constants.Duration;
|
|||
import mage.constants.Layer;
|
||||
import static mage.constants.Layer.TypeChangingEffects_4;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SpellAbilityType;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.constants.TimingRule;
|
||||
import mage.constants.Zone;
|
||||
|
|
@ -108,6 +109,7 @@ public class BestowAbility extends SpellAbility {
|
|||
|
||||
public BestowAbility(Card card, String manaString) {
|
||||
super(new ManaCostsImpl(manaString), card.getName() + " using bestow");
|
||||
this.spellAbilityType = SpellAbilityType.BASE_ALTERNATE;
|
||||
this.timing = TimingRule.SORCERY;
|
||||
TargetPermanent auraTarget = new TargetCreaturePermanent();
|
||||
this.addTarget(auraTarget);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
package mage.abilities.keyword;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
|
|
@ -40,7 +41,6 @@ import mage.abilities.effects.OneShotEffect;
|
|||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.EntersTheBattlefieldEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
|
|
@ -120,7 +120,7 @@ public class EchoAbility extends TriggeredAbilityImpl {
|
|||
if (manaEcho) {
|
||||
sb.append(" ");
|
||||
} else {
|
||||
sb.append("-");
|
||||
sb.append("—");
|
||||
}
|
||||
sb.append(echoCosts.getText());
|
||||
sb.append(" <i>(At the beginning of your upkeep, if this came under your control since the beginning of your last upkeep, sacrifice it unless you pay its echo cost.)</i>");
|
||||
|
|
@ -143,16 +143,16 @@ class EchoEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (player != null && permanent != null) {
|
||||
if (player.chooseUse(Outcome.Benefit, "Pay " + cost.getText() /* + " or sacrifice " + permanent.getName() */ + "?", game)) {
|
||||
cost.clearPaid();
|
||||
if (cost.pay(source, game, source.getSourceId(), source.getControllerId(), false)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
permanent.sacrifice(source.getSourceId(), game);
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObjectReference mor = new MageObjectReference(source.getSourceId(), game);
|
||||
if (controller != null && mor.refersTo(source.getSourceObject(game))) {
|
||||
if (controller.chooseUse(Outcome.Benefit, "Pay " + cost.getText() /* + " or sacrifice " + permanent.getName() */ + "?", game)) {
|
||||
cost.clearPaid();
|
||||
if (cost.pay(source, game, source.getSourceId(), source.getControllerId(), false)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
mor.getPermanent(game).sacrifice(source.getSourceId(), game);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ public class UndyingAbility extends DiesTriggeredAbility {
|
|||
|
||||
public UndyingAbility() {
|
||||
super(new UndyingEffect());
|
||||
this.addEffect(new ReturnSourceFromGraveyardToBattlefieldEffect());
|
||||
this.addEffect(new ReturnSourceFromGraveyardToBattlefieldEffect(false, true));
|
||||
}
|
||||
|
||||
public UndyingAbility(final UndyingAbility ability) {
|
||||
|
|
@ -40,7 +40,6 @@ public class UndyingAbility extends DiesTriggeredAbility {
|
|||
if (super.checkTrigger(event, game)) {
|
||||
Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD);
|
||||
if (!permanent.getCounters().containsKey(CounterType.P1P1) || permanent.getCounters().getCount(CounterType.P1P1) == 0) {
|
||||
Logger.getLogger(UndyingAbility.class).info("Undying trigger: " + getSourceId());
|
||||
game.getState().setValue("undying" + getSourceId(),permanent.getId());
|
||||
return true;
|
||||
}
|
||||
|
|
@ -115,8 +114,6 @@ class UndyingReplacementEffect extends ReplacementEffectImpl {
|
|||
if (event.getTargetId().equals(source.getSourceId())) {
|
||||
// Check if undying condition is true
|
||||
UUID targetId = (UUID) game.getState().getValue("undying" + source.getSourceId());
|
||||
Logger.getLogger(UndyingReplacementEffect.class).info("Undying replacement applies: " + targetId + " eventSourceId " + event.getTargetId());
|
||||
|
||||
if (targetId != null && targetId.equals(source.getSourceId())) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,52 +25,34 @@
|
|||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.filter.common;
|
||||
|
||||
package mage.watchers.common;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.watchers.Watcher;
|
||||
import mage.constants.CardType;
|
||||
import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||
|
||||
/**
|
||||
* @author jeffwadsworth
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
||||
public class PermanentTappedForManaWatcher extends Watcher {
|
||||
public class FilterControlledPlaneswalkerPermanent extends FilterControlledPermanent {
|
||||
|
||||
public List<UUID> permanentId = new ArrayList<>();
|
||||
|
||||
public PermanentTappedForManaWatcher() {
|
||||
super("PermanentTappedForMana", WatcherScope.GAME);
|
||||
public FilterControlledPlaneswalkerPermanent() {
|
||||
this("planeswalker you control");
|
||||
}
|
||||
|
||||
public PermanentTappedForManaWatcher(final PermanentTappedForManaWatcher watcher) {
|
||||
super(watcher);
|
||||
public FilterControlledPlaneswalkerPermanent(String name) {
|
||||
super(name);
|
||||
this.add(new CardTypePredicate(CardType.PLANESWALKER));
|
||||
}
|
||||
|
||||
public FilterControlledPlaneswalkerPermanent(final FilterControlledPlaneswalkerPermanent filter) {
|
||||
super(filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermanentTappedForManaWatcher copy() {
|
||||
return new PermanentTappedForManaWatcher(this);
|
||||
public FilterControlledPlaneswalkerPermanent copy() {
|
||||
return new FilterControlledPlaneswalkerPermanent(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.TAPPED_FOR_MANA) {
|
||||
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getSourceId());
|
||||
if (permanent != null) {
|
||||
permanentId.add(permanent.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
permanentId.clear();
|
||||
}
|
||||
}
|
||||
|
|
@ -52,14 +52,14 @@ public class FilterPlaneswalkerOrPlayer extends FilterImpl<Object> {
|
|||
public FilterPlaneswalkerOrPlayer(Set<UUID> defenders) {
|
||||
super("planeswalker or player");
|
||||
|
||||
ArrayList<Predicate<Permanent>> permanentPredicates = new ArrayList<Predicate<Permanent>>();
|
||||
ArrayList<Predicate<Permanent>> permanentPredicates = new ArrayList<>();
|
||||
for (UUID defenderId : defenders) {
|
||||
permanentPredicates.add(new ControllerIdPredicate(defenderId));
|
||||
}
|
||||
planeswalkerFilter = new FilterPlaneswalkerPermanent();
|
||||
planeswalkerFilter.add(Predicates.or(permanentPredicates));
|
||||
|
||||
ArrayList<Predicate<Player>> playerPredicates = new ArrayList<Predicate<Player>>();
|
||||
ArrayList<Predicate<Player>> playerPredicates = new ArrayList<>();
|
||||
for (UUID defenderId : defenders) {
|
||||
playerPredicates.add(new PlayerIdPredicate(defenderId));
|
||||
}
|
||||
|
|
|
|||
116
Mage/src/mage/game/GameTinyLeadersImpl.java
Normal file
116
Mage/src/mage/game/GameTinyLeadersImpl.java
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EmptyEffect;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.continious.CommanderManaReplacementEffect;
|
||||
import mage.abilities.effects.common.continious.CommanderReplacementEffect;
|
||||
import mage.abilities.effects.common.cost.CommanderCostModification;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.MultiplayerAttackOption;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.RangeOfInfluence;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.turn.TurnMod;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JRHerlehy
|
||||
*/
|
||||
public abstract class GameTinyLeadersImpl extends GameImpl{
|
||||
|
||||
protected boolean alsoLibrary; // replace also commander going to library
|
||||
protected boolean startingPlayerSkipsDraw = true;
|
||||
|
||||
public GameTinyLeadersImpl(MultiplayerAttackOption attackOption, RangeOfInfluence range, int freeMulligans, int startLife) {
|
||||
super(attackOption, range, freeMulligans, startLife);
|
||||
}
|
||||
|
||||
public GameTinyLeadersImpl(final GameTinyLeadersImpl game) {
|
||||
super(game);
|
||||
this.alsoLibrary = game.alsoLibrary;
|
||||
this.startingPlayerSkipsDraw = game.startingPlayerSkipsDraw;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init(UUID choosingPlayerId, GameOptions gameOptions) {
|
||||
Ability ability = new SimpleStaticAbility(Zone.COMMAND, new EmptyEffect("Commander effects"));
|
||||
//Move tiny leader to command zone
|
||||
for (UUID playerId: state.getPlayerList(startingPlayerId)) {
|
||||
Player player = getPlayer(playerId);
|
||||
if (player != null){
|
||||
if (player.getSideboard().size() > 0){
|
||||
Card commander = getCard((UUID)player.getSideboard().toArray()[0]);
|
||||
if (commander != null) {
|
||||
player.setCommanderId(commander.getId());
|
||||
commander.moveToZone(Zone.COMMAND, null, this, true);
|
||||
ability.addEffect(new CommanderReplacementEffect(commander.getId(), alsoLibrary));
|
||||
ability.addEffect(new CommanderCostModification(commander.getId()));
|
||||
ability.addEffect(new CommanderManaReplacementEffect(player.getId(), CardUtil.getColorIdentity(commander)));
|
||||
getState().setValue(commander.getId() + "_castCount", 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
this.getState().addAbility(ability, null);
|
||||
super.init(choosingPlayerId, gameOptions);
|
||||
if (startingPlayerSkipsDraw) {
|
||||
state.getTurnMods().add(new TurnMod(startingPlayerId, PhaseStep.DRAW));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> getOpponents(UUID playerId) {
|
||||
Set<UUID> opponents = new HashSet<>();
|
||||
for (UUID opponentId: this.getPlayer(playerId).getInRange()) {
|
||||
if (!opponentId.equals(playerId)) {
|
||||
opponents.add(opponentId);
|
||||
}
|
||||
}
|
||||
return opponents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpponent(Player player, UUID playerToCheck) {
|
||||
return !player.getId().equals(playerToCheck);
|
||||
}
|
||||
|
||||
public void setAlsoLibrary(boolean alsoLibrary) {
|
||||
this.alsoLibrary = alsoLibrary;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -28,6 +28,9 @@
|
|||
|
||||
package mage.game.stack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.Mana;
|
||||
|
|
@ -47,7 +50,11 @@ import mage.abilities.keyword.BestowAbility;
|
|||
import mage.abilities.keyword.MorphAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.SplitCard;
|
||||
import mage.constants.*;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.SpellAbilityType;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.Counter;
|
||||
import mage.counters.Counters;
|
||||
import mage.game.Game;
|
||||
|
|
@ -59,10 +66,6 @@ import mage.target.Target;
|
|||
import mage.target.TargetAmount;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
|
@ -181,7 +184,7 @@ public class Spell implements StackObject, Card {
|
|||
// 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
|
||||
// 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.
|
||||
legalParts |= spellAbilityHasLegalParts(spellAbility, game);
|
||||
}
|
||||
|
|
@ -635,7 +638,14 @@ public class Spell implements StackObject, Card {
|
|||
index = symbolString.indexOf("{X}");
|
||||
}
|
||||
}
|
||||
cmc += spellAbility.getManaCosts().convertedManaCost() + spellAbility.getManaCostsToPay().getX() * xMultiplier;
|
||||
if (this.getSpellAbility().getSpellAbilityType().equals(SpellAbilityType.BASE_ALTERNATE)) {
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -299,7 +299,7 @@ public interface Player extends MageItem, Copyable<Player> {
|
|||
boolean chooseUse(Outcome outcome, String message, Game game);
|
||||
boolean choose(Outcome outcome, Choice choice, Game game);
|
||||
boolean choosePile(Outcome outcome, String message, List<? extends Card> pile1, List<? extends Card> pile2, Game game);
|
||||
boolean playMana(ManaCost unpaid, Game game);
|
||||
boolean playMana(ManaCost unpaid, String promptText, Game game);
|
||||
|
||||
/**
|
||||
* Moves the cards from cards to the bottom of the players library.
|
||||
|
|
|
|||
|
|
@ -1628,6 +1628,9 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
MageObject source = game.getPermanentOrLKIBattlefield(sourceId);
|
||||
if (source == null) {
|
||||
source = game.getObject(sourceId);
|
||||
if (source instanceof Card && !CardUtil.isPermanentCard((Card)source)) {
|
||||
source = game.getLastKnownInformation(sourceId, Zone.STACK);
|
||||
}
|
||||
if (source instanceof Spell) {
|
||||
sourceControllerId = ((Spell) source).getControllerId();
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ public class TargetCardInLibrary extends TargetCard {
|
|||
Collections.sort(cards, new CardNameComparator());
|
||||
while (!isChosen() && !doneChosing()) {
|
||||
chosen = targets.size() >= minNumberOfTargets;
|
||||
if (!player.choose(outcome, new CardsImpl(Zone.LIBRARY, cards), this, game)) {
|
||||
if (!player.chooseTarget(outcome, new CardsImpl(Zone.LIBRARY, cards), this, null, game)) {
|
||||
return chosen;
|
||||
}
|
||||
chosen = targets.size() >= minNumberOfTargets;
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ public class TargetControlledPermanent extends TargetPermanent {
|
|||
this(1, 1, filter, false);
|
||||
}
|
||||
|
||||
public TargetControlledPermanent(int minNumTargets, int maxNumTargets, FilterPermanent filter, boolean notTarget) {
|
||||
public TargetControlledPermanent(int minNumTargets, int maxNumTargets, FilterControlledPermanent filter, boolean notTarget) {
|
||||
super(minNumTargets, maxNumTargets, filter, notTarget);
|
||||
this.targetName = filter.getMessage();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -479,12 +479,19 @@ public class CardUtil {
|
|||
}
|
||||
|
||||
public static UUID getObjectExileZoneId(Game game, MageObject mageObject) {
|
||||
return getObjectExileZoneId(game, mageObject, false);
|
||||
}
|
||||
|
||||
public static UUID getObjectExileZoneId(Game game, MageObject mageObject, boolean previous) {
|
||||
int zoneChangeCounter = 0;
|
||||
if (mageObject instanceof Permanent) {
|
||||
zoneChangeCounter = ((Permanent) mageObject).getZoneChangeCounter();
|
||||
} else if (mageObject instanceof Card) {
|
||||
zoneChangeCounter = ((Card) mageObject).getZoneChangeCounter();
|
||||
}
|
||||
if (zoneChangeCounter > 0 && previous) {
|
||||
zoneChangeCounter--;
|
||||
}
|
||||
return getExileZoneId(getObjectZoneString(SOURCE_EXILE_ZONE_TEXT,mageObject.getId(), game, zoneChangeCounter, false), game);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,10 @@ import java.util.HashSet;
|
|||
import java.util.LinkedHashMap;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.mana.AlternateManaPaymentAbility;
|
||||
import mage.game.Game;
|
||||
|
||||
/**
|
||||
* @author noxx
|
||||
|
|
@ -334,4 +338,28 @@ public class ManaUtil {
|
|||
|
||||
return useableAbilities;
|
||||
}
|
||||
|
||||
/**
|
||||
* This activates the special button inthe feedback panel of the client
|
||||
* if there exists special ways to pay the mana (e.g. Delve, Convoke)
|
||||
*
|
||||
* @param source ability the mana costs have to be paid for
|
||||
* @param game
|
||||
* @param unpaid mana that has still to be paid
|
||||
* @return message to be shown in human players feedback area
|
||||
*/
|
||||
public static String addSpecialManaPayAbilities(Ability source, Game game, ManaCost unpaid) {
|
||||
// check for special mana payment possibilities
|
||||
MageObject mageObject = source.getSourceObject(game);
|
||||
if (mageObject != null) {
|
||||
for (Ability ability :mageObject.getAbilities()) {
|
||||
if (ability instanceof AlternateManaPaymentAbility) {
|
||||
((AlternateManaPaymentAbility) ability).addSpecialAction(source, game, unpaid);
|
||||
}
|
||||
}
|
||||
return unpaid.getText() + "<div style='font-size:11pt'>" + mageObject.getLogName() + "</div>";
|
||||
} else {
|
||||
return unpaid.getText();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ public class MiracleWatcher extends Watcher {
|
|||
Cards cards = new CardsImpl();
|
||||
cards.add(card);
|
||||
controller.lookAtCards("Miracle", cards, game);
|
||||
if (controller.chooseUse(Outcome.Benefit, "Reveal card to be able to use Miracle?", game)) {
|
||||
if (controller.chooseUse(Outcome.Benefit, "Reveal " + card.getName() + " to be able to use Miracle?", game)) {
|
||||
controller.revealCards("Miracle", cards, game);
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.MIRACLE_CARD_REVEALED, card.getId(), card.getId(),controller.getId()));
|
||||
break;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue