mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-15 10:18:01 +00:00
Card: move Abilities to Card and only create them once
This commit is contained in:
@@ -608,7 +608,6 @@ public class ComputerUtilCost {
|
||||
Set<String> colorsAvailable = Sets.newHashSet();
|
||||
|
||||
if (additionalLands != null) {
|
||||
GameActionUtil.grantBasicLandsManaAbilities(additionalLands);
|
||||
cardsToConsider.addAll(additionalLands);
|
||||
}
|
||||
|
||||
|
||||
@@ -848,9 +848,6 @@ public class GameAction {
|
||||
}
|
||||
}
|
||||
|
||||
final CardCollection lands = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.LANDS);
|
||||
GameActionUtil.grantBasicLandsManaAbilities(lands);
|
||||
|
||||
for (final Card c : staticList) {
|
||||
for (int i = 0; i < c.getStaticCommandList().size(); i++) {
|
||||
final Object[] staticCheck = c.getStaticCommandList().get(i);
|
||||
@@ -896,13 +893,16 @@ public class GameAction {
|
||||
}
|
||||
}
|
||||
|
||||
final Map<String, Object> runParams = Maps.newHashMap();
|
||||
game.getTriggerHandler().runTrigger(TriggerType.Always, runParams, false);
|
||||
if (runEvents) {
|
||||
final Map<String, Object> runParams = Maps.newHashMap();
|
||||
game.getTriggerHandler().runTrigger(TriggerType.Always, runParams, false);
|
||||
}
|
||||
|
||||
// Update P/T and type in the view only once after all the cards have been processed, to avoid flickering
|
||||
for (Card c : affectedCards) {
|
||||
c.updatePowerToughnessForView();
|
||||
c.updateTypesForView();
|
||||
c.updateAbilityTextForView(); // only update keywords and text for view to avoid flickering
|
||||
}
|
||||
|
||||
if (runEvents && !affectedCards.isEmpty()) {
|
||||
|
||||
@@ -22,10 +22,7 @@ import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import forge.card.MagicColor;
|
||||
import forge.card.mana.ManaCostParser;
|
||||
import forge.game.ability.AbilityFactory;
|
||||
import forge.game.ability.AbilityFactory.AbilityRecordType;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.card.*;
|
||||
@@ -40,7 +37,6 @@ import forge.util.TextUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
@@ -52,59 +48,11 @@ import java.util.Map;
|
||||
* @version $Id$
|
||||
*/
|
||||
public final class GameActionUtil {
|
||||
// Cache these instead of generating them on the fly, to avoid excessive allocations every time
|
||||
// static abilities are checked.
|
||||
@SuppressWarnings("unchecked")
|
||||
private static final Map<String, String>[] BASIC_LAND_ABILITIES_PARAMS = new Map[MagicColor.WUBRG.length];
|
||||
private static final AbilityRecordType[] BASIC_LAND_ABILITIES_TYPES = new AbilityRecordType[MagicColor.WUBRG.length];
|
||||
static {
|
||||
for (int i = 0; i < MagicColor.WUBRG.length; i++ ) {
|
||||
String color = MagicColor.toShortString(MagicColor.WUBRG[i]);
|
||||
String abString = "AB$ Mana | Cost$ T | Produced$ " + color +
|
||||
" | SpellDescription$ Add {" + color + "}.";
|
||||
Map<String, String> mapParams = AbilityFactory.getMapParams(abString);
|
||||
BASIC_LAND_ABILITIES_PARAMS[i] = mapParams;
|
||||
BASIC_LAND_ABILITIES_TYPES[i] = AbilityRecordType.getRecordType(mapParams);
|
||||
}
|
||||
}
|
||||
|
||||
private GameActionUtil() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the st land mana abilities.
|
||||
* @param game
|
||||
*
|
||||
* @return the stLandManaAbilities
|
||||
*/
|
||||
public static void grantBasicLandsManaAbilities(List<Card> lands) {
|
||||
// remove all abilities granted by this Command
|
||||
for (final Card land : lands) {
|
||||
List<SpellAbility> origManaAbs = Lists.newArrayList(land.getManaAbilities());
|
||||
// will get comodification exception without a different list
|
||||
for (final SpellAbility sa : origManaAbs) {
|
||||
if (sa.isBasicLandAbility()) {
|
||||
land.getCurrentState().removeManaAbility(sa);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add all appropriate mana abilities based on current types
|
||||
for (int i = 0; i < MagicColor.WUBRG.length; i++ ) {
|
||||
String landType = MagicColor.Constant.BASIC_LANDS.get(i);
|
||||
Map<String, String> mapParams = BASIC_LAND_ABILITIES_PARAMS[i];
|
||||
AbilityRecordType type = BASIC_LAND_ABILITIES_TYPES[i];
|
||||
for (final Card land : lands) {
|
||||
if (land.getType().hasSubtype(landType)) {
|
||||
final SpellAbility sa = AbilityFactory.getAbility(mapParams, type, land, null);
|
||||
sa.setBasicLandAbility(true);
|
||||
land.getCurrentState().addManaAbility(sa);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // stLandManaAbilities
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Find the alternative costs to a {@link SpellAbility}.
|
||||
|
||||
@@ -254,6 +254,8 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
|
||||
private Table<Card, CounterType, Integer> etbCounters = HashBasedTable.create();
|
||||
|
||||
private SpellAbility[] basicLandAbilities = new SpellAbility[MagicColor.WUBRG.length];
|
||||
|
||||
// Enumeration for CMC request types
|
||||
public enum SplitCMCMode {
|
||||
CurrentSideCMC,
|
||||
@@ -2168,6 +2170,11 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
}
|
||||
|
||||
public void updateSpellAbilities(List<SpellAbility> list, CardState state, Boolean mana) {
|
||||
// do Basic Land Abilities there
|
||||
if (mana == null || mana == true) {
|
||||
updateBasicLandAbilities(list, state);
|
||||
}
|
||||
|
||||
for (KeywordInterface kw : getUnhiddenKeywords(state)) {
|
||||
for (SpellAbility sa : kw.getAbilities()) {
|
||||
if (mana == null || mana == sa.isManaAbility()) {
|
||||
@@ -2177,6 +2184,30 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateBasicLandAbilities(List<SpellAbility> list, CardState state) {
|
||||
final CardTypeView type = state.getTypeWithChanges();
|
||||
|
||||
if (!type.isLand()) {
|
||||
// no land, do nothing there
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < MagicColor.WUBRG.length; i++ ) {
|
||||
byte c = MagicColor.WUBRG[i];
|
||||
if (type.hasSubtype(MagicColor.Constant.BASIC_LANDS.get(i))) {
|
||||
SpellAbility sa = basicLandAbilities[i];
|
||||
|
||||
// no Ability for this type yet, make a new one
|
||||
if (sa == null) {
|
||||
sa = CardFactoryUtil.buildBasicLandAbility(state, c);
|
||||
basicLandAbilities[i] = sa;
|
||||
}
|
||||
|
||||
list.add(sa);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final FCollectionView<SpellAbility> getIntrinsicSpellAbilities() {
|
||||
return currentState.getIntrinsicSpellAbilities();
|
||||
}
|
||||
@@ -2785,20 +2816,9 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
}
|
||||
|
||||
public final void removeChangedCardTypes(final long timestamp, final boolean updateView) {
|
||||
CardChangedType changed = changedCardTypes.remove(timestamp);
|
||||
if (updateView) {
|
||||
if (changedCardTypes.remove(timestamp) != null && updateView) {
|
||||
currentState.getView().updateType(currentState);
|
||||
}
|
||||
|
||||
// if it stops being a land, the abilities does need to be removed
|
||||
if (changed != null && changed.getAddType() != null && changed.getAddType().isLand()) {
|
||||
for (final String s : changed.getAddType().getSubtypes()) {
|
||||
if(CardType.isABasicLandType(s)) {
|
||||
GameActionUtil.grantBasicLandsManaAbilities(ImmutableList.of(this));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final void addColor(final String s, final boolean addToColors, final long timestamp) {
|
||||
|
||||
@@ -73,6 +73,15 @@ import java.util.Map.Entry;
|
||||
*/
|
||||
public class CardFactoryUtil {
|
||||
|
||||
public static SpellAbility buildBasicLandAbility(final CardState state, byte color) {
|
||||
String strcolor = MagicColor.toShortString(color);
|
||||
String abString = "AB$ Mana | Cost$ T | Produced$ " + strcolor +
|
||||
" | SpellDescription$ Add {" + strcolor + "}.";
|
||||
SpellAbility sa = AbilityFactory.getAbility(abString, state);
|
||||
sa.setIntrinsic(true); // always intristic
|
||||
return sa;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* abilityMorphDown.
|
||||
|
||||
@@ -80,8 +80,6 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
private Player deltrigActivatingPlayer = null; // used by delayed triggers to ensure the original activator can be restored
|
||||
private Player targetingPlayer = null;
|
||||
|
||||
private boolean basicLandAbility; // granted by basic land type
|
||||
|
||||
private Card grantorCard = null; // card which grants the ability (equipment or owner of static ability that gave this one)
|
||||
private SpellAbility mayPlayOriginal = null;
|
||||
|
||||
@@ -1202,14 +1200,6 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
return cm != null && cm.getAmountOfX() > 0;
|
||||
}
|
||||
|
||||
public boolean isBasicLandAbility() {
|
||||
return basicLandAbility;
|
||||
}
|
||||
|
||||
public void setBasicLandAbility(boolean basicLandAbility0) {
|
||||
basicLandAbility = basicLandAbility0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeTargetedBy(SpellAbility sa) {
|
||||
return sa.canTargetSpellAbility(this);
|
||||
|
||||
@@ -769,8 +769,6 @@ public final class StaticAbilityContinuous {
|
||||
Player mayPlayController = params.containsKey("MayPlayCardOwner") ? affectedCard.getOwner() : controller;
|
||||
affectedCard.setMayPlay(mayPlayController, mayPlayWithoutManaCost, mayPlayAltManaCost, mayPlayWithFlash, mayPlayGrantZonePermissions, stAb);
|
||||
}
|
||||
|
||||
affectedCard.updateAbilityTextForView(); // only update keywords and text for view to avoid flickering
|
||||
}
|
||||
|
||||
return affectedCards;
|
||||
|
||||
Reference in New Issue
Block a user