mirror of
https://github.com/magefree/mage.git
synced 2025-12-24 12:31:59 -08:00
Merge origin/master
This commit is contained in:
commit
1d450730c0
129 changed files with 5752 additions and 2644 deletions
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package mage.abilities;
|
||||
|
||||
import java.util.UUID;
|
||||
|
|
@ -154,13 +153,19 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa
|
|||
@Override
|
||||
public ActivationStatus canActivate(UUID playerId, Game game) {
|
||||
//20091005 - 602.2
|
||||
if (!(hasMoreActivationsThisTurn(game) && (condition == null || condition.apply(game, this)))) {
|
||||
if (!(hasMoreActivationsThisTurn(game)
|
||||
&& (condition == null
|
||||
|| condition.apply(game, this)))) {
|
||||
return ActivationStatus.getFalse();
|
||||
}
|
||||
switch (mayActivate) {
|
||||
case ANY:
|
||||
break;
|
||||
|
||||
case ACTIVE:
|
||||
if (game.getActivePlayerId() != playerId) {
|
||||
return ActivationStatus.getFalse();
|
||||
}
|
||||
break;
|
||||
case NOT_YOU:
|
||||
if (controlsAbility(playerId, game)) {
|
||||
return ActivationStatus.getFalse();
|
||||
|
|
@ -198,9 +203,17 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa
|
|||
return ActivationStatus.getFalse();
|
||||
}
|
||||
//20091005 - 602.5d/602.5e
|
||||
MageObjectReference permittingObject = game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_AS_INSTANT, this, controllerId, game);
|
||||
if (timing == TimingRule.INSTANT || game.canPlaySorcery(playerId) || null != permittingObject) {
|
||||
if (costs.canPay(this, sourceId, playerId, game) && canChooseTarget(game)) {
|
||||
MageObjectReference permittingObject = game.getContinuousEffects()
|
||||
.asThough(sourceId,
|
||||
AsThoughEffectType.ACTIVATE_AS_INSTANT,
|
||||
this,
|
||||
controllerId,
|
||||
game);
|
||||
if (timing == TimingRule.INSTANT
|
||||
|| game.canPlaySorcery(playerId)
|
||||
|| null != permittingObject) {
|
||||
if (costs.canPay(this, sourceId, playerId, game)
|
||||
&& canChooseTarget(game)) {
|
||||
this.activatorId = playerId;
|
||||
return new ActivationStatus(true, permittingObject);
|
||||
}
|
||||
|
|
@ -297,8 +310,10 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa
|
|||
}
|
||||
|
||||
protected ActivationInfo getActivationInfo(Game game) {
|
||||
Integer turnNum = (Integer) game.getState().getValue(CardUtil.getCardZoneString("activationsTurn" + originalId, sourceId, game));
|
||||
Integer activationCount = (Integer) game.getState().getValue(CardUtil.getCardZoneString("activationsCount" + originalId, sourceId, game));
|
||||
Integer turnNum = (Integer) game.getState()
|
||||
.getValue(CardUtil.getCardZoneString("activationsTurn" + originalId, sourceId, game));
|
||||
Integer activationCount = (Integer) game.getState()
|
||||
.getValue(CardUtil.getCardZoneString("activationsCount" + originalId, sourceId, game));
|
||||
if (turnNum == null || activationCount == null) {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -306,7 +321,9 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa
|
|||
}
|
||||
|
||||
protected void setActivationInfo(ActivationInfo activationInfo, Game game) {
|
||||
game.getState().setValue(CardUtil.getCardZoneString("activationsTurn" + originalId, sourceId, game), activationInfo.turnNum);
|
||||
game.getState().setValue(CardUtil.getCardZoneString("activationsCount" + originalId, sourceId, game), activationInfo.activationCounter);
|
||||
game.getState().setValue(CardUtil
|
||||
.getCardZoneString("activationsTurn" + originalId, sourceId, game), activationInfo.turnNum);
|
||||
game.getState().setValue(CardUtil
|
||||
.getCardZoneString("activationsCount" + originalId, sourceId, game), activationInfo.activationCounter);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
package mage.abilities.effects.common;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
|
|
@ -32,35 +32,58 @@ public class FightTargetsEffect extends OneShotEffect {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Card card = game.getCard(source.getSourceId());
|
||||
if (card != null) {
|
||||
// only if both targets are legal the effect will be applied
|
||||
if (source.getTargets().get(0).isLegal(source, game) && source.getTargets().get(1).isLegal(source, game)) {
|
||||
Permanent creature1 = game.getPermanent(source.getTargets().get(0).getFirstTarget());
|
||||
Permanent creature2 = game.getPermanent(source.getTargets().get(1).getFirstTarget());
|
||||
// 20110930 - 701.10
|
||||
if (creature1 != null && creature2 != null) {
|
||||
if (creature1.isCreature() && creature2.isCreature()) {
|
||||
return creature1.fight(creature2, source, game);
|
||||
}
|
||||
UUID target1Id = null;
|
||||
UUID target2Id = null;
|
||||
// first target is in target pointer, second target is a normal target
|
||||
if (source.getTargets().size() < 2) {
|
||||
if (!source.getTargets().get(0).isLegal(source, game)) {
|
||||
return false;
|
||||
}
|
||||
target1Id = getTargetPointer().getFirst(game, source);
|
||||
target2Id = source.getTargets().getFirstTarget();
|
||||
if (target1Id == target2Id) {
|
||||
return false;
|
||||
}
|
||||
// two normal targets available, only if both targets are legal the effect will be applied
|
||||
} else if (source.getTargets().get(0).isLegal(source, game) && source.getTargets().get(1).isLegal(source, game)) {
|
||||
target1Id = source.getTargets().get(0).getFirstTarget();
|
||||
target2Id = source.getTargets().get(1).getFirstTarget();
|
||||
}
|
||||
Permanent creature1 = game.getPermanent(target1Id);
|
||||
Permanent creature2 = game.getPermanent(target2Id);
|
||||
// 20110930 - 701.10
|
||||
if (creature1 != null && creature2 != null) {
|
||||
if (creature1.isCreature() && creature2.isCreature()) {
|
||||
return creature1.fight(creature2, source, game);
|
||||
}
|
||||
}
|
||||
if (!game.isSimulation()) {
|
||||
game.informPlayers(card.getName() + " has been fizzled.");
|
||||
}
|
||||
}
|
||||
if (!game.isSimulation()) {
|
||||
game.informPlayers(card.getName() + " has been fizzled.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FightTargetsEffect copy() {
|
||||
public FightTargetsEffect
|
||||
copy() {
|
||||
return new FightTargetsEffect(this);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(Mode mode) {
|
||||
if (staticText != null && !staticText.isEmpty()) {
|
||||
public String
|
||||
getText(Mode mode
|
||||
) {
|
||||
if (staticText
|
||||
!= null && !staticText
|
||||
.isEmpty()) {
|
||||
return staticText;
|
||||
|
||||
}
|
||||
return "Target " + mode.getTargets().get(0).getTargetName() + " fights another target " + mode.getTargets().get(1).getTargetName();
|
||||
return "Target " + mode
|
||||
.getTargets().get(0).getTargetName() + " fights another target " + mode
|
||||
.getTargets().get(1).getTargetName();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package mage.abilities.effects.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ReplacementEffectImpl;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jeffwadsworth
|
||||
*/
|
||||
|
||||
public class SkipCombatStepEffect extends ReplacementEffectImpl {
|
||||
|
||||
public SkipCombatStepEffect(Duration duration) {
|
||||
super(duration, Outcome.Detriment);
|
||||
staticText = "that player skips their next combat phase";
|
||||
}
|
||||
|
||||
public SkipCombatStepEffect(final SkipCombatStepEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkipCombatStepEffect copy() {
|
||||
return new SkipCombatStepEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.COMBAT_PHASE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
return event.getPlayerId().equals(targetPointer.getFirst(game, source));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package mage.abilities.effects.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ReplacementEffectImpl;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jeffwadsworth
|
||||
*/
|
||||
|
||||
public class SkipNextDrawStepTargetEffect extends ReplacementEffectImpl {
|
||||
|
||||
public SkipNextDrawStepTargetEffect() {
|
||||
super(Duration.OneUse, Outcome.Detriment);
|
||||
staticText = "Target player skips his or her next draw step";
|
||||
}
|
||||
|
||||
public SkipNextDrawStepTargetEffect(final SkipNextDrawStepTargetEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkipNextDrawStepTargetEffect copy() {
|
||||
return new SkipNextDrawStepTargetEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DRAW_STEP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
return event.getPlayerId().equals(source.getFirstTarget());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,8 @@
|
|||
package mage.abilities.meta;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.TriggeredAbility;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
|
|
@ -8,10 +11,6 @@ import mage.game.Game;
|
|||
import mage.game.events.GameEvent;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* A triggered ability that combines several others and triggers whenever one or
|
||||
* more of them would. The abilities passed in should have null as their effect,
|
||||
|
|
@ -56,7 +55,6 @@ public class OrTriggeredAbility extends TriggeredAbilityImpl {
|
|||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
for (TriggeredAbility ability : triggeredAbilities) {
|
||||
if (ability.checkEventType(event, game)) {
|
||||
System.out.println("Correct event type (" + event.getType() + ")");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -69,11 +67,9 @@ public class OrTriggeredAbility extends TriggeredAbilityImpl {
|
|||
for (int i = 0; i < triggeredAbilities.length; i++) {
|
||||
TriggeredAbility ability = triggeredAbilities[i];
|
||||
if (ability.checkEventType(event, game) && ability.checkTrigger(event, game)) {
|
||||
System.out.println("Triggered from " + ability.getRule());
|
||||
triggeringAbilities.add(i);
|
||||
toRet = true;
|
||||
}
|
||||
System.out.println("Checked " + ability.getRule());
|
||||
}
|
||||
return toRet;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ public enum CardRepository {
|
|||
// raise this if db structure was changed
|
||||
private static final long CARD_DB_VERSION = 51;
|
||||
// raise this if new cards were added to the server
|
||||
private static final long CARD_CONTENT_VERSION = 122;
|
||||
private static final long CARD_CONTENT_VERSION = 123;
|
||||
private Dao<CardInfo, Object> cardDao;
|
||||
private Set<String> classNames;
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ public enum CounterType {
|
|||
|
||||
AGE("age"),
|
||||
AIM("aim"),
|
||||
ARROW("arrow"),
|
||||
ARROWHEAD("arrowhead"),
|
||||
AWAKENING("awakening"),
|
||||
BLAZE("blaze"),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package mage.filter.predicate.other;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Mode;
|
||||
import mage.filter.predicate.ObjectSourcePlayer;
|
||||
import mage.filter.predicate.ObjectSourcePlayerPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jeffwadsworth
|
||||
*/
|
||||
public class TargetsPlayerPredicate implements ObjectSourcePlayerPredicate<ObjectSourcePlayer<MageObject>> {
|
||||
|
||||
public TargetsPlayerPredicate() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(ObjectSourcePlayer<MageObject> input, Game game) {
|
||||
StackObject object = game.getStack().getStackObject(input.getObject().getId());
|
||||
if (object != null) {
|
||||
for (UUID modeId : object.getStackAbility().getModes().getSelectedModes()) {
|
||||
Mode mode = object.getStackAbility().getModes().get(modeId);
|
||||
for (Target target : mode.getTargets()) {
|
||||
for (UUID targetId : target.getTargets()) {
|
||||
Player player = game.getPlayer(targetId);
|
||||
return player != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "that targets a player";
|
||||
}
|
||||
}
|
||||
|
|
@ -37,6 +37,7 @@ public class MatchOptions implements Serializable {
|
|||
protected boolean spectatorsAllowed;
|
||||
protected boolean planeChase;
|
||||
protected int quitRatio;
|
||||
protected int minimumRating;
|
||||
protected int edhPowerLevel;
|
||||
protected boolean rated;
|
||||
protected int numSeatsForMatch;
|
||||
|
|
@ -205,6 +206,10 @@ public class MatchOptions implements Serializable {
|
|||
this.quitRatio = quitRatio;
|
||||
}
|
||||
|
||||
public int getMinimumRating() { return minimumRating; }
|
||||
|
||||
public void setMinimumRating(int minimumRating) { this.minimumRating = minimumRating; }
|
||||
|
||||
public int getEdhPowerLevel() {
|
||||
return edhPowerLevel;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ public class TournamentOptions implements Serializable {
|
|||
protected int numberRounds;
|
||||
protected String password;
|
||||
protected int quitRatio;
|
||||
protected int minimumRating;
|
||||
|
||||
public TournamentOptions(String name, String matchType, int numSeats) {
|
||||
this.name = name;
|
||||
|
|
@ -98,4 +99,8 @@ public class TournamentOptions implements Serializable {
|
|||
public void setQuitRatio(int quitRatio) {
|
||||
this.quitRatio = quitRatio;
|
||||
}
|
||||
|
||||
public int getMinimumRating() { return minimumRating; }
|
||||
|
||||
public void setMinimumRating(int minimumRating) { this.minimumRating = minimumRating; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -349,6 +349,15 @@ public interface Player extends MageItem, Copyable<Player> {
|
|||
*/
|
||||
boolean searchLibrary(TargetCardInLibrary target, Game game, UUID targetPlayerId, boolean triggerEvents);
|
||||
|
||||
/**
|
||||
* Reveals all players' libraries. Useful for abilities like Jace, Architect of Thought's -8
|
||||
* that have effects that require information from all libraries.
|
||||
* @param source
|
||||
* @param game
|
||||
* @return
|
||||
*/
|
||||
void lookAtAllLibraries(Ability source, Game game);
|
||||
|
||||
boolean canPlayLand();
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2489,6 +2489,17 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lookAtAllLibraries(Ability source, Game game) {
|
||||
for(UUID playerId : game.getState().getPlayersInRange(this.getId(), game)){
|
||||
Player player = game.getPlayer(playerId);
|
||||
String playerName = this.getName().equals(player.getName()) ? "Your " : player.getName() + "'s ";
|
||||
playerName += "library";
|
||||
Cards cardsInLibrary = new CardsImpl(player.getLibrary().getTopCards(game, player.getLibrary().size()));
|
||||
lookAtCards(playerName, cardsInLibrary, game);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean handleLibraryCastableCards(Library library, Game game, UUID targetPlayerId) {
|
||||
// for handling Panglacial Wurm
|
||||
boolean alreadyChosenUse = false;
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ public final class ClassScanner {
|
|||
if(classLoader == null) classLoader = Thread.currentThread().getContextClassLoader();
|
||||
assert classLoader != null;
|
||||
|
||||
HashMap<String, String> dirs = new HashMap<>();
|
||||
TreeSet<String> jars = new TreeSet<>();
|
||||
Map<String, String> dirs = new HashMap<>();
|
||||
Set<String> jars = new TreeSet<>();
|
||||
for (String packageName : packages) {
|
||||
String path = packageName.replace('.', '/');
|
||||
Enumeration<URL> resources = classLoader.getResources(path);
|
||||
|
|
@ -51,8 +51,8 @@ public final class ClassScanner {
|
|||
}
|
||||
}
|
||||
|
||||
for (String filePath : dirs.keySet()) {
|
||||
cards.addAll(findClasses(classLoader, new File(filePath), dirs.get(filePath), type));
|
||||
for (Map.Entry<String, String> dir : dirs.entrySet()) {
|
||||
cards.addAll(findClasses(classLoader, new File(dir.getKey()), dir.getValue(), type));
|
||||
}
|
||||
|
||||
for (String filePath : jars) {
|
||||
|
|
@ -66,7 +66,7 @@ public final class ClassScanner {
|
|||
|
||||
private static List<Class> findClasses(ClassLoader classLoader, File directory, String packageName, Class<?> type) {
|
||||
List<Class> cards = new ArrayList<>();
|
||||
if (!directory.exists()) return cards;
|
||||
if (directory == null || !directory.exists()) return cards;
|
||||
|
||||
for (File file : directory.listFiles()) {
|
||||
if (file.getName().endsWith(".class")) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue