mirror of
https://github.com/magefree/mage.git
synced 2025-12-25 21:12:04 -08:00
Merge remote-tracking branch 'remotes/upstream/master'
This commit is contained in:
commit
bd4d00f031
172 changed files with 2189 additions and 1304 deletions
|
|
@ -28,6 +28,7 @@
|
|||
package mage.abilities;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.Costs;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
|
|
@ -42,6 +43,7 @@ import mage.constants.TargetController;
|
|||
import mage.constants.TimingRule;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.command.Emblem;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
|
|
@ -215,9 +217,13 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa
|
|||
if (this.controllerId != null && this.controllerId.equals(playerId)) {
|
||||
return true;
|
||||
} else {
|
||||
Card card = (Card) game.getObject(this.sourceId);
|
||||
if (card != null && game.getState().getZone(this.sourceId) != Zone.BATTLEFIELD) {
|
||||
return card.getOwnerId().equals(playerId);
|
||||
MageObject mageObject = game.getObject(this.sourceId);
|
||||
if (mageObject instanceof Emblem) {
|
||||
return ((Emblem) mageObject).getControllerId().equals(playerId);
|
||||
} else {
|
||||
if (game.getState().getZone(this.sourceId) != Zone.BATTLEFIELD) {
|
||||
return ((Card) mageObject).getOwnerId().equals(playerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -69,6 +69,6 @@ public class CounterTargetEffect extends OneShotEffect {
|
|||
if (staticText != null && !staticText.isEmpty()) {
|
||||
return staticText;
|
||||
}
|
||||
return "counter target " + (mode.getTargets().get(0) != null ? mode.getTargets().get(0).getTargetName() : "spell");
|
||||
return "counter target " + (!mode.getTargets().isEmpty() ? mode.getTargets().get(0).getTargetName() : "spell");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,9 +109,8 @@ public class BecomesColorSourceEffect extends ContinuousEffectImpl {
|
|||
this.discard();
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
throw new UnsupportedOperationException("No color set");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -68,12 +68,8 @@ public class AftermathAbility extends SimpleStaticAbility {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getRule(boolean all) {
|
||||
if (all) {
|
||||
return "Aftermath <i>(Cast this card only from your graveyard. Exile it afterwards.)</i>";
|
||||
} else {
|
||||
return "Aftermath";
|
||||
}
|
||||
public String getRule() {
|
||||
return "Aftermath <i>(Cast this spell only from your graveyard. Then exile it.)</i>";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -81,7 +77,6 @@ class AftermathCastFromGraveyard extends AsThoughEffectImpl {
|
|||
|
||||
public AftermathCastFromGraveyard() {
|
||||
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfGame, Outcome.Benefit);
|
||||
staticText = "Cast {this} from your graveyard";
|
||||
}
|
||||
|
||||
public AftermathCastFromGraveyard(final AftermathCastFromGraveyard effect) {
|
||||
|
|
@ -98,10 +93,6 @@ class AftermathCastFromGraveyard extends AsThoughEffectImpl {
|
|||
return new AftermathCastFromGraveyard(this);
|
||||
}
|
||||
|
||||
private static String msb(UUID id) {
|
||||
return Integer.toUnsignedString((int) id.getMostSignificantBits(), 16);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
if (objectId.equals(source.getSourceId())
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@
|
|||
*/
|
||||
package mage.cards;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Abilities;
|
||||
import mage.abilities.AbilitiesImpl;
|
||||
import mage.abilities.Ability;
|
||||
|
|
@ -36,10 +39,6 @@ import mage.constants.SpellAbilityType;
|
|||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ package mage.cards.repository;
|
|||
import com.j256.ormlite.field.DataType;
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
|
|
@ -41,16 +43,13 @@ import mage.constants.*;
|
|||
import mage.util.SubTypeList;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author North
|
||||
*/
|
||||
@DatabaseTable(tableName = "card")
|
||||
public class CardInfo {
|
||||
|
||||
private static final int MAX_RULE_LENGTH = 700;
|
||||
private static final int MAX_RULE_LENGTH = 750;
|
||||
|
||||
private static final String SEPARATOR = "@@@";
|
||||
@DatabaseField(indexName = "name_index")
|
||||
|
|
@ -157,13 +156,30 @@ public class CardInfo {
|
|||
this.setManaCosts(card.getManaCost().getSymbols());
|
||||
|
||||
int length = 0;
|
||||
for (String rule : card.getRules()) {
|
||||
length += rule.length();
|
||||
List<String> rulesList = new ArrayList<>();
|
||||
if (card instanceof SplitCard) {
|
||||
for (String rule : ((SplitCard) card).getLeftHalfCard().getRules()) {
|
||||
length += rule.length();
|
||||
rulesList.add(rule);
|
||||
}
|
||||
for (String rule : ((SplitCard) card).getRightHalfCard().getRules()) {
|
||||
length += rule.length();
|
||||
rulesList.add(rule);
|
||||
}
|
||||
for (String rule : card.getRules()) {
|
||||
length += rule.length();
|
||||
rulesList.add(rule);
|
||||
}
|
||||
} else {
|
||||
for (String rule : card.getRules()) {
|
||||
length += rule.length();
|
||||
rulesList.add(rule);
|
||||
}
|
||||
}
|
||||
if (length > MAX_RULE_LENGTH) {
|
||||
length = 0;
|
||||
ArrayList<String> shortRules = new ArrayList<>();
|
||||
for (String rule : card.getRules()) {
|
||||
for (String rule : rulesList) {
|
||||
if (length + rule.length() + 3 <= MAX_RULE_LENGTH) {
|
||||
shortRules.add(rule);
|
||||
length += rule.length() + 3;
|
||||
|
|
@ -175,7 +191,7 @@ public class CardInfo {
|
|||
Logger.getLogger(CardInfo.class).warn("Card rule text was cut - cardname: " + card.getName());
|
||||
this.setRules(shortRules);
|
||||
} else {
|
||||
this.setRules(card.getRules());
|
||||
this.setRules(rulesList);
|
||||
}
|
||||
|
||||
SpellAbility spellAbility = card.getSpellAbility();
|
||||
|
|
@ -306,7 +322,7 @@ public class CardInfo {
|
|||
|
||||
public final SubTypeList getSubTypes() {
|
||||
SubTypeList sl = new SubTypeList();
|
||||
if(subtypes.trim().isEmpty()){
|
||||
if (subtypes.trim().isEmpty()) {
|
||||
return sl;
|
||||
}
|
||||
for (String s : subtypes.split(SEPARATOR)) {
|
||||
|
|
|
|||
|
|
@ -37,16 +37,15 @@ import com.j256.ormlite.stmt.Where;
|
|||
import com.j256.ormlite.support.ConnectionSource;
|
||||
import com.j256.ormlite.support.DatabaseConnection;
|
||||
import com.j256.ormlite.table.TableUtils;
|
||||
import java.io.File;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SetType;
|
||||
import mage.util.RandomUtil;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author North
|
||||
*/
|
||||
|
|
@ -59,7 +58,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 = 85;
|
||||
private static final long CARD_CONTENT_VERSION = 86;
|
||||
private final TreeSet<String> landTypes = new TreeSet<>();
|
||||
private Dao<CardInfo, Object> cardDao;
|
||||
private Set<String> classNames;
|
||||
|
|
@ -274,10 +273,6 @@ public enum CardRepository {
|
|||
return names;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public CardInfo findCard(String setCode, String cardNumber) {
|
||||
try {
|
||||
QueryBuilder<CardInfo, Object> queryBuilder = cardDao.queryBuilder();
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
package mage.constants;
|
||||
|
||||
import mage.util.SubTypeList;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import mage.util.SubTypeList;
|
||||
|
||||
public enum SubType {
|
||||
|
||||
|
|
@ -427,8 +428,8 @@ public enum SubType {
|
|||
return subTypes;
|
||||
}
|
||||
|
||||
public static Set<String> getBasicLands(boolean customSet) {
|
||||
return Arrays.stream(values()).filter(s -> s.customSet == customSet).filter(p -> p.getSubTypeSet() == SubTypeSet.BasicLandType).map(SubType::getDescription).collect(Collectors.toSet());
|
||||
public static Set<SubType> getBasicLands(boolean customSet) {
|
||||
return Arrays.stream(values()).filter(s -> s.customSet == customSet).filter(p -> p.getSubTypeSet() == SubTypeSet.BasicLandType).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
public static SubTypeList getLandTypes(boolean customSet) {
|
||||
|
|
|
|||
|
|
@ -7,9 +7,12 @@ package mage.filter;
|
|||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.filter.common.*;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||
import mage.filter.predicate.mageobject.SubtypePredicate;
|
||||
import mage.filter.predicate.mageobject.SupertypePredicate;
|
||||
import mage.filter.predicate.permanent.AnotherPredicate;
|
||||
import mage.filter.predicate.permanent.AttackingPredicate;
|
||||
import mage.filter.predicate.permanent.TokenPredicate;
|
||||
|
|
@ -64,6 +67,26 @@ public final class StaticFilters {
|
|||
|
||||
public static final FilterPermanent FILTER_ATTACKING_CREATURES = new FilterCreaturePermanent("attacking creatures");
|
||||
|
||||
|
||||
|
||||
public static final FilterPermanent FILTER_AURA = new FilterPermanent();
|
||||
public static final FilterPermanent FILTER_EQUIPMENT = new FilterPermanent();
|
||||
public static final FilterPermanent FILTER_FORTIFICATION = new FilterPermanent();
|
||||
public static final FilterPermanent FILTER_LEGENDARY = new FilterPermanent();
|
||||
|
||||
static {
|
||||
FILTER_AURA.add(new CardTypePredicate(CardType.ENCHANTMENT));
|
||||
FILTER_AURA.add(new SubtypePredicate(SubType.AURA));
|
||||
|
||||
FILTER_EQUIPMENT.add(new CardTypePredicate(CardType.ARTIFACT));
|
||||
FILTER_EQUIPMENT.add(new SubtypePredicate(SubType.EQUIPMENT));
|
||||
|
||||
FILTER_FORTIFICATION.add(new CardTypePredicate(CardType.ARTIFACT));
|
||||
FILTER_FORTIFICATION.add(new SubtypePredicate(SubType.FORTIFICATION));
|
||||
|
||||
FILTER_LEGENDARY.add(new SupertypePredicate(SuperType.LEGENDARY));
|
||||
}
|
||||
|
||||
static {
|
||||
FILTER_CONTROLLED_PERMANENT_NON_LAND.add(
|
||||
Predicates.not(new CardTypePredicate(CardType.LAND)));
|
||||
|
|
|
|||
|
|
@ -28,7 +28,9 @@
|
|||
package mage.filter.predicate.other;
|
||||
|
||||
import mage.cards.Card;
|
||||
import mage.cards.SplitCard;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.filter.predicate.Predicate;
|
||||
import mage.game.Game;
|
||||
|
||||
|
|
@ -39,9 +41,15 @@ import mage.game.Game;
|
|||
public class CardTextPredicate implements Predicate<Card> {
|
||||
|
||||
private final String text;
|
||||
private final boolean inNames;
|
||||
private final boolean inTypes;
|
||||
private final boolean inRules;
|
||||
|
||||
public CardTextPredicate(String text) {
|
||||
public CardTextPredicate(String text, boolean inNames, boolean inTypes, boolean inRules) {
|
||||
this.text = text;
|
||||
this.inNames = inNames;
|
||||
this.inTypes = inTypes;
|
||||
this.inRules = inRules;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -50,7 +58,7 @@ public class CardTextPredicate implements Predicate<Card> {
|
|||
return true;
|
||||
}
|
||||
// first check in card name
|
||||
if (input.getName().toLowerCase().contains(text.toLowerCase())) {
|
||||
if (inNames && input.getName().toLowerCase().contains(text.toLowerCase())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -60,17 +68,40 @@ public class CardTextPredicate implements Predicate<Card> {
|
|||
boolean found = false;
|
||||
if (!token.isEmpty()) {
|
||||
// then try to find in rules
|
||||
for (String rule : input.getRules(game)) {
|
||||
if (rule.toLowerCase().contains(token)) {
|
||||
found = true;
|
||||
break;
|
||||
if (inRules) {
|
||||
if (input.isSplitCard()) {
|
||||
for (String rule : ((SplitCard) input).getLeftHalfCard().getRules(game)) {
|
||||
if (rule.toLowerCase().contains(token)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (String rule : ((SplitCard) input).getRightHalfCard().getRules(game)) {
|
||||
if (rule.toLowerCase().contains(token)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (String rule : input.getRules(game)) {
|
||||
if (rule.toLowerCase().contains(token)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (SubType subType : input.getSubtype(game)) {
|
||||
if (subType.toString().equalsIgnoreCase(token)) {
|
||||
found = true;
|
||||
break;
|
||||
if (inTypes) {
|
||||
for (SubType subType : input.getSubtype(game)) {
|
||||
if (subType.toString().equalsIgnoreCase(token)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (SuperType superType : input.getSuperType()) {
|
||||
if (superType.toString().equalsIgnoreCase(token)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,9 +54,9 @@ import mage.designations.Monarch;
|
|||
import mage.filter.Filter;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.filter.common.FilterPlaneswalkerPermanent;
|
||||
import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||
import mage.filter.predicate.mageobject.NamePredicate;
|
||||
import mage.filter.predicate.mageobject.SubtypePredicate;
|
||||
import mage.filter.predicate.mageobject.SupertypePredicate;
|
||||
|
|
@ -103,24 +103,6 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
|
||||
private static final Logger logger = Logger.getLogger(GameImpl.class);
|
||||
|
||||
private static final FilterPermanent FILTER_AURA = new FilterPermanent();
|
||||
private static final FilterPermanent FILTER_EQUIPMENT = new FilterPermanent();
|
||||
private static final FilterPermanent FILTER_FORTIFICATION = new FilterPermanent();
|
||||
private static final FilterPermanent FILTER_LEGENDARY = new FilterPermanent();
|
||||
|
||||
static {
|
||||
FILTER_AURA.add(new CardTypePredicate(CardType.ENCHANTMENT));
|
||||
FILTER_AURA.add(new SubtypePredicate(SubType.AURA));
|
||||
|
||||
FILTER_EQUIPMENT.add(new CardTypePredicate(CardType.ARTIFACT));
|
||||
FILTER_EQUIPMENT.add(new SubtypePredicate(SubType.EQUIPMENT));
|
||||
|
||||
FILTER_FORTIFICATION.add(new CardTypePredicate(CardType.ARTIFACT));
|
||||
FILTER_FORTIFICATION.add(new SubtypePredicate(SubType.FORTIFICATION));
|
||||
|
||||
FILTER_LEGENDARY.add(new SupertypePredicate(SuperType.LEGENDARY));
|
||||
}
|
||||
|
||||
private transient Object customData;
|
||||
protected boolean simulation = false;
|
||||
|
||||
|
|
@ -1784,7 +1766,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
if (perm.isWorld()) {
|
||||
worldEnchantment.add(perm);
|
||||
}
|
||||
if (FILTER_AURA.match(perm, this)) {
|
||||
if (StaticFilters.FILTER_AURA.match(perm, this)) {
|
||||
//20091005 - 704.5n, 702.14c
|
||||
if (perm.getAttachedTo() == null) {
|
||||
Card card = this.getCard(perm.getId());
|
||||
|
|
@ -1862,10 +1844,10 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (this.getState().isLegendaryRuleActive() && FILTER_LEGENDARY.match(perm, this)) {
|
||||
if (this.getState().isLegendaryRuleActive() && StaticFilters.FILTER_LEGENDARY.match(perm, this)) {
|
||||
legendary.add(perm);
|
||||
}
|
||||
if (FILTER_EQUIPMENT.match(perm, this)) {
|
||||
if (StaticFilters.FILTER_EQUIPMENT.match(perm, this)) {
|
||||
//20091005 - 704.5p, 702.14d
|
||||
if (perm.getAttachedTo() != null) {
|
||||
Permanent attachedTo = getPermanent(perm.getAttachedTo());
|
||||
|
|
@ -1890,7 +1872,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (FILTER_FORTIFICATION.match(perm, this)) {
|
||||
if (StaticFilters.FILTER_FORTIFICATION.match(perm, this)) {
|
||||
if (perm.getAttachedTo() != null) {
|
||||
Permanent land = getPermanent(perm.getAttachedTo());
|
||||
if (land == null || !land.getAttachments().contains(perm.getId())) {
|
||||
|
|
|
|||
|
|
@ -282,20 +282,22 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
|||
if (blocked) {
|
||||
for (UUID blockerId : blockerOrder) {
|
||||
Permanent blocker = game.getPermanent(blockerId);
|
||||
int lethalDamage;
|
||||
if (attacker.getAbilities().containsKey(DeathtouchAbility.getInstance().getId())) {
|
||||
lethalDamage = 1;
|
||||
} else {
|
||||
lethalDamage = blocker.getToughness().getValue() - blocker.getDamage();
|
||||
if (blocker != null) {
|
||||
int lethalDamage;
|
||||
if (attacker.getAbilities().containsKey(DeathtouchAbility.getInstance().getId())) {
|
||||
lethalDamage = 1;
|
||||
} else {
|
||||
lethalDamage = blocker.getToughness().getValue() - blocker.getDamage();
|
||||
}
|
||||
if (lethalDamage >= damage) {
|
||||
assigned.put(blockerId, damage);
|
||||
damage = 0;
|
||||
break;
|
||||
}
|
||||
int damageAssigned = player.getAmount(lethalDamage, damage, "Assign damage to " + blocker.getName(), game);
|
||||
assigned.put(blockerId, damageAssigned);
|
||||
damage -= damageAssigned;
|
||||
}
|
||||
if (lethalDamage >= damage) {
|
||||
assigned.put(blockerId, damage);
|
||||
damage = 0;
|
||||
break;
|
||||
}
|
||||
int damageAssigned = player.getAmount(lethalDamage, damage, "Assign damage to " + blocker.getName(), game);
|
||||
assigned.put(blockerId, damageAssigned);
|
||||
damage -= damageAssigned;
|
||||
}
|
||||
if (damage > 0 && hasTrample(attacker)) {
|
||||
defenderDamage(attacker, damage, game);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue