mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-11 16:26:22 +00:00
Compare commits
2 Commits
52b21fa72f
...
linkedAbil
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fef579b9f2 | ||
|
|
eba393fc03 |
@@ -4,9 +4,11 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import forge.card.CardStateName;
|
||||
@@ -35,6 +37,8 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView,
|
||||
protected Card hostCard;
|
||||
protected CardState cardState = null;
|
||||
|
||||
protected List<StaticLayerInterface> grantedByStatic = Lists.newArrayList();
|
||||
|
||||
/** The map params. */
|
||||
protected Map<String, String> originalMapParams = Maps.newHashMap(),
|
||||
mapParams = Maps.newHashMap();
|
||||
@@ -589,6 +593,31 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView,
|
||||
return null;
|
||||
}
|
||||
|
||||
public Card getOriginalOrHost() {
|
||||
return ObjectUtils.defaultIfNull(getOriginalHost(), getHostCard());
|
||||
}
|
||||
|
||||
public List<StaticLayerInterface> getGrantedByStatic() {
|
||||
return grantedByStatic;
|
||||
}
|
||||
|
||||
public void setGrantedByStatic(List<StaticLayerInterface> list) {
|
||||
this.grantedByStatic = Lists.newArrayList(list);
|
||||
}
|
||||
|
||||
public void addGrantedByStatic(final StaticLayerInterface stAb) {
|
||||
grantedByStatic.add(stAb);
|
||||
}
|
||||
|
||||
// TODO currently Clone effects doesn't set Grantor like giving Abilities does
|
||||
// if it would, then this needs to be refactored anyway
|
||||
public Card getFirstGrantor() {
|
||||
if (grantedByStatic.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return grantedByStatic.get(0).getHostCard();
|
||||
}
|
||||
|
||||
public boolean isCopiedTrait() {
|
||||
if (this.getCardState() == null) {
|
||||
return false;
|
||||
@@ -650,7 +679,8 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView,
|
||||
copy.mapParams = Maps.newHashMap(originalMapParams);
|
||||
copy.setSVars(sVars);
|
||||
copy.setCardState(cardState);
|
||||
// dont use setHostCard to not trigger the not copied parts yet
|
||||
copy.setGrantedByStatic(grantedByStatic);
|
||||
// don't use setHostCard to not trigger the not copied parts yet
|
||||
copy.hostCard = host;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package forge.game;
|
||||
|
||||
import forge.game.card.Card;
|
||||
|
||||
public interface StaticLayerInterface {
|
||||
|
||||
public Card getHostCard();
|
||||
}
|
||||
@@ -105,9 +105,9 @@ public class AbilityUtils {
|
||||
}
|
||||
else if (defined.equals("OriginalHost")) {
|
||||
if (sa instanceof SpellAbility) {
|
||||
c = ((SpellAbility)sa).getRootAbility().getOriginalHost();
|
||||
c = ((SpellAbility)sa).getRootAbility().getFirstGrantor();
|
||||
} else {
|
||||
c = sa.getOriginalHost();
|
||||
c = sa.getFirstGrantor();
|
||||
}
|
||||
}
|
||||
else if (defined.equals("EffectSource")) {
|
||||
@@ -539,7 +539,7 @@ public class AbilityUtils {
|
||||
val = 0;
|
||||
}
|
||||
} else if (calcX[0].equals("OriginalHost")) {
|
||||
val = xCount(ability.getOriginalHost(), calcX[1], ability);
|
||||
val = xCount(ability.getFirstGrantor(), calcX[1], ability);
|
||||
} else if (calcX[0].startsWith("Remembered")) {
|
||||
// Add whole Remembered list to handlePaid
|
||||
final CardCollection list = new CardCollection();
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
package forge.game.card;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.collect.ForwardingTable;
|
||||
import com.google.common.collect.HashBasedTable;
|
||||
import com.google.common.collect.Table;
|
||||
|
||||
import forge.game.StaticLayerInterface;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.staticability.StaticAbility;
|
||||
|
||||
public class ActivationTable extends ForwardingTable<SpellAbility, Optional<StaticAbility>, Integer> {
|
||||
Table<SpellAbility, Optional<StaticAbility>, Integer> dataTable = HashBasedTable.create();
|
||||
public class ActivationTable extends ForwardingTable<SpellAbility, List<StaticLayerInterface>, Integer> {
|
||||
Table<SpellAbility, List<StaticLayerInterface>, Integer> dataTable = HashBasedTable.create();
|
||||
|
||||
@Override
|
||||
protected Table<SpellAbility, Optional<StaticAbility>, Integer> delegate() {
|
||||
protected Table<SpellAbility, List<StaticLayerInterface>, Integer> delegate() {
|
||||
return dataTable;
|
||||
}
|
||||
|
||||
@@ -36,7 +37,7 @@ public class ActivationTable extends ForwardingTable<SpellAbility, Optional<Stat
|
||||
SpellAbility original = getOriginal(sa);
|
||||
|
||||
if (original != null) {
|
||||
Optional<StaticAbility> st = Optional.fromNullable(root.getGrantorStatic());
|
||||
List<StaticLayerInterface> st = root.getGrantedByStatic();
|
||||
|
||||
delegate().put(original, st, ObjectUtils.defaultIfNull(get(original, st), 0) + 1);
|
||||
}
|
||||
@@ -45,7 +46,7 @@ public class ActivationTable extends ForwardingTable<SpellAbility, Optional<Stat
|
||||
public Integer get(SpellAbility sa) {
|
||||
SpellAbility root = sa.getRootAbility();
|
||||
SpellAbility original = getOriginal(sa);
|
||||
Optional<StaticAbility> st = Optional.fromNullable(root.getGrantorStatic());
|
||||
List<StaticLayerInterface> st = root.getGrantedByStatic();
|
||||
|
||||
if (contains(original, st)) {
|
||||
return get(original, st);
|
||||
|
||||
@@ -36,6 +36,7 @@ import forge.game.GameEntityCounterTable;
|
||||
import forge.game.GameStage;
|
||||
import forge.game.GlobalRuleChange;
|
||||
import forge.game.IHasSVars;
|
||||
import forge.game.StaticLayerInterface;
|
||||
import forge.game.ability.AbilityFactory;
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
@@ -74,6 +75,7 @@ import forge.util.collect.FCollection;
|
||||
import forge.util.collect.FCollectionView;
|
||||
import io.sentry.Breadcrumb;
|
||||
import io.sentry.Sentry;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.mutable.MutableBoolean;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
@@ -149,11 +151,13 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
private final Table<Long, Long, CardTraitChanges> changedCardTraits = TreeBasedTable.create(); // Layer 6
|
||||
|
||||
// stores the card traits created by static abilities
|
||||
private final Table<StaticAbility, String, SpellAbility> storedSpellAbilility = TreeBasedTable.create();
|
||||
private final Table<StaticAbility, String, SpellAbility> storedSpellAbility = TreeBasedTable.create();
|
||||
private final Table<StaticAbility, String, Trigger> storedTrigger = TreeBasedTable.create();
|
||||
private final Table<StaticAbility, String, ReplacementEffect> storedReplacementEffect = TreeBasedTable.create();
|
||||
private final Table<StaticAbility, String, StaticAbility> storedStaticAbility = TreeBasedTable.create();
|
||||
|
||||
private final Table<StaticLayerInterface, SpellAbility, SpellAbility> copiedSpellAbility = HashBasedTable.create();
|
||||
|
||||
// x=timestamp y=StaticAbility id
|
||||
private final Table<Long, Long, CardColor> changedCardColorsByText = TreeBasedTable.create(); // Layer 3 by Text Change
|
||||
private final Table<Long, Long, CardColor> changedCardColorsCharacterDefining = TreeBasedTable.create(); // Layer 5 CDA
|
||||
@@ -329,11 +333,8 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
private final ActivationTable numberGameActivations = new ActivationTable();
|
||||
private final ActivationTable numberAbilityResolved = new ActivationTable();
|
||||
|
||||
private final Map<SpellAbility, List<String>> chosenModesTurn = Maps.newHashMap();
|
||||
private final Map<SpellAbility, List<String>> chosenModesGame = Maps.newHashMap();
|
||||
|
||||
private final Table<SpellAbility, StaticAbility, List<String>> chosenModesTurnStatic = HashBasedTable.create();
|
||||
private final Table<SpellAbility, StaticAbility, List<String>> chosenModesGameStatic = HashBasedTable.create();
|
||||
private final LinkedAbilityTable<String> chosenModesTurn = new LinkedAbilityTable<String>();
|
||||
private final LinkedAbilityTable<String> chosenModesGame = new LinkedAbilityTable<String>();
|
||||
|
||||
private CombatLki combatLKI;
|
||||
|
||||
@@ -4254,12 +4255,12 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
}
|
||||
|
||||
public final SpellAbility getSpellAbilityForStaticAbility(final String str, final StaticAbility stAb) {
|
||||
SpellAbility result = storedSpellAbilility.get(stAb, str);
|
||||
SpellAbility result = storedSpellAbility.get(stAb, str);
|
||||
if (result == null) {
|
||||
result = AbilityFactory.getAbility(str, this, stAb);
|
||||
result.setIntrinsic(false);
|
||||
result.setGrantorStatic(stAb);
|
||||
storedSpellAbilility.put(stAb, str, result);
|
||||
result.addGrantedByStatic(stAb);
|
||||
storedSpellAbility.put(stAb, str, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -4268,6 +4269,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
Trigger result = storedTrigger.get(stAb, str);
|
||||
if (result == null) {
|
||||
result = TriggerHandler.parseTrigger(str, this, false, stAb);
|
||||
result.addGrantedByStatic(stAb);
|
||||
storedTrigger.put(stAb, str, result);
|
||||
}
|
||||
return result;
|
||||
@@ -4278,6 +4280,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
ReplacementEffect result = storedReplacementEffect.get(stAb, str);
|
||||
if (result == null) {
|
||||
result = ReplacementHandler.parseReplacement(str, this, false, stAb);
|
||||
result.addGrantedByStatic(stAb);
|
||||
storedReplacementEffect.put(stAb, str, result);
|
||||
}
|
||||
return result;
|
||||
@@ -4287,11 +4290,28 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
StaticAbility result = storedStaticAbility.get(stAb, str);
|
||||
if (result == null) {
|
||||
result = StaticAbility.create(str, this, stAb.getCardState(), false);
|
||||
result.addGrantedByStatic(stAb);
|
||||
storedStaticAbility.put(stAb, str, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public final SpellAbility copySpellAbilityForStaticAbility(final SpellAbility sa, final StaticAbility stAb, final boolean intrinsic) {
|
||||
SpellAbility result = copiedSpellAbility.get(stAb, sa);
|
||||
if (result == null) {
|
||||
result = sa.copy(this, false);
|
||||
if (stAb.hasParam("GainsAbilitiesLimitPerTurn")) {
|
||||
result.setRestrictions(sa.getRestrictions());
|
||||
result.getRestrictions().setLimitToCheck(stAb.getParam("GainsAbilitiesLimitPerTurn"));
|
||||
}
|
||||
result.setOriginalAbility(sa.getOriginalAbility()); // need to be set to get the Once Per turn Clause correct
|
||||
result.addGrantedByStatic(stAb);
|
||||
result.setIntrinsic(intrinsic);
|
||||
copiedSpellAbility.put(stAb, sa, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public final void addChangedCardTraits(Collection<SpellAbility> spells, Collection<SpellAbility> removedAbilities,
|
||||
Collection<Trigger> trigger, Collection<ReplacementEffect> replacements, Collection<StaticAbility> statics,
|
||||
boolean removeAll, boolean removeNonMana, long timestamp, long staticId) {
|
||||
@@ -6863,91 +6883,19 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
}
|
||||
|
||||
public List<String> getChosenModesTurn(SpellAbility ability) {
|
||||
SpellAbility original = null;
|
||||
SpellAbility root = ability.getRootAbility();
|
||||
|
||||
// because trigger spell abilities are copied, try to get original one
|
||||
if (root.isTrigger()) {
|
||||
original = root.getTrigger().getOverridingAbility();
|
||||
} else {
|
||||
original = ability.getOriginalAbility();
|
||||
if (original == null) {
|
||||
original = ability;
|
||||
}
|
||||
}
|
||||
|
||||
if (ability.getGrantorStatic() != null) {
|
||||
return chosenModesTurnStatic.get(original, ability.getGrantorStatic());
|
||||
}
|
||||
return chosenModesTurn.get(original);
|
||||
return chosenModesTurn.get(ability);
|
||||
}
|
||||
public List<String> getChosenModesGame(SpellAbility ability) {
|
||||
SpellAbility original = null;
|
||||
SpellAbility root = ability.getRootAbility();
|
||||
|
||||
// because trigger spell abilities are copied, try to get original one
|
||||
if (root.isTrigger()) {
|
||||
original = root.getTrigger().getOverridingAbility();
|
||||
} else {
|
||||
original = ability.getOriginalAbility();
|
||||
if (original == null) {
|
||||
original = ability;
|
||||
}
|
||||
}
|
||||
|
||||
if (ability.getGrantorStatic() != null) {
|
||||
return chosenModesGameStatic.get(original, ability.getGrantorStatic());
|
||||
}
|
||||
return chosenModesGame.get(original);
|
||||
return chosenModesGame.get(ability);
|
||||
}
|
||||
|
||||
public void addChosenModes(SpellAbility ability, String mode) {
|
||||
SpellAbility original = null;
|
||||
SpellAbility root = ability.getRootAbility();
|
||||
|
||||
// because trigger spell abilities are copied, try to get original one
|
||||
if (root.isTrigger()) {
|
||||
original = root.getTrigger().getOverridingAbility();
|
||||
} else {
|
||||
original = ability.getOriginalAbility();
|
||||
if (original == null) {
|
||||
original = ability;
|
||||
}
|
||||
}
|
||||
|
||||
if (ability.getGrantorStatic() != null) {
|
||||
List<String> result = chosenModesTurnStatic.get(original, ability.getGrantorStatic());
|
||||
if (result == null) {
|
||||
result = Lists.newArrayList();
|
||||
chosenModesTurnStatic.put(original, ability.getGrantorStatic(), result);
|
||||
}
|
||||
result.add(mode);
|
||||
result = chosenModesGameStatic.get(original, ability.getGrantorStatic());
|
||||
if (result == null) {
|
||||
result = Lists.newArrayList();
|
||||
chosenModesGameStatic.put(original, ability.getGrantorStatic(), result);
|
||||
}
|
||||
result.add(mode);
|
||||
} else {
|
||||
List<String> result = chosenModesTurn.get(original);
|
||||
if (result == null) {
|
||||
result = Lists.newArrayList();
|
||||
chosenModesTurn.put(original, result);
|
||||
}
|
||||
result.add(mode);
|
||||
|
||||
result = chosenModesGame.get(original);
|
||||
if (result == null) {
|
||||
result = Lists.newArrayList();
|
||||
chosenModesGame.put(original, result);
|
||||
}
|
||||
result.add(mode);
|
||||
}
|
||||
this.chosenModesTurn.put(mode, ability);
|
||||
this.chosenModesGame.put(mode, ability);
|
||||
}
|
||||
|
||||
public void resetChosenModeTurn() {
|
||||
chosenModesTurn.clear();
|
||||
chosenModesTurnStatic.clear();
|
||||
}
|
||||
|
||||
public int getPlaneswalkerAbilityActivated() {
|
||||
|
||||
111
forge-game/src/main/java/forge/game/card/LinkedAbilityTable.java
Normal file
111
forge-game/src/main/java/forge/game/card/LinkedAbilityTable.java
Normal file
@@ -0,0 +1,111 @@
|
||||
package forge.game.card;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
|
||||
import com.google.common.collect.ForwardingTable;
|
||||
import com.google.common.collect.HashBasedTable;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Table;
|
||||
|
||||
import forge.game.CardTraitBase;
|
||||
import forge.game.StaticLayerInterface;
|
||||
import forge.util.collect.FCollection;
|
||||
|
||||
public class LinkedAbilityTable<T> extends ForwardingTable<Card, List<StaticLayerInterface>, FCollection<T>> {
|
||||
private Table<Card, List<StaticLayerInterface>, FCollection<T>> dataTable = HashBasedTable.create();
|
||||
|
||||
@Override
|
||||
protected Table<Card, List<StaticLayerInterface>, FCollection<T>> delegate() {
|
||||
return dataTable;
|
||||
}
|
||||
|
||||
protected FCollection<T> getSupplier() {
|
||||
return new FCollection<T>();
|
||||
}
|
||||
|
||||
protected FCollection<T> putInternal(T object, Card host, List<StaticLayerInterface> st) {
|
||||
host = ObjectUtils.defaultIfNull(host.getEffectSource(), host);
|
||||
FCollection<T> old;
|
||||
if (contains(host, st)) {
|
||||
old = get(host, st);
|
||||
} else {
|
||||
old = getSupplier();
|
||||
delegate().put(host, st, old);
|
||||
}
|
||||
old.add(object);
|
||||
return old;
|
||||
}
|
||||
/*
|
||||
public FCollection<T> put(T object, Card host) {
|
||||
return putInternal(object, host, null);
|
||||
}
|
||||
//*/
|
||||
public FCollection<T> put(T object, CardTraitBase ctb) {
|
||||
return putInternal(object, ctb.getOriginalOrHost(), ctb.getGrantedByStatic());
|
||||
}
|
||||
|
||||
protected void setInternal(Iterable<T> list, Card host, List<StaticLayerInterface> st) {
|
||||
host = ObjectUtils.defaultIfNull(host.getEffectSource(), host);
|
||||
if (list == null || Iterables.isEmpty(list)) {
|
||||
delegate().remove(host, st);
|
||||
} else {
|
||||
FCollection<T> old = getSupplier();
|
||||
old.addAll(list);
|
||||
delegate().put(host, st, old);
|
||||
}
|
||||
}
|
||||
|
||||
public void set(Iterable<T> list, CardTraitBase ctb) {
|
||||
setInternal(list, ctb.getOriginalOrHost(), ctb.getGrantedByStatic());
|
||||
}
|
||||
|
||||
public FCollection<T> get(CardTraitBase ctb) {
|
||||
Card host = ctb.getOriginalOrHost();
|
||||
host = ObjectUtils.defaultIfNull(host.getEffectSource(), host);
|
||||
List<StaticLayerInterface> st = ctb.getGrantedByStatic();
|
||||
if (contains(host, st)) {
|
||||
return get(host, st);
|
||||
} else {
|
||||
return FCollection.<T>getEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public FCollection<T> get(Card host) {
|
||||
if (contains(host, Lists.newArrayList())) {
|
||||
return get(host, Lists.newArrayList());
|
||||
} else {
|
||||
return FCollection.<T>getEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean contains(T object, CardTraitBase ctb) {
|
||||
return get(ctb).contains(object);
|
||||
}
|
||||
|
||||
public boolean remove(T value) {
|
||||
boolean changed = false;
|
||||
for (FCollection<T> col : delegate().values()) {
|
||||
if (col.remove(value)) {
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
public boolean hasOtherLinkedValues(Card host) {
|
||||
for (List<StaticLayerInterface> o : this.columnKeySet()) {
|
||||
if (!o.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (Card ctbHost : this.rowKeySet()) {
|
||||
if (!host.equals(ctbHost)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package forge.game.card.token;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
@@ -273,7 +272,7 @@ public class TokenInfo {
|
||||
final Card host = sa.getHostCard();
|
||||
final Game game = host.getGame();
|
||||
|
||||
String edition = ObjectUtils.firstNonNull(sa.getOriginalHost(), host).getSetCode();
|
||||
String edition = sa.getOriginalOrHost().getSetCode();
|
||||
PaperToken token = StaticData.instance().getAllTokens().getToken(script, edition);
|
||||
|
||||
if (token == null) {
|
||||
|
||||
@@ -81,7 +81,7 @@ public class CostRemoveCounter extends CostPart {
|
||||
} else {
|
||||
List<Card> typeList;
|
||||
if (type.equals("OriginalHost")) {
|
||||
typeList = Lists.newArrayList(ability.getOriginalHost());
|
||||
typeList = Lists.newArrayList(ability.getFirstGrantor());
|
||||
} else {
|
||||
typeList = CardLists.getValidCards(payer.getCardsIn(this.zone), type.split(";"), payer, source, ability);
|
||||
}
|
||||
@@ -155,7 +155,7 @@ public class CostRemoveCounter extends CostPart {
|
||||
else {
|
||||
List<Card> typeList;
|
||||
if (type.equals("OriginalHost")) {
|
||||
typeList = Lists.newArrayList(ability.getOriginalHost());
|
||||
typeList = Lists.newArrayList(ability.getFirstGrantor());
|
||||
} else {
|
||||
typeList = CardLists.getValidCards(payer.getCardsIn(this.zone), type.split(";"), payer, source, ability);
|
||||
}
|
||||
|
||||
@@ -113,7 +113,10 @@ public class CostSacrifice extends CostPartWithList {
|
||||
final Card source = ability.getHostCard();
|
||||
|
||||
if (getType().equals("OriginalHost")) {
|
||||
Card originalEquipment = ability.getOriginalHost();
|
||||
Card originalEquipment = ability.getFirstGrantor();
|
||||
if (!originalEquipment.getController().equals(activator)) {
|
||||
return false;
|
||||
}
|
||||
return originalEquipment.isEquipping() && originalEquipment.canBeSacrificedBy(ability, effect);
|
||||
}
|
||||
else if (!payCostFromSource()) { // You can always sac all
|
||||
@@ -131,7 +134,7 @@ public class CostSacrifice extends CostPartWithList {
|
||||
// if X is defined, it needs to be calculated and checked, if X is
|
||||
// choice, it can be Paid even if it's 0
|
||||
}
|
||||
else return source.canBeSacrificedBy(ability, effect);
|
||||
else return source.getController().equals(activator) && source.canBeSacrificedBy(ability, effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -76,7 +76,7 @@ public class CostUnattach extends CostPartWithList {
|
||||
if (type.equals("CARDNAME")) {
|
||||
return source.isEquipping();
|
||||
} else if (type.equals("OriginalHost")) {
|
||||
Card originalEquipment = ability.getOriginalHost();
|
||||
Card originalEquipment = ability.getFirstGrantor();
|
||||
return originalEquipment.isEquipping();
|
||||
} else {
|
||||
return CardLists.getValidCards(source.getEquippedBy(), type, payer, source, ability).size() > 0;
|
||||
@@ -89,7 +89,7 @@ public class CostUnattach extends CostPartWithList {
|
||||
return source;
|
||||
}
|
||||
} else if (getType().equals("OriginalHost")) {
|
||||
Card originalEquipment = ability.getOriginalHost();
|
||||
Card originalEquipment = ability.getFirstGrantor();
|
||||
if (originalEquipment.isEquipping()) {
|
||||
return originalEquipment;
|
||||
}
|
||||
|
||||
@@ -920,8 +920,8 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
desc = CardTranslation.translateMultipleDescriptionText(desc, currentName);
|
||||
desc = TextUtil.fastReplace(desc, "CARDNAME", CardTranslation.getTranslatedName(currentName));
|
||||
desc = TextUtil.fastReplace(desc, "NICKNAME", Lang.getInstance().getNickName(CardTranslation.getTranslatedName(currentName)));
|
||||
if (node.getOriginalHost() != null) {
|
||||
desc = TextUtil.fastReplace(desc, "ORIGINALHOST", node.getOriginalHost().getName());
|
||||
if (node.getFirstGrantor() != null) {
|
||||
desc = TextUtil.fastReplace(desc, "ORIGINALHOST", node.getFirstGrantor().getName());
|
||||
}
|
||||
sb.append(desc);
|
||||
}
|
||||
@@ -2354,7 +2354,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
}
|
||||
|
||||
public SpellAbility getOriginalAbility() {
|
||||
return grantorOriginal;
|
||||
return ObjectUtils.defaultIfNull(grantorOriginal, this);
|
||||
}
|
||||
public void setOriginalAbility(final SpellAbility sa) {
|
||||
grantorOriginal = sa;
|
||||
|
||||
@@ -31,6 +31,7 @@ import forge.game.Game;
|
||||
import forge.game.GameEntity;
|
||||
import forge.game.GameStage;
|
||||
import forge.game.IIdentifiable;
|
||||
import forge.game.StaticLayerInterface;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
@@ -51,7 +52,7 @@ import forge.util.TextUtil;
|
||||
/**
|
||||
* The Class StaticAbility.
|
||||
*/
|
||||
public class StaticAbility extends CardTraitBase implements IIdentifiable, Cloneable, Comparable<StaticAbility> {
|
||||
public class StaticAbility extends CardTraitBase implements IIdentifiable, Cloneable, Comparable<StaticAbility>, StaticLayerInterface {
|
||||
private static int maxId = 0;
|
||||
private static int nextId() { return ++maxId; }
|
||||
|
||||
|
||||
@@ -615,9 +615,7 @@ public final class StaticAbilityContinuous {
|
||||
List<KeywordInterface> keywords = Lists.newArrayList();
|
||||
|
||||
for (SpellAbility sa : state.getSpellAbilities()) {
|
||||
SpellAbility newSA = sa.copy(affectedCard, false);
|
||||
newSA.setOriginalAbility(sa); // need to be set to get the Once Per turn Clause correct
|
||||
newSA.setGrantorStatic(stAb);
|
||||
SpellAbility newSA = affectedCard.copySpellAbilityForStaticAbility(sa, stAb, true);
|
||||
//newSA.setIntrinsic(false); needs to be changed by CardTextChanges
|
||||
|
||||
spellAbilities.add(newSA);
|
||||
@@ -626,7 +624,6 @@ public final class StaticAbilityContinuous {
|
||||
for (String ability : params.get("GainTextAbilities").split(" & ")) {
|
||||
final SpellAbility sa = AbilityFactory.getAbility(AbilityUtils.getSVar(stAb, ability), affectedCard, stAb);
|
||||
sa.setIntrinsic(true); // needs to be affected by Text
|
||||
sa.setGrantorStatic(stAb);
|
||||
spellAbilities.add(sa);
|
||||
}
|
||||
}
|
||||
@@ -835,15 +832,7 @@ public final class StaticAbilityContinuous {
|
||||
if (loyaltyAB && !sa.isPwAbility()) {
|
||||
continue;
|
||||
}
|
||||
SpellAbility newSA = sa.copy(affectedCard, false);
|
||||
if (params.containsKey("GainsAbilitiesLimitPerTurn")) {
|
||||
newSA.setRestrictions(sa.getRestrictions());
|
||||
newSA.getRestrictions().setLimitToCheck(params.get("GainsAbilitiesLimitPerTurn"));
|
||||
}
|
||||
newSA.setOriginalAbility(sa); // need to be set to get the Once Per turn Clause correct
|
||||
newSA.setGrantorStatic(stAb);
|
||||
newSA.setIntrinsic(false);
|
||||
addedAbilities.add(newSA);
|
||||
addedAbilities.add(affectedCard.copySpellAbilityForStaticAbility(sa, stAb, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,8 +206,8 @@ public abstract class Trigger extends TriggerReplacementBase {
|
||||
if (!saDesc.startsWith(sa.getHostCard().getName())) {
|
||||
saDesc = saDesc.substring(0, 1).toLowerCase() + saDesc.substring(1);
|
||||
}
|
||||
if (saDesc.contains("ORIGINALHOST") && sa.getOriginalHost() != null) {
|
||||
saDesc = TextUtil.fastReplace(saDesc, "ORIGINALHOST", sa.getOriginalHost().getName());
|
||||
if (saDesc.contains("ORIGINALHOST") && sa.getFirstGrantor() != null) {
|
||||
saDesc = TextUtil.fastReplace(saDesc, "ORIGINALHOST", sa.getFirstGrantor().getName());
|
||||
}
|
||||
} else {
|
||||
saDesc = "<take no action>"; // printed in case nothing is chosen for the ability (e.g. Charm with Up to X)
|
||||
|
||||
@@ -943,7 +943,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
|
||||
return PaymentDecision.card(source, cntRemoved >= 0 ? cntRemoved : maxCounters);
|
||||
|
||||
} else if (type.equals("OriginalHost")) {
|
||||
final int maxCounters = ability.getOriginalHost().getCounters(cost.counter);
|
||||
final int maxCounters = ability.getFirstGrantor().getCounters(cost.counter);
|
||||
if (amount.equals("All")) {
|
||||
cntRemoved = maxCounters;
|
||||
}
|
||||
@@ -951,7 +951,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
|
||||
return null;
|
||||
}
|
||||
|
||||
return PaymentDecision.card(ability.getOriginalHost(), cntRemoved >= 0 ? cntRemoved : maxCounters);
|
||||
return PaymentDecision.card(ability.getFirstGrantor(), cntRemoved >= 0 ? cntRemoved : maxCounters);
|
||||
}
|
||||
|
||||
CardCollectionView validCards = CardLists.getValidCards(player.getCardsIn(cost.zone), type.split(";"), player, source, ability);
|
||||
@@ -994,7 +994,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
|
||||
}
|
||||
|
||||
if (type.equals("OriginalHost")) {
|
||||
Card host = ability.getOriginalHost();
|
||||
Card host = ability.getFirstGrantor();
|
||||
if (host.getController() == ability.getActivatingPlayer() && host.isInPlay()) {
|
||||
return controller.confirmPayment(cost, Localizer.getInstance().getMessage("lblSacrificeCardConfirm", CardTranslation.getTranslatedName(host.getName())), ability) ? PaymentDecision.card(host) : null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user