This commit is contained in:
LoneFox 2015-09-25 20:51:29 +03:00
commit 0ebd773caf
55 changed files with 28614 additions and 28269 deletions

View file

@ -228,30 +228,62 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
for (ManaCost cost : this) {
if (!cost.isPaid() && cost instanceof ColoredManaCost) {
cost.assignPayment(game, ability, pool);
if (pool.count() == 0) {
return;
}
}
}
for (ManaCost cost : this) {
if (!cost.isPaid() && cost instanceof HybridManaCost) {
cost.assignPayment(game, ability, pool);
if (pool.count() == 0) {
return;
}
}
}
// Mono Hybrid mana costs
// First try only to pay colored mana with the pool
for (ManaCost cost : this) {
if (!cost.isPaid() && cost instanceof MonoHybridManaCost) {
if (((((MonoHybridManaCost) cost).containsColor(ColoredManaSymbol.W)) && pool.getWhite() > 0)
|| ((((MonoHybridManaCost) cost).containsColor(ColoredManaSymbol.B)) && pool.getBlack() > 0)
|| ((((MonoHybridManaCost) cost).containsColor(ColoredManaSymbol.R)) && pool.getRed() > 0)
|| ((((MonoHybridManaCost) cost).containsColor(ColoredManaSymbol.G)) && pool.getGreen() > 0)
|| ((((MonoHybridManaCost) cost).containsColor(ColoredManaSymbol.U)) && pool.getBlue() > 0)) {
cost.assignPayment(game, ability, pool);
if (pool.count() == 0) {
return;
}
}
}
}
// if colored didn't fit pay colorless with the mana
for (ManaCost cost : this) {
if (!cost.isPaid() && cost instanceof MonoHybridManaCost) {
cost.assignPayment(game, ability, pool);
if (pool.count() == 0) {
return;
}
}
}
for (ManaCost cost : this) {
if (!cost.isPaid() && cost instanceof SnowManaCost) {
cost.assignPayment(game, ability, pool);
if (pool.count() == 0) {
return;
}
}
}
for (ManaCost cost : this) {
if (!cost.isPaid() && cost instanceof GenericManaCost) {
cost.assignPayment(game, ability, pool);
if (pool.count() == 0) {
return;
}
}
}

View file

@ -148,7 +148,7 @@ public class DontUntapInControllersNextUntapStepTargetEffect extends ContinuousR
if (targetName != null && targetName.length() > 0) {
return targetName + " doesn't untap during its controller's next untap step";
} else {
return "Target " + (mode == null ? "creature" : mode.getTargets().get(0).getTargetName()) + " doesn't untap during its controller's next untap step";
return "target " + (mode == null ? "creature" : mode.getTargets().get(0).getTargetName()) + " doesn't untap during its controller's next untap step";
}
}

View file

@ -25,7 +25,6 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.abilities.effects.common;
import java.util.ArrayList;
@ -46,8 +45,7 @@ import mage.target.TargetPermanent;
import mage.util.CardUtil;
/**
* All opponents have to sacrifice [amount] permanents
* that match the [filter].
* All opponents have to sacrifice [amount] permanents that match the [filter].
*
* @author LevelX2
*/
@ -59,6 +57,7 @@ public class SacrificeOpponentsEffect extends OneShotEffect {
public SacrificeOpponentsEffect(FilterPermanent filter) {
this(1, filter);
}
public SacrificeOpponentsEffect(int amount, FilterPermanent filter) {
this(new StaticValue(amount), filter);
}
@ -87,12 +86,14 @@ public class SacrificeOpponentsEffect extends OneShotEffect {
filter.add(new ControllerPredicate(TargetController.YOU));
for (UUID playerId : game.getOpponents(source.getControllerId())) {
Player player = game.getPlayer(playerId);
if (player != null) {
if (player != null) {
int numTargets = Math.min(amount.calculate(game, source, this), game.getBattlefield().countAll(filter, player.getId(), game));
TargetPermanent target = new TargetPermanent(numTargets, numTargets, filter, true);
if (target.canChoose(player.getId(), game)) {
player.chooseTarget(Outcome.Sacrifice, target, source, game);
perms.addAll(target.getTargets());
if (numTargets > 0) {
TargetPermanent target = new TargetPermanent(numTargets, numTargets, filter, true);
if (target.canChoose(player.getId(), game)) {
player.chooseTarget(Outcome.Sacrifice, target, source, game);
perms.addAll(target.getTargets());
}
}
}
}

View file

@ -3,7 +3,6 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package mage.abilities.effects.common.combat;
import mage.abilities.Ability;
@ -12,6 +11,7 @@ import mage.constants.Duration;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.watchers.common.AttackedThisTurnWatcher;
/**
*
@ -24,19 +24,28 @@ public class AttacksIfAbleAllEffect extends RequirementEffect {
public AttacksIfAbleAllEffect(FilterCreaturePermanent filter) {
this(filter, Duration.WhileOnBattlefield);
}
boolean eachCombat;
public AttacksIfAbleAllEffect(FilterCreaturePermanent filter, Duration duration) {
this(filter, duration, false);
}
public AttacksIfAbleAllEffect(FilterCreaturePermanent filter, Duration duration, boolean eachCombat) {
super(duration);
staticText = new StringBuilder(filter.getMessage())
.append(" attack ")
.append(duration.equals(Duration.EndOfTurn) ? "this":"each")
.append(" turn if able").toString();
this.filter = filter;
this.eachCombat = eachCombat;
if (this.duration == Duration.EndOfTurn) {
staticText = filter.getMessage() + " attack " + (eachCombat ? "each combat" : "this turn") + " if able";
} else {
staticText = filter.getMessage() + " attack each " + (eachCombat ? "combat" : "turn") + " if able";
}
}
public AttacksIfAbleAllEffect(final AttacksIfAbleAllEffect effect) {
super(effect);
this.filter = effect.filter;
this.eachCombat = effect.eachCombat;
}
@Override
@ -46,7 +55,14 @@ public class AttacksIfAbleAllEffect extends RequirementEffect {
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
return filter.match(permanent, source.getSourceId(), source.getControllerId(), game);
if (filter.match(permanent, source.getSourceId(), source.getControllerId(), game)) {
if (eachCombat) {
return true;
}
AttackedThisTurnWatcher watcher = (AttackedThisTurnWatcher) game.getState().getWatchers().get("AttackedThisTurn");
return watcher != null && !watcher.getAttackedThisTurnCreatures().contains(permanent.getId());
}
return false;
}
@Override

View file

@ -25,13 +25,12 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.abilities.effects.common.combat;
import mage.constants.Duration;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.RequirementEffect;
import mage.constants.Duration;
import mage.game.Game;
import mage.game.permanent.Permanent;
@ -56,10 +55,7 @@ public class AttacksIfAbleTargetEffect extends RequirementEffect {
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
if (this.getTargetPointer().getTargets(game, source).contains(permanent.getId())) {
return true;
}
return false;
return this.getTargetPointer().getTargets(game, source).contains(permanent.getId());
}
@Override
@ -79,8 +75,7 @@ public class AttacksIfAbleTargetEffect extends RequirementEffect {
}
if (this.duration == Duration.EndOfTurn) {
return new StringBuilder("Target ").append(mode.getTargets().get(0).getTargetName()).append(" attacks this turn if able").toString();
}
else {
} else {
return new StringBuilder("Target ").append(mode.getTargets().get(0).getTargetName()).append(" attacks each turn if able").toString();
}
}

View file

@ -56,7 +56,10 @@ public abstract class ExpansionSet implements Serializable {
protected String blockName;
protected boolean hasBoosters = false;
protected int numBoosterSpecial;
protected int numBoosterLands;
protected int ratioBoosterSpecialLand = 0; // if > 0 basic lands are replaced with speical land in the ratio every X land is replaced by special land
protected int numBoosterCommon;
protected int numBoosterUncommon;
protected int numBoosterRare;
@ -150,9 +153,14 @@ public abstract class ExpansionSet implements Serializable {
}
if (numBoosterLands > 0) {
List<CardInfo> specialLands = getSpecialLand();
List<CardInfo> basicLands = getCardsByRarity(Rarity.LAND);
for (int i = 0; i < numBoosterLands; i++) {
addToBooster(booster, basicLands);
if (ratioBoosterSpecialLand > 0 && rnd.nextInt(ratioBoosterSpecialLand) == 1 && specialLands != null) {
addToBooster(booster, specialLands);
} else {
addToBooster(booster, basicLands);
}
}
}
List<CardInfo> commons = getCardsByRarity(Rarity.COMMON);
@ -320,6 +328,10 @@ public abstract class ExpansionSet implements Serializable {
return null;
}
public List<CardInfo> getSpecialLand() {
return null;
}
public void removeSavedCards() {
savedCards.clear();
}

View file

@ -63,7 +63,7 @@ public enum CardRepository {
// raise this if db structure was changed
private static final long CARD_DB_VERSION = 41;
// raise this if new cards were added to the server
private static final long CARD_CONTENT_VERSION = 37;
private static final long CARD_CONTENT_VERSION = 38;
private final Random random = new Random();
private Dao<CardInfo, Object> cardDao;

View file

@ -1,16 +1,16 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
@ -20,14 +20,14 @@
* 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.token;
import java.util.Random;
import mage.MageInt;
import mage.Mana;
import mage.abilities.costs.common.SacrificeSourceCost;
@ -49,7 +49,24 @@ public class EldraziScionToken extends Token {
power = new MageInt(1);
toughness = new MageInt(1);
addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, Mana.ColorlessMana, new SacrificeSourceCost()));
this.setOriginalExpansionSetCode("BFZ");
setOriginalExpansionSetCode("BFZ");
}
@Override
public void setExpansionSetCodeForImage(String code) {
super.setExpansionSetCodeForImage(code);
if (getOriginalExpansionSetCode().equals("BFZ")) {
this.setTokenType(new Random().nextInt(3) + 1); // 3 different images
}
}
public EldraziScionToken(final EldraziScionToken token) {
super(token);
}
@Override
public EldraziScionToken copy() {
return new EldraziScionToken(this); //To change body of generated methods, choose Tools | Templates.
}
}

View file

@ -171,6 +171,7 @@ public class Spell extends StackObjImpl implements Card {
int index = 0;
result = false;
boolean legalParts = false;
boolean notTargeted = true;
// check for legal parts
for (SpellAbility spellAbility : this.spellAbilities) {
// if muliple modes are selected, and there are modes with targets, then at least one mode has to have a legal target or
@ -178,10 +179,15 @@ public class Spell extends StackObjImpl implements Card {
// If all targets are illegal when the spell tries to resolve, the spell is countered and none of its effects happen.
// If at least one target is still legal at that time, the spell resolves, but an illegal target can't perform any actions
// or have any actions performed on it.
legalParts |= spellAbilityHasLegalParts(spellAbility, game);
// if only a spliced spell has targets and all targets ar illegal, the complete spell is countered
if (hasTargets(spellAbility, game)) {
notTargeted = false;
legalParts |= spellAbilityHasLegalParts(spellAbility, game);
}
}
// resolve if legal parts
if (legalParts) {
if (notTargeted || legalParts) {
for (SpellAbility spellAbility : this.spellAbilities) {
if (spellAbilityHasLegalParts(spellAbility, game)) {
for (UUID modeId : spellAbility.getModes().getSelectedModes()) {
@ -262,6 +268,21 @@ public class Spell extends StackObjImpl implements Card {
}
}
private boolean hasTargets(SpellAbility spellAbility, Game game) {
if (spellAbility.getModes().getSelectedModes().size() > 1) {
for (UUID modeId : spellAbility.getModes().getSelectedModes()) {
spellAbility.getModes().setActiveMode(modeId);
if (!spellAbility.getTargets().isEmpty()) {
return true;
}
}
return false;
} else {
return !spellAbility.getTargets().isEmpty();
}
}
private boolean spellAbilityHasLegalParts(SpellAbility spellAbility, Game game) {
if (spellAbility.getModes().getSelectedModes().size() > 1) {
boolean targetedMode = false;

View file

@ -2927,7 +2927,7 @@ public abstract class PlayerImpl implements Player, Serializable {
Set<Card> cardList = new HashSet<>();
for (UUID cardId : cards) {
fromZone = game.getState().getZone(cardId);
if (fromZone.equals(Zone.BATTLEFIELD)) {
if (Zone.BATTLEFIELD.equals(fromZone)) {
Permanent permanent = game.getPermanent(cardId);
if (permanent != null) {
cardList.add(permanent);

View file

@ -117,13 +117,15 @@ public class TargetSpellOrPermanent extends TargetImpl {
if (permanent != null) {
if (source != null) {
MageObject targetSource = game.getObject(source.getSourceId());
return permanent.canBeTargetedBy(targetSource, source.getControllerId(), game) && filter.match(permanent, source.getSourceId(), source.getControllerId(), game);
return permanent.canBeTargetedBy(targetSource, source.getControllerId(), game)
&& filter.match(permanent, source.getSourceId(), source.getControllerId(), game);
} else {
return filter.match(permanent, game);
}
}
Spell spell = game.getStack().getSpell(id);
if (spell != null) {
if (spell != null
&& !source.getSourceId().equals(id)) { // 114.4. A spell or ability on the stack is an illegal target for itself.
return filter.match(spell, game);
}
return false;
@ -151,7 +153,9 @@ public class TargetSpellOrPermanent extends TargetImpl {
MageObject targetSource = game.getObject(sourceId);
for (StackObject stackObject : game.getStack()) {
Spell spell = game.getStack().getSpell(stackObject.getId());
if (spell != null && filter.match(spell, sourceId, sourceControllerId, game)) {
if (spell != null
&& !sourceId.equals(spell.getSourceId())
&& filter.match(spell, sourceId, sourceControllerId, game)) {
count++;
if (count >= this.minNumberOfTargets) {
return true;
@ -184,7 +188,8 @@ public class TargetSpellOrPermanent extends TargetImpl {
int count = 0;
for (StackObject stackObject : game.getStack()) {
Spell spell = game.getStack().getSpell(stackObject.getId());
if (spell != null && filter.match(spell, null, sourceControllerId, game) && filter.match(spell, game)) {
if (spell != null
&& filter.match(spell, null, sourceControllerId, game) && filter.match(spell, game)) {
count++;
if (count >= this.minNumberOfTargets) {
return true;
@ -208,7 +213,9 @@ public class TargetSpellOrPermanent extends TargetImpl {
MageObject targetSource = game.getObject(sourceId);
for (StackObject stackObject : game.getStack()) {
Spell spell = game.getStack().getSpell(stackObject.getId());
if (spell != null && filter.match(spell, null, sourceControllerId, game) && filter.match(spell, game)) {
if (spell != null
&& !sourceId.equals(spell.getSourceId())
&& filter.match(spell, sourceId, sourceControllerId, game)) {
possibleTargets.add(spell.getId());
}
}
@ -225,7 +232,8 @@ public class TargetSpellOrPermanent extends TargetImpl {
Set<UUID> possibleTargets = new HashSet<>();
for (StackObject stackObject : game.getStack()) {
Spell spell = game.getStack().getSpell(stackObject.getId());
if (spell != null && filter.match(spell, null, sourceControllerId, game) && filter.match(spell, game)) {
if (spell != null
&& filter.match(spell, null, sourceControllerId, game)) {
possibleTargets.add(spell.getId());
}
}