Card: move Abilities to Card and only create them once

This commit is contained in:
Hanmac
2018-05-16 21:32:41 +02:00
parent 3505047c9b
commit c1da970c47
7 changed files with 46 additions and 82 deletions

View File

@@ -608,7 +608,6 @@ public class ComputerUtilCost {
Set<String> colorsAvailable = Sets.newHashSet();
if (additionalLands != null) {
GameActionUtil.grantBasicLandsManaAbilities(additionalLands);
cardsToConsider.addAll(additionalLands);
}

View File

@@ -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()) {

View File

@@ -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}.

View File

@@ -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) {

View File

@@ -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.

View File

@@ -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);

View File

@@ -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;