mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 11:48:02 +00:00
Merge branch 'bloodyCardTraits' into 'master'
CardTaits: make cardtraits inside LKI has the same id's as the in the original See merge request core-developers/forge!197
This commit is contained in:
@@ -233,7 +233,7 @@ public final class GameActionUtil {
|
||||
alternatives.add(newSA);
|
||||
}
|
||||
if (sa.hasParam("Equip") && sa instanceof AbilityActivated && keyword.equals("EquipInstantSpeed")) {
|
||||
final SpellAbility newSA = ((AbilityActivated) sa).getCopy();
|
||||
final SpellAbility newSA = sa.copy();
|
||||
SpellAbilityRestriction sar = newSA.getRestrictions();
|
||||
sar.setSorcerySpeed(false);
|
||||
sar.setInstantSpeed(true);
|
||||
|
||||
@@ -11,7 +11,7 @@ import forge.game.zone.ZoneType;
|
||||
/**
|
||||
* Created by Hellfish on 2014-02-09.
|
||||
*/
|
||||
public abstract class TriggerReplacementBase extends CardTraitBase {
|
||||
public abstract class TriggerReplacementBase extends CardTraitBase implements IIdentifiable, Cloneable {
|
||||
protected EnumSet<ZoneType> validHostZones;
|
||||
|
||||
/** The overriding ability. */
|
||||
|
||||
@@ -5,7 +5,6 @@ import forge.game.ability.effects.ChangeZoneEffect;
|
||||
import forge.game.ability.effects.ManaEffect;
|
||||
import forge.game.ability.effects.ManaReflectedEffect;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardFactory;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.spellability.AbilityActivated;
|
||||
import forge.game.spellability.AbilityManaPart;
|
||||
@@ -41,17 +40,6 @@ public class AbilityApiBased extends AbilityActivated {
|
||||
return effect.getStackDescriptionWithSubs(mapParams, this);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.spellability.AbilityActivated#getCopy()
|
||||
*/
|
||||
@Override
|
||||
public AbilityActivated getCopy() {
|
||||
TargetRestrictions tgt = getTargetRestrictions() == null ? null : new TargetRestrictions(getTargetRestrictions());
|
||||
AbilityActivated res = new AbilityApiBased(api, getHostCard(), getPayCosts(), tgt, mapParams);
|
||||
CardFactory.copySpellAbility(this, res, getHostCard());
|
||||
return res;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.spellability.SpellAbility#resolve()
|
||||
*/
|
||||
|
||||
@@ -195,7 +195,7 @@ public class CharmEffect extends SpellAbilityEffect {
|
||||
|
||||
for (AbilitySub sub : chosen) {
|
||||
// Clone the chosen, just in case the some subAb gets chosen multiple times
|
||||
AbilitySub clone = (AbilitySub)sub.getCopy();
|
||||
AbilitySub clone = (AbilitySub)sub.copy();
|
||||
|
||||
// update ActivatingPlayer
|
||||
clone.setActivatingPlayer(sa.getActivatingPlayer());
|
||||
|
||||
@@ -141,6 +141,10 @@ public class PumpEffect extends SpellAbilityEffect {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see forge.game.ability.SpellAbilityEffect#getStackDescription(forge.game.spellability.SpellAbility)
|
||||
*/
|
||||
@Override
|
||||
protected String getStackDescription(final SpellAbility sa) {
|
||||
|
||||
|
||||
@@ -822,17 +822,18 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
public final FCollectionView<Trigger> getTriggers() {
|
||||
return currentState.getTriggers();
|
||||
}
|
||||
// only used for LKI
|
||||
public final void setTriggers(final Iterable<Trigger> trigs, boolean intrinsicOnly) {
|
||||
final FCollection<Trigger> copyList = new FCollection<>();
|
||||
for (final Trigger t : trigs) {
|
||||
if (!intrinsicOnly || t.isIntrinsic()) {
|
||||
copyList.add(t.getCopyForHostCard(this));
|
||||
copyList.add(t.copy(this, true));
|
||||
}
|
||||
}
|
||||
currentState.setTriggers(copyList);
|
||||
}
|
||||
public final Trigger addTrigger(final Trigger t) {
|
||||
final Trigger newtrig = t.getCopyForHostCard(this);
|
||||
final Trigger newtrig = t.copy(this, false);
|
||||
currentState.addTrigger(newtrig);
|
||||
return newtrig;
|
||||
}
|
||||
@@ -5171,16 +5172,14 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
currentState.clearReplacementEffects();
|
||||
for (final ReplacementEffect replacementEffect : res) {
|
||||
if (replacementEffect.isIntrinsic()) {
|
||||
addReplacementEffect(replacementEffect);
|
||||
addReplacementEffect(replacementEffect.copy(this, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ReplacementEffect addReplacementEffect(final ReplacementEffect replacementEffect) {
|
||||
final ReplacementEffect replacementEffectCopy = replacementEffect.getCopy(); // doubtful - every caller provides a newly parsed instance, why copy?
|
||||
replacementEffectCopy.setHostCard(this);
|
||||
currentState.addReplacementEffect(replacementEffectCopy);
|
||||
return replacementEffectCopy;
|
||||
currentState.addReplacementEffect(replacementEffect);
|
||||
return replacementEffect;
|
||||
}
|
||||
public void removeReplacementEffect(ReplacementEffect replacementEffect) {
|
||||
currentState.removeReplacementEffect(replacementEffect);
|
||||
@@ -5192,6 +5191,17 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasReplacementEffect(final ReplacementEffect re) {
|
||||
return currentState.hasReplacementEffect(re);
|
||||
}
|
||||
public boolean hasReplacementEffect(final int id) {
|
||||
return currentState.hasReplacementEffect(id);
|
||||
}
|
||||
|
||||
public ReplacementEffect getReplacementEffect(final int id) {
|
||||
return currentState.getReplacementEffect(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns what zone this card was cast from (from what zone it was moved to the stack).
|
||||
*/
|
||||
|
||||
@@ -184,21 +184,10 @@ public class CardFactory {
|
||||
c.setCopiedSpell(true);
|
||||
|
||||
final SpellAbility copySA;
|
||||
if (sa instanceof AbilityActivated) {
|
||||
copySA = ((AbilityActivated)sa).getCopy();
|
||||
copySA.setHostCard(original);
|
||||
}
|
||||
else if (sa.isTrigger()) {
|
||||
if (sa.isTrigger()) {
|
||||
copySA = getCopiedTriggeredAbility(sa);
|
||||
}
|
||||
else {
|
||||
copySA = sa.copy();
|
||||
AbilitySub subSA = copySA.getSubAbility();
|
||||
while (subSA != null) {
|
||||
subSA.setCopied(true);
|
||||
subSA = subSA.getSubAbility();
|
||||
}
|
||||
copySA.setHostCard(c);
|
||||
} else {
|
||||
copySA = sa.copy(c, false);
|
||||
}
|
||||
c.getCurrentState().setNonManaAbilities(copySA);
|
||||
copySA.setCopied(true);
|
||||
@@ -577,27 +566,28 @@ public class CardFactory {
|
||||
to.addAlternateState(toState, updateView);
|
||||
}
|
||||
final CardState toCharacteristics = to.getState(toState), fromCharacteristics = from.getState(fromState);
|
||||
toCharacteristics.copyFrom(from, fromCharacteristics);
|
||||
toCharacteristics.copyFrom(fromCharacteristics, false);
|
||||
}
|
||||
|
||||
public static void copySpellAbility(SpellAbility from, SpellAbility to, final Card host) {
|
||||
if (from.getActivatingPlayer() != null) {
|
||||
to.setActivatingPlayer(from.getActivatingPlayer());
|
||||
|
||||
public static void copySpellAbility(SpellAbility from, SpellAbility to, final Card host, final boolean lki) {
|
||||
|
||||
if (from.getTargetRestrictions() != null) {
|
||||
to.setTargetRestrictions(from.getTargetRestrictions());
|
||||
}
|
||||
to.setDescription(from.getOriginalDescription());
|
||||
to.setStackDescription(from.getOriginalStackDescription());
|
||||
|
||||
if (from.getSubAbility() != null) {
|
||||
to.setSubAbility(from.getSubAbility().getCopy(host));
|
||||
to.setSubAbility((AbilitySub) from.getSubAbility().copy(host, lki));
|
||||
}
|
||||
for (Map.Entry<String, AbilitySub> e : from.getAdditionalAbilities().entrySet()) {
|
||||
to.setAdditionalAbility(e.getKey(), e.getValue().getCopy(host));
|
||||
to.setAdditionalAbility(e.getKey(), (AbilitySub) e.getValue().copy(host, lki));
|
||||
}
|
||||
for (Map.Entry<String, List<AbilitySub>> e : from.getAdditionalAbilityLists().entrySet()) {
|
||||
to.setAdditionalAbilityList(e.getKey(), Lists.transform(e.getValue(), new Function<AbilitySub, AbilitySub>() {
|
||||
@Override
|
||||
public AbilitySub apply(AbilitySub input) {
|
||||
return input.getCopy(host);
|
||||
return (AbilitySub) input.copy(host, lki);
|
||||
}
|
||||
}));
|
||||
}
|
||||
@@ -607,7 +597,12 @@ public class CardFactory {
|
||||
if (from.getConditions() != null) {
|
||||
to.setConditions((SpellAbilityCondition) from.getConditions().copy());
|
||||
}
|
||||
|
||||
|
||||
// do this after other abilties are copied
|
||||
if (from.getActivatingPlayer() != null) {
|
||||
to.setActivatingPlayer(from.getActivatingPlayer(), lki);
|
||||
}
|
||||
|
||||
for (String sVar : from.getSVars()) {
|
||||
to.setSVar(sVar, from.getSVar(sVar));
|
||||
}
|
||||
|
||||
@@ -170,10 +170,10 @@ public class CardState extends GameObject {
|
||||
public final boolean hasIntrinsicKeyword(String k) {
|
||||
return intrinsicKeywords.contains(k);
|
||||
}
|
||||
public final void setIntrinsicKeywords(final Iterable<KeywordInterface> intrinsicKeyword0) {
|
||||
public final void setIntrinsicKeywords(final Iterable<KeywordInterface> intrinsicKeyword0, final boolean lki) {
|
||||
intrinsicKeywords.clear();
|
||||
for (KeywordInterface k : intrinsicKeyword0) {
|
||||
intrinsicKeywords.insert(k.copy(card));
|
||||
intrinsicKeywords.insert(k.copy(card, lki));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,6 +367,24 @@ public class CardState extends GameObject {
|
||||
return getReplacementEffects().contains(re);
|
||||
}
|
||||
|
||||
public final boolean hasReplacementEffect(final int id) {
|
||||
for (final ReplacementEffect r : getReplacementEffects()) {
|
||||
if (id == r.getId()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public final ReplacementEffect getReplacementEffect(final int id) {
|
||||
for (final ReplacementEffect r : getReplacementEffects()) {
|
||||
if (id == r.getId()) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public final Map<String, String> getSVars() {
|
||||
return sVars;
|
||||
}
|
||||
@@ -406,7 +424,7 @@ public class CardState extends GameObject {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public final void copyFrom(final Card c, final CardState source) {
|
||||
public final void copyFrom(final CardState source, final boolean lki) {
|
||||
// Makes a "deeper" copy of a CardState object
|
||||
setName(source.getName());
|
||||
setType(source.type);
|
||||
@@ -419,36 +437,30 @@ public class CardState extends GameObject {
|
||||
manaAbilities.clear();
|
||||
for (SpellAbility sa : source.manaAbilities) {
|
||||
if (sa.isIntrinsic()) {
|
||||
SpellAbility saCopy = sa.copy();
|
||||
saCopy.setHostCard(card); // update HostCard
|
||||
manaAbilities.add(saCopy);
|
||||
manaAbilities.add(sa.copy(card, lki));
|
||||
}
|
||||
}
|
||||
|
||||
nonManaAbilities.clear();
|
||||
for (SpellAbility sa : source.nonManaAbilities) {
|
||||
if (sa.isIntrinsic()) {
|
||||
SpellAbility saCopy = sa.copy();
|
||||
saCopy.setHostCard(card); // update HostCard
|
||||
nonManaAbilities.add(saCopy);
|
||||
nonManaAbilities.add(sa.copy(card, lki));
|
||||
}
|
||||
}
|
||||
|
||||
setIntrinsicKeywords(source.intrinsicKeywords.getValues());
|
||||
setIntrinsicKeywords(source.intrinsicKeywords.getValues(), lki);
|
||||
setImageKey(source.getImageKey());
|
||||
setRarity(source.rarity);
|
||||
setSetCode(source.setCode);
|
||||
|
||||
triggers.clear();
|
||||
for (Trigger tr : source.triggers) {
|
||||
triggers.add(tr.getCopyForHostCard(card));
|
||||
triggers.add(tr.copy(card, lki));
|
||||
}
|
||||
|
||||
replacementEffects.clear();
|
||||
for (ReplacementEffect re : source.replacementEffects) {
|
||||
ReplacementEffect reCopy = re.getCopy();
|
||||
reCopy.setHostCard(card);
|
||||
replacementEffects.add(reCopy);
|
||||
replacementEffects.add(re.copy(card, lki));
|
||||
}
|
||||
|
||||
staticAbilities.clear();
|
||||
@@ -456,7 +468,6 @@ public class CardState extends GameObject {
|
||||
StaticAbility saCopy = new StaticAbility(sa, this.card);
|
||||
staticAbilities.add(saCopy);
|
||||
}
|
||||
view.updateKeywords(c, this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -211,19 +211,18 @@ public final class CardUtil {
|
||||
// used for the purpose of cards that care about the zone the card was known to be in last
|
||||
newCopy.setLastKnownZone(in.getLastKnownZone());
|
||||
|
||||
newCopy.getCurrentState().copyFrom(in, in.getState(in.getCurrentStateName()));
|
||||
newCopy.getCurrentState().copyFrom(in.getState(in.getCurrentStateName()), true);
|
||||
|
||||
if (in.isCloned()) {
|
||||
newCopy.addAlternateState(CardStateName.Cloner, false);
|
||||
newCopy.getState(CardStateName.Cloner).copyFrom(in, in.getState(CardStateName.Cloner));
|
||||
newCopy.getState(CardStateName.Cloner).copyFrom(in.getState(CardStateName.Cloner), true);
|
||||
}
|
||||
|
||||
newCopy.setType(new CardType(in.getType()));
|
||||
newCopy.setToken(in.isToken());
|
||||
newCopy.setTriggers(in.getTriggers(), false);
|
||||
for (SpellAbility sa : in.getSpellAbilities()) {
|
||||
newCopy.addSpellAbility(sa);
|
||||
sa.setHostCard(in);
|
||||
newCopy.addSpellAbility(sa.copy(newCopy, true));
|
||||
}
|
||||
|
||||
// lock in the current P/T without bonus from counters
|
||||
@@ -263,6 +262,11 @@ public final class CardUtil {
|
||||
|
||||
newCopy.setMeldedWith(in.getMeldedWith());
|
||||
|
||||
// update keyword cache on all states
|
||||
for (CardStateName s : newCopy.getStates()) {
|
||||
newCopy.updateKeywordsCache(newCopy.getState(s));
|
||||
}
|
||||
|
||||
return newCopy;
|
||||
}
|
||||
|
||||
|
||||
@@ -167,6 +167,17 @@ public class KeywordCollection implements Iterable<String>, Serializable {
|
||||
};
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append(map.values());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public KeywordCollectionView getView() {
|
||||
if (view == null) {
|
||||
view = new KeywordCollectionView();
|
||||
|
||||
@@ -180,26 +180,23 @@ public abstract class KeywordInstance<T extends KeywordInstance<?>> implements K
|
||||
* (non-Javadoc)
|
||||
* @see forge.game.keyword.KeywordInterface#copy()
|
||||
*/
|
||||
public KeywordInterface copy(final Card host) {
|
||||
public KeywordInterface copy(final Card host, final boolean lki) {
|
||||
try {
|
||||
KeywordInstance<?> result = (KeywordInstance<?>) super.clone();
|
||||
|
||||
result.abilities = Lists.newArrayList();
|
||||
for (SpellAbility sa : this.abilities) {
|
||||
SpellAbility saCopy = sa.copy(host);
|
||||
result.abilities.add(saCopy);
|
||||
result.abilities.add(sa.copy(host, lki));
|
||||
}
|
||||
|
||||
result.triggers = Lists.newArrayList();
|
||||
for (Trigger tr : this.triggers) {
|
||||
result.triggers.add(tr.getCopyForHostCard(host));
|
||||
result.triggers.add(tr.copy(host, lki));
|
||||
}
|
||||
|
||||
result.replacements = Lists.newArrayList();
|
||||
for (ReplacementEffect re : this.replacements) {
|
||||
ReplacementEffect reCopy = re.getCopy();
|
||||
reCopy.setHostCard(host);
|
||||
result.replacements.add(reCopy);
|
||||
result.replacements.add(re.copy(host, lki));
|
||||
}
|
||||
|
||||
result.staticAbilities = Lists.newArrayList();
|
||||
@@ -212,4 +209,12 @@ public abstract class KeywordInstance<T extends KeywordInstance<?>> implements K
|
||||
throw new RuntimeException("KeywordInstance : clone() error, " + ex);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getOriginal();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,5 +49,5 @@ public interface KeywordInterface extends Cloneable {
|
||||
*/
|
||||
public Collection<StaticAbility> getStaticAbilities();
|
||||
|
||||
public KeywordInterface copy(final Card host);
|
||||
public KeywordInterface copy(final Card host, final boolean lki);
|
||||
}
|
||||
@@ -1,12 +1,16 @@
|
||||
package forge.game.replacement;
|
||||
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
@@ -32,7 +36,7 @@ public class ReplaceMoved extends ReplacementEffect {
|
||||
return false;
|
||||
}
|
||||
final Player controller = getHostCard().getController();
|
||||
|
||||
|
||||
if (hasParam("ValidCard")) {
|
||||
if (!matchesValid(runParams.get("Affected"), getParam("ValidCard").split(","), getHostCard())) {
|
||||
return false;
|
||||
@@ -44,31 +48,46 @@ public class ReplaceMoved extends ReplacementEffect {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
boolean matchedZone = false;
|
||||
if (hasParam("Origin")) {
|
||||
for(ZoneType z : ZoneType.listValueOf(getParam("Origin"))) {
|
||||
if(z == (ZoneType) runParams.get("Origin"))
|
||||
matchedZone = true;
|
||||
}
|
||||
|
||||
|
||||
if(!matchedZone)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (hasParam("Destination")) {
|
||||
matchedZone = false;
|
||||
ZoneType zt = (ZoneType) runParams.get("Destination");
|
||||
for(ZoneType z : ZoneType.listValueOf(getParam("Destination"))) {
|
||||
if(z == (ZoneType) runParams.get("Destination"))
|
||||
if(z == zt)
|
||||
matchedZone = true;
|
||||
}
|
||||
|
||||
|
||||
if(!matchedZone)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (zt.equals(ZoneType.Battlefield)) {
|
||||
// would be an etb replacement effect that enters the battlefield
|
||||
Card lki = CardUtil.getLKICopy((Card) runParams.get("Affected"));
|
||||
lki.setLastKnownZone(lki.getController().getZone(zt));
|
||||
|
||||
CardCollection preList = new CardCollection(lki);
|
||||
getHostCard().getGame().getAction().checkStaticAbilities(false, Sets.newHashSet(lki), preList);
|
||||
|
||||
// check if when entering the battlefield would still has this RE or is suppressed
|
||||
if (!lki.hasReplacementEffect(this) || lki.getReplacementEffect(getId()).isSuppressed()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasParam("ExcludeDestination")) {
|
||||
|
||||
@@ -19,11 +19,9 @@ package forge.game.replacement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.TriggerReplacementBase;
|
||||
import forge.game.ability.AbilityApiBased;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.util.TextUtil;
|
||||
|
||||
@@ -35,12 +33,37 @@ import java.util.Map;
|
||||
*
|
||||
*/
|
||||
public abstract class ReplacementEffect extends TriggerReplacementBase {
|
||||
private static int maxId = 0;
|
||||
private static int nextId() { return ++maxId; }
|
||||
|
||||
/** The ID. */
|
||||
private int id;
|
||||
|
||||
private ReplacementLayer layer = ReplacementLayer.None;
|
||||
|
||||
/** The has run. */
|
||||
private boolean hasRun = false;
|
||||
|
||||
/**
|
||||
* Gets the id.
|
||||
*
|
||||
* @return the id
|
||||
*/
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* setID.
|
||||
* </p>
|
||||
*
|
||||
* @param id
|
||||
* a int.
|
||||
*/
|
||||
public final void setId(final int id) {
|
||||
this.id = id;
|
||||
}
|
||||
/**
|
||||
* Checks for run.
|
||||
*
|
||||
@@ -59,6 +82,7 @@ public abstract class ReplacementEffect extends TriggerReplacementBase {
|
||||
* the host
|
||||
*/
|
||||
public ReplacementEffect(final Map<String, String> map, final Card host, final boolean intrinsic) {
|
||||
this.id = nextId();
|
||||
this.intrinsic = intrinsic;
|
||||
originalMapParams.putAll(map);
|
||||
mapParams.putAll(map);
|
||||
@@ -133,32 +157,27 @@ public abstract class ReplacementEffect extends TriggerReplacementBase {
|
||||
*
|
||||
* @return the copy
|
||||
*/
|
||||
public final ReplacementEffect getCopy() {
|
||||
final ReplacementType rt = ReplacementType.getTypeFor(this);
|
||||
final ReplacementEffect res = rt.createReplacement(mapParams, hostCard, intrinsic);
|
||||
final SpellAbility overridingAbility = this.getOverridingAbility();
|
||||
if (overridingAbility != null) {
|
||||
final SpellAbility overridingAbilityCopy;
|
||||
if (overridingAbility instanceof AbilityApiBased) {
|
||||
overridingAbilityCopy = ((AbilityApiBased) overridingAbility).getCopy();
|
||||
} else if (overridingAbility instanceof AbilitySub) {
|
||||
overridingAbilityCopy = ((AbilitySub) overridingAbility).getCopy();
|
||||
} else {
|
||||
System.err.println("Overriding ability of " + hostCard + " of unexpected type " + overridingAbility.getClass());
|
||||
overridingAbilityCopy = null;
|
||||
}
|
||||
|
||||
if (overridingAbilityCopy != null) {
|
||||
overridingAbilityCopy.setHostCard(hostCard);
|
||||
res.setOverridingAbility(overridingAbilityCopy);
|
||||
}
|
||||
}
|
||||
res.setActiveZone(validHostZones);
|
||||
res.setLayer(getLayer());
|
||||
res.setTemporary(isTemporary());
|
||||
public final ReplacementEffect copy(final Card host, final boolean lki) {
|
||||
final ReplacementEffect res = (ReplacementEffect) clone();
|
||||
for (String key : getSVars()) {
|
||||
res.setSVar(key, getSVar(key));
|
||||
}
|
||||
|
||||
final SpellAbility sa = this.getOverridingAbility();
|
||||
if (sa != null) {
|
||||
final SpellAbility overridingAbilityCopy = sa.copy(host, lki);
|
||||
if (overridingAbilityCopy != null) {
|
||||
res.setOverridingAbility(overridingAbilityCopy);
|
||||
}
|
||||
}
|
||||
|
||||
if (!lki) {
|
||||
res.setId(nextId());
|
||||
}
|
||||
|
||||
res.setActiveZone(validHostZones);
|
||||
res.setLayer(getLayer());
|
||||
res.setTemporary(isTemporary());
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -206,6 +225,29 @@ public abstract class ReplacementEffect extends TriggerReplacementBase {
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final Object clone() {
|
||||
try {
|
||||
return super.clone();
|
||||
} catch (final Exception ex) {
|
||||
throw new RuntimeException("ReplacementEffect : clone() error, " + ex);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final boolean equals(final Object o) {
|
||||
if (!(o instanceof ReplacementEffect)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.getId() == ((ReplacementEffect) o).getId();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 42 * (42 + this.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,21 +61,12 @@ public class ReplacementHandler {
|
||||
decider = ((Card) affected).getController();
|
||||
}
|
||||
|
||||
ReplacementResult res = run(runParams, ReplacementLayer.Control, decider);
|
||||
if (res != ReplacementResult.NotReplaced) {
|
||||
return res;
|
||||
}
|
||||
res = run(runParams, ReplacementLayer.Copy, decider);
|
||||
if (res != ReplacementResult.NotReplaced) {
|
||||
return res;
|
||||
}
|
||||
res = run(runParams, ReplacementLayer.Other, decider);
|
||||
if (res != ReplacementResult.NotReplaced) {
|
||||
return res;
|
||||
}
|
||||
res = run(runParams, ReplacementLayer.None, decider);
|
||||
if (res != ReplacementResult.NotReplaced) {
|
||||
return res;
|
||||
// try out all layer
|
||||
for (ReplacementLayer layer : ReplacementLayer.values()) {
|
||||
ReplacementResult res = run(runParams, layer, decider);
|
||||
if (res != ReplacementResult.NotReplaced) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return ReplacementResult.NotReplaced;
|
||||
|
||||
@@ -32,16 +32,6 @@ public enum ReplacementType {
|
||||
clasz = cls;
|
||||
}
|
||||
|
||||
public static ReplacementType getTypeFor(ReplacementEffect e) {
|
||||
final Class<? extends ReplacementEffect> cls = e.getClass();
|
||||
for (final ReplacementType v : ReplacementType.values()) {
|
||||
if (v.clasz.equals(cls)) {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ReplacementType smartValueOf(String value) {
|
||||
final String valToCompate = value.trim();
|
||||
for (final ReplacementType v : ReplacementType.values()) {
|
||||
|
||||
@@ -72,10 +72,6 @@ public abstract class AbilityActivated extends SpellAbility implements java.io.S
|
||||
}
|
||||
}
|
||||
|
||||
public abstract AbilityActivated getCopy(); /* {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean canPlay() {
|
||||
|
||||
@@ -25,7 +25,6 @@ import forge.game.ability.effects.ChangeZoneEffect;
|
||||
import forge.game.ability.effects.ManaEffect;
|
||||
import forge.game.ability.effects.ManaReflectedEffect;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardFactory;
|
||||
import forge.game.cost.Cost;
|
||||
|
||||
import java.util.Map;
|
||||
@@ -102,16 +101,6 @@ public final class AbilitySub extends SpellAbility implements java.io.Serializab
|
||||
}
|
||||
}
|
||||
|
||||
public AbilitySub getCopy() {
|
||||
return getCopy(getHostCard());
|
||||
}
|
||||
public AbilitySub getCopy(Card host) {
|
||||
TargetRestrictions t = getTargetRestrictions() == null ? null : new TargetRestrictions(getTargetRestrictions());
|
||||
AbilitySub res = new AbilitySub(api, host, t, mapParams);
|
||||
CardFactory.copySpellAbility(this, res, host);
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStackDescription() {
|
||||
return effect.getStackDescriptionWithSubs(mapParams, this);
|
||||
|
||||
@@ -313,24 +313,25 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
return activatingPlayer;
|
||||
}
|
||||
public void setActivatingPlayer(final Player player) {
|
||||
setActivatingPlayer(player, false);
|
||||
}
|
||||
public void setActivatingPlayer(final Player player, final boolean lki) {
|
||||
// trickle down activating player
|
||||
activatingPlayer = player;
|
||||
if (subAbility != null) {
|
||||
subAbility.setActivatingPlayer(player);
|
||||
subAbility.setActivatingPlayer(player, lki);
|
||||
}
|
||||
for (AbilitySub sa : additionalAbilities.values()) {
|
||||
if (sa.getActivatingPlayer() != player) {
|
||||
sa.setActivatingPlayer(player);
|
||||
}
|
||||
sa.setActivatingPlayer(player, lki);
|
||||
}
|
||||
for (List<AbilitySub> list : additionalAbilityLists.values()) {
|
||||
for (AbilitySub sa : list) {
|
||||
if (sa.getActivatingPlayer() != player) {
|
||||
sa.setActivatingPlayer(player);
|
||||
}
|
||||
sa.setActivatingPlayer(player, lki);
|
||||
}
|
||||
}
|
||||
view.updateCanPlay(this, false);
|
||||
if (!lki) {
|
||||
view.updateCanPlay(this, false);
|
||||
}
|
||||
}
|
||||
|
||||
public Player getDeltrigActivatingPlayer() {
|
||||
@@ -789,17 +790,18 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
}
|
||||
|
||||
public SpellAbility copy() {
|
||||
return copy(hostCard);
|
||||
return copy(hostCard, false);
|
||||
}
|
||||
public SpellAbility copy(Card host) {
|
||||
public SpellAbility copy(Card host, final boolean lki) {
|
||||
SpellAbility clone = null;
|
||||
try {
|
||||
clone = (SpellAbility) clone();
|
||||
clone.id = nextId();
|
||||
clone.id = lki ? id : nextId();
|
||||
clone.view = new SpellAbilityView(clone);
|
||||
|
||||
// dont use setHostCard to not trigger the not copied parts yet
|
||||
clone.hostCard = host;
|
||||
if (host != null && host.getGame() != null) {
|
||||
if (!lki && host != null && host.getGame() != null) {
|
||||
host.getGame().addSpellAbility(clone);
|
||||
}
|
||||
// need to clone the maps too so they can be changed
|
||||
@@ -808,8 +810,11 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
|
||||
clone.triggeringObjects = Maps.newHashMap(this.triggeringObjects);
|
||||
|
||||
if (getPayCosts() != null) {
|
||||
clone.setPayCosts(getPayCosts().copy());
|
||||
}
|
||||
// run special copy Ability to make a deep copy
|
||||
CardFactory.copySpellAbility(this, clone, host);
|
||||
CardFactory.copySpellAbility(this, clone, host, lki);
|
||||
} catch (final CloneNotSupportedException e) {
|
||||
System.err.println(e);
|
||||
}
|
||||
@@ -1109,6 +1114,9 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
}
|
||||
public void setCopied(boolean isCopied0) {
|
||||
isCopied = isCopied0;
|
||||
if (this.getSubAbility() != null) {
|
||||
this.getSubAbility().setCopied(isCopied0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -369,12 +369,12 @@ public final class StaticAbilityContinuous {
|
||||
cardsIGainedAbilitiesFrom = CardLists.getValidCards(cardsIGainedAbilitiesFrom, valids, hostCard.getController(), hostCard, null);
|
||||
|
||||
if (cardsIGainedAbilitiesFrom.size() > 0) {
|
||||
addFullAbs = new ArrayList<SpellAbility>();
|
||||
addFullAbs = Lists.newArrayList();
|
||||
|
||||
for (Card c : cardsIGainedAbilitiesFrom) {
|
||||
for (SpellAbility sa : c.getSpellAbilities()) {
|
||||
if (sa instanceof AbilityActivated) {
|
||||
SpellAbility newSA = ((AbilityActivated) sa).getCopy();
|
||||
SpellAbility newSA = sa.copy(hostCard, false);
|
||||
if (params.containsKey("GainsAbilitiesLimitPerTurn")) {
|
||||
newSA.setRestrictions(sa.getRestrictions());
|
||||
newSA.getRestrictions().setLimitToCheck(params.get("GainsAbilitiesLimitPerTurn"));
|
||||
@@ -382,7 +382,6 @@ public final class StaticAbilityContinuous {
|
||||
newSA.setOriginalHost(c);
|
||||
newSA.setIntrinsic(false);
|
||||
newSA.setTemporary(true);
|
||||
newSA.setHostCard(hostCard);
|
||||
addFullAbs.add(newSA);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.Ability;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.OptionalCost;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
@@ -49,9 +48,8 @@ import forge.util.TextUtil;
|
||||
* @version $Id$
|
||||
*/
|
||||
public abstract class Trigger extends TriggerReplacementBase {
|
||||
|
||||
/** Constant <code>nextID=0</code>. */
|
||||
private static int nextID = 0;
|
||||
private static int maxId = 0;
|
||||
private static int nextId() { return ++maxId; }
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -59,23 +57,12 @@ public abstract class Trigger extends TriggerReplacementBase {
|
||||
* </p>
|
||||
*/
|
||||
public static void resetIDs() {
|
||||
Trigger.nextID = 50000;
|
||||
Trigger.maxId = 50000;
|
||||
}
|
||||
|
||||
/** The ID. */
|
||||
private int id = Trigger.nextID++;
|
||||
private int id;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* setID.
|
||||
* </p>
|
||||
*
|
||||
* @param id
|
||||
* a int.
|
||||
*/
|
||||
public final void setID(final int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/** The run params. */
|
||||
private Map<String, Object> runParams;
|
||||
@@ -131,9 +118,10 @@ public abstract class Trigger extends TriggerReplacementBase {
|
||||
* the intrinsic
|
||||
*/
|
||||
public Trigger(final Map<String, String> params, final Card host, final boolean intrinsic) {
|
||||
this.id = nextId();
|
||||
this.intrinsic = intrinsic;
|
||||
|
||||
this.setRunParams(new HashMap<String, Object>());
|
||||
this.setRunParams(Maps.newHashMap());
|
||||
this.originalMapParams.putAll(params);
|
||||
this.mapParams.putAll(params);
|
||||
this.setHostCard(host);
|
||||
@@ -462,13 +450,25 @@ public abstract class Trigger extends TriggerReplacementBase {
|
||||
|
||||
/**
|
||||
* Gets the id.
|
||||
*
|
||||
*
|
||||
* @return the id
|
||||
*/
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* setID.
|
||||
* </p>
|
||||
*
|
||||
* @param id
|
||||
* a int.
|
||||
*/
|
||||
public final void setId(final int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
private Ability triggeredSA;
|
||||
|
||||
/**
|
||||
@@ -515,33 +515,25 @@ public abstract class Trigger extends TriggerReplacementBase {
|
||||
void setMode(TriggerType triggerType) {
|
||||
mode = triggerType;
|
||||
}
|
||||
|
||||
|
||||
public final Trigger getCopyForHostCard(Card newHost) {
|
||||
final TriggerType tt = TriggerType.getTypeFor(this);
|
||||
final Trigger copy = tt.createTrigger(originalMapParams, newHost, intrinsic);
|
||||
public final Trigger copy(Card newHost, boolean lki) {
|
||||
final Trigger copy = (Trigger) clone();
|
||||
|
||||
if (this.getOverridingAbility() != null) {
|
||||
SpellAbility old = this.getOverridingAbility();
|
||||
SpellAbility sa = old;
|
||||
// try to copy it if newHost is not the wanted host
|
||||
final Card oldHost = old.getHostCard();
|
||||
if (!newHost.equals(oldHost)) {
|
||||
if (old instanceof AbilitySub) {
|
||||
sa = ((AbilitySub)old).getCopy();
|
||||
sa.setHostCard(newHost);
|
||||
}
|
||||
} else if (newHost != oldHost) {
|
||||
//host would be the same, but different state?
|
||||
sa.setHostCard(newHost);
|
||||
}
|
||||
copy.setOverridingAbility(sa);
|
||||
copy.originalMapParams.putAll(originalMapParams);
|
||||
copy.mapParams.putAll(originalMapParams);
|
||||
copy.setHostCard(newHost);
|
||||
|
||||
if (getOverridingAbility() != null) {
|
||||
copy.setOverridingAbility(getOverridingAbility().copy(newHost, lki));
|
||||
}
|
||||
|
||||
// 2015-03-07 Removing the ID copying which makes copied triggers Identical to each other when removing
|
||||
//copy.setID(this.getId());
|
||||
copy.setMode(this.getMode());
|
||||
copy.setTriggerPhases(this.validPhases);
|
||||
if (!lki) {
|
||||
copy.setId(nextId());
|
||||
}
|
||||
|
||||
if (validPhases != null) {
|
||||
copy.setTriggerPhases(Lists.newArrayList(validPhases));
|
||||
}
|
||||
copy.setActiveZone(validHostZones);
|
||||
copy.setTemporary(isTemporary());
|
||||
return copy;
|
||||
@@ -572,4 +564,14 @@ public abstract class Trigger extends TriggerReplacementBase {
|
||||
{
|
||||
this.numberTurnActivations = 0;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final Object clone() {
|
||||
try {
|
||||
return super.clone();
|
||||
} catch (final Exception ex) {
|
||||
throw new RuntimeException("Trigger : clone() error, " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,11 +86,9 @@ public enum TriggerType {
|
||||
Untaps(TriggerUntaps.class),
|
||||
Vote(TriggerVote.class);
|
||||
|
||||
private final Class<? extends Trigger> classTrigger;
|
||||
private final Constructor<? extends Trigger> constructor;
|
||||
|
||||
private TriggerType(Class<? extends Trigger> clasz) {
|
||||
classTrigger = clasz;
|
||||
constructor = findConstructor(clasz);
|
||||
}
|
||||
|
||||
@@ -122,16 +120,6 @@ public enum TriggerType {
|
||||
|
||||
throw new RuntimeException("Element " + value + " not found in TriggerType enum");
|
||||
}
|
||||
|
||||
public static TriggerType getTypeFor(Trigger t) {
|
||||
final Class<? extends Trigger> cls = t.getClass();
|
||||
for (final TriggerType v : TriggerType.values()) {
|
||||
if (v.classTrigger.equals(cls)) {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this method.
|
||||
|
||||
Reference in New Issue
Block a user