Merge branch 'fixes' into 'master'

Fixes

See merge request core-developers/forge!276
This commit is contained in:
Sol
2018-03-07 21:46:27 +00:00
13 changed files with 65 additions and 37 deletions

View File

@@ -170,8 +170,8 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView {
* @return a boolean. * @return a boolean.
*/ */
public static boolean matchesValid(final Object o, final String[] valids, final Card srcCard) { public static boolean matchesValid(final Object o, final String[] valids, final Card srcCard) {
if (o instanceof GameEntity) { if (o instanceof GameObject) {
final GameEntity c = (GameEntity) o; final GameObject c = (GameObject) o;
return c.isValid(valids, srcCard.getController(), srcCard, null); return c.isValid(valids, srcCard.getController(), srcCard, null);
} }

View File

@@ -179,6 +179,18 @@ public class ForgeScript {
if (!sa.hasParam("Equip")) { if (!sa.hasParam("Equip")) {
return false; return false;
} }
} else if (property.startsWith("IsTargeting")) {
String k[] = property.split(" ", 2);
boolean found = false;
for (GameObject o : AbilityUtils.getDefinedObjects(source, k[1], spellAbility)) {
if (sa.isTargeting(o)) {
found = true;
break;
}
}
if (!found) {
return false;
}
} }
return true; return true;

View File

@@ -1205,7 +1205,7 @@ public class AbilityUtils {
final SpellAbility sa) { final SpellAbility sa) {
final FCollection<SpellAbility> sas = new FCollection<SpellAbility>(); final FCollection<SpellAbility> sas = new FCollection<SpellAbility>();
final String defined = (def == null) ? "Self" : applyAbilityTextChangeEffects(def, sa); // default to Self final String defined = (def == null) ? "Self" : applyAbilityTextChangeEffects(def, sa); // default to Self
final Game game = sa.getActivatingPlayer().getGame(); final Game game = card.getGame();
SpellAbility s = null; SpellAbility s = null;

View File

@@ -7,7 +7,6 @@ import forge.game.card.Card;
import forge.game.event.GameEventCardModeChosen; import forge.game.event.GameEventCardModeChosen;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.util.MyRandom; import forge.util.MyRandom;
import java.util.List; import java.util.List;
@@ -34,14 +33,16 @@ public class ChooseGenericEffect extends SpellAbilityEffect {
final SpellAbility fallback = sa.getAdditionalAbility("FallbackAbility"); final SpellAbility fallback = sa.getAdditionalAbility("FallbackAbility");
final List<Player> tgtPlayers = getDefinedPlayersOrTargeted(sa); final List<Player> tgtPlayers = getDefinedPlayersOrTargeted(sa);
final TargetRestrictions tgt = sa.getTargetRestrictions();
for (final Player p : tgtPlayers) { for (final Player p : tgtPlayers) {
// determine if any of the choices are not valid // determine if any of the choices are not valid
List<SpellAbility> saToRemove = Lists.<SpellAbility>newArrayList(); List<SpellAbility> saToRemove = Lists.<SpellAbility>newArrayList();
for (SpellAbility saChoice : abilities) { for (SpellAbility saChoice : abilities) {
if ("Player.IsRemembered".equals(saChoice.getParam("Defined")) && saChoice.hasParam("UnlessCost")) { if (!saChoice.getRestrictions().checkOtherRestrictions(host, saChoice, sa.getActivatingPlayer()) ) {
saToRemove.add(saChoice);
} else if (saChoice.hasParam("UnlessCost") &&
"Player.IsRemembered".equals(saChoice.getParam("Defined"))) {
String unlessCost = saChoice.getParam("UnlessCost"); String unlessCost = saChoice.getParam("UnlessCost");
// Sac a permanent in presence of Sigarda, Host of Herons // Sac a permanent in presence of Sigarda, Host of Herons
// TODO: generalize this by testing if the unless cost can be paid // TODO: generalize this by testing if the unless cost can be paid
@@ -55,7 +56,7 @@ public class ChooseGenericEffect extends SpellAbilityEffect {
} }
abilities.removeAll(saToRemove); abilities.removeAll(saToRemove);
if (tgt != null && sa.getTargets().isTargeting(p) && !p.canBeTargetedBy(sa)) { if (sa.usesTargeting() && sa.getTargets().isTargeting(p) && !p.canBeTargetedBy(sa)) {
continue; continue;
} }

View File

@@ -149,7 +149,7 @@ public class CloneEffect extends SpellAbilityEffect {
// set the host card for copied spellabilities // set the host card for copied spellabilities
for (final SpellAbility newSa : tgtCard.getSpellAbilities()) { for (final SpellAbility newSa : tgtCard.getSpellAbilities()) {
newSa.setHostCard(cardToCopy); newSa.setOriginalHost(cardToCopy);
} }
// restore name if it should be unchanged // restore name if it should be unchanged

View File

@@ -22,7 +22,7 @@ public abstract class RegenerateBaseEffect extends SpellAbilityEffect {
final Game game = hostCard.getGame(); final Game game = hostCard.getGame();
// create Effect for Regeneration // create Effect for Regeneration
Card eff = createEffect( final Card eff = createEffect(
hostCard, sa.getActivatingPlayer(), hostCard.getName() + "'s Regeneration", hostCard.getImageKey()); hostCard, sa.getActivatingPlayer(), hostCard.getName() + "'s Regeneration", hostCard.getImageKey());
eff.addRemembered(list); eff.addRemembered(list);

View File

@@ -66,7 +66,7 @@ public class SetStateEffect extends SpellAbilityEffect {
continue; continue;
} }
if ("Transform".equals(mode) && tgt.equals(host)) { if ("Transform".equals(mode) && tgt.equals(host) && sa.hasSVar("StoredTransform")) {
// If want to Transform, and host is trying to transform self, skip if not in alignment // If want to Transform, and host is trying to transform self, skip if not in alignment
boolean skip = tgt.getTransformedTimestamp() != Long.parseLong(sa.getSVar("StoredTransform")); boolean skip = tgt.getTransformedTimestamp() != Long.parseLong(sa.getSVar("StoredTransform"));
// Clear SVar from SA so it doesn't get reused accidentally // Clear SVar from SA so it doesn't get reused accidentally

View File

@@ -18,9 +18,7 @@
package forge.game.ability.effects; package forge.game.ability.effects;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import forge.StaticData; import forge.StaticData;
import forge.card.MagicColor; import forge.card.MagicColor;
@@ -281,10 +279,10 @@ public class TokenEffect extends SpellAbilityEffect {
if (prototype == null) { if (prototype == null) {
tokens = tokenInfo.makeTokenWithMultiplier(controller, finalAmount, cause != null); tokens = tokenInfo.makeTokenWithMultiplier(controller, finalAmount, cause != null);
grantHiddenKeywords(tokens); grantHiddenKeywords(tokens);
grantSvars(tokens, root); grantSvars(tokens, sa);
grantAbilities(tokens, root); grantAbilities(tokens, sa);
grantTriggers(tokens, root); grantTriggers(tokens, sa);
grantStatics(tokens, root); grantStatics(tokens, sa);
} else { } else {
tokens = TokenInfo.makeTokensFromPrototype(prototype, controller, finalAmount, cause != null); tokens = TokenInfo.makeTokensFromPrototype(prototype, controller, finalAmount, cause != null);
} }
@@ -352,7 +350,6 @@ public class TokenEffect extends SpellAbilityEffect {
} }
private String determineTokenColor(Card host) { private String determineTokenColor(Card host) {
Set<String> colorSet = new HashSet<>();
final String[] substitutedColors = Arrays.copyOf(this.tokenColors, this.tokenColors.length); final String[] substitutedColors = Arrays.copyOf(this.tokenColors, this.tokenColors.length);
for (int i = 0; i < substitutedColors.length; i++) { for (int i = 0; i < substitutedColors.length; i++) {
if (substitutedColors[i].equals("ChosenColor")) { if (substitutedColors[i].equals("ChosenColor")) {

View File

@@ -2350,11 +2350,12 @@ public class CardFactoryUtil {
final String name = StringUtils.join(k); final String name = StringUtils.join(k);
final String trigStr = "Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield " final String trigStr = "Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield "
+ " | Execute$ " + name + "Choose | ValidCard$ Card.Self | Secondary$ True" + " | ValidCard$ Card.Self | Secondary$ True"
+ " | TriggerDescription$ Fabricate " + n + " (" + inst.getReminderText() + ")"; + " | TriggerDescription$ Fabricate " + n + " (" + inst.getReminderText() + ")";
final String choose = "DB$ GenericChoice | Choices$ DB" + name + "Counter,DB" + name + "Token | ConditionPresent$ Card.StrictlySelf | SubAbility$ DB" + name + "Token2 | AILogic$ " + name; final String choose = "DB$ GenericChoice | AILogic$ " + name;
final String counter = "DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ " + n + " | SpellDescription$ Put " final String counter = "DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ " + n +
" | IsPresent$ Card.StrictlySelf | SpellDescription$ Put "
+ Lang.nounWithNumeral(n, "+1/+1 counter") + " on it."; + Lang.nounWithNumeral(n, "+1/+1 counter") + " on it.";
final String token = "DB$ Token | TokenAmount$ " + n + " | TokenName$ Servo | TokenTypes$ Artifact,Creature,Servo" final String token = "DB$ Token | TokenAmount$ " + n + " | TokenName$ Servo | TokenTypes$ Artifact,Creature,Servo"
+ " | TokenOwner$ You | TokenColors$ Colorless | TokenPower$ 1 | TokenToughness$ 1" + " | TokenOwner$ You | TokenColors$ Colorless | TokenPower$ 1 | TokenToughness$ 1"
@@ -2363,10 +2364,15 @@ public class CardFactoryUtil {
final Trigger trigger = TriggerHandler.parseTrigger(trigStr, card, intrinsic); final Trigger trigger = TriggerHandler.parseTrigger(trigStr, card, intrinsic);
card.setSVar(name + "Choose", choose); SpellAbility saChoose = AbilityFactory.getAbility(choose, card);
card.setSVar("DB" + name + "Counter", counter);
card.setSVar("DB" + name + "Token", token); List<AbilitySub> list = Lists.newArrayList();
card.setSVar("DB" + name + "Token2", token + " | ConditionPresent$ Card.StrictlySelf | ConditionCompare$ EQ0"); list.add((AbilitySub)AbilityFactory.getAbility(counter, card));
list.add((AbilitySub)AbilityFactory.getAbility(token, card));
saChoose.setAdditionalAbilityList("Choices", list);
saChoose.setIntrinsic(intrinsic);
trigger.setOverridingAbility(saChoose);
inst.addTrigger(trigger); inst.addTrigger(trigger);
} else if (keyword.startsWith("Fading")) { } else if (keyword.startsWith("Fading")) {
@@ -3367,6 +3373,8 @@ public class CardFactoryUtil {
// extra part for the Damage Prevention keywords // extra part for the Damage Prevention keywords
if (keyword.startsWith("Prevent all ")) { if (keyword.startsWith("Prevent all ")) {
// TODO add intrinsic warning
boolean isCombat = false; boolean isCombat = false;
boolean from = false; boolean from = false;
boolean to = false; boolean to = false;

View File

@@ -816,6 +816,10 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
if (manaPart != null) { if (manaPart != null) {
clone.manaPart = new AbilityManaPart(host, mapParams); clone.manaPart = new AbilityManaPart(host, mapParams);
} }
// clear maps for copy, the values will be added later
clone.additionalAbilities = Maps.newHashMap();
clone.additionalAbilityLists = Maps.newHashMap();
// run special copy Ability to make a deep copy // run special copy Ability to make a deep copy
CardFactory.copySpellAbility(this, clone, host, lki); CardFactory.copySpellAbility(this, clone, host, lki);
} catch (final CloneNotSupportedException e) { } catch (final CloneNotSupportedException e) {
@@ -1486,24 +1490,33 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
return topSA.getHostCard().isValid(tgt.getValidTgts(), getActivatingPlayer(), getHostCard(), this); return topSA.getHostCard().isValid(tgt.getValidTgts(), getActivatingPlayer(), getHostCard(), this);
} }
public boolean isTargeting(GameObject o) {
if (getTargets().isTargeting(o)) {
return true;
}
SpellAbility p = getParent();
return p != null && p.isTargeting(o);
}
// Takes one argument like Permanent.Blue+withFlying // Takes one argument like Permanent.Blue+withFlying
@Override @Override
public final boolean isValid(final String restriction, final Player sourceController, final Card source, SpellAbility spellAbility) { public final boolean isValid(final String restriction, final Player sourceController, final Card source, SpellAbility spellAbility) {
// Inclusive restrictions are Card types // Inclusive restrictions are Card types
final String[] incR = restriction.split("\\.", 2); final String[] incR = restriction.split("\\.", 2);
SpellAbility root = getRootAbility();
if (incR[0].equals("Spell")) { if (incR[0].equals("Spell")) {
if (!isSpell()) { if (!root.isSpell()) {
return false; return false;
} }
} }
else if (incR[0].equals("Triggered")) { else if (incR[0].equals("Triggered")) {
if (!isTrigger()) { if (!root.isTrigger()) {
return false; return false;
} }
} }
else if (incR[0].equals("Activated")) { else if (incR[0].equals("Activated")) {
if (!(this instanceof AbilityActivated)) { if (!(root instanceof AbilityActivated)) {
return false; return false;
} }
} }

View File

@@ -160,7 +160,7 @@ public class SimulateMatch {
private static void simulateSingleMatch(Match mc, int iGame, boolean outputGamelog) { private static void simulateSingleMatch(final Match mc, int iGame, boolean outputGamelog) {
final StopWatch sw = new StopWatch(); final StopWatch sw = new StopWatch();
sw.start(); sw.start();

View File

@@ -2,16 +2,13 @@ Name:Treasure Map
ManaCost:2 ManaCost:2
Types:Artifact Types:Artifact
A:AB$ Scry | Cost$ 1 T | ScryNum$ 1 | SubAbility$ DBLandmark | SpellDescription$ Scry 1. Put a landmark counter on CARDNAME. Then if there are three or more landmark counters on it, remove those counters, transform CARDNAME, and create three colorless Treasure artifact tokens with "{T}, Sacrifice this artifact: Add one mana of any color to your mana pool." A:AB$ Scry | Cost$ 1 T | ScryNum$ 1 | SubAbility$ DBLandmark | SpellDescription$ Scry 1. Put a landmark counter on CARDNAME. Then if there are three or more landmark counters on it, remove those counters, transform CARDNAME, and create three colorless Treasure artifact tokens with "{T}, Sacrifice this artifact: Add one mana of any color to your mana pool."
SVar:DBLandmark:DB$ PutCounter | Defined$ Self | CounterType$ LANDMARK | CounterNum$ 1 | SubAbility$ DBStoreSVar SVar:DBLandmark:DB$ PutCounter | Defined$ Self | CounterType$ LANDMARK | CounterNum$ 1 | SubAbility$ DBBranch
SVar:DBStoreSVar:DB$ StoreSVar | SVar$ FoundTreasure | Type$ Number | Expression$ 1 | ConditionCheckSVar$ XMarksTheSpot | ConditionSVarCompare$ GE1 | References$ XMarksTheSpot,FoundTreasure | SubAbility$ DBRemoveCtrs SVar:DBBranch:DB$ Branch | BranchConditionSVar$ XMarksTheSpot | References$ XMarksTheSpot | TrueSubAbility$ DBRemoveCtrs
SVar:DBRemoveCtrs:DB$ RemoveCounter | Defined$ Self | CounterType$ LANDMARK | CounterNum$ 3 | ConditionCheckSVar$ FoundTreasure | ConditionSVarCompare$ GE1 | References$ FoundTreasure | SubAbility$ DBTreasureTokens SVar:DBRemoveCtrs:DB$ RemoveCounter | Defined$ Self | CounterType$ LANDMARK | CounterNum$ All | SubAbility$ DBTransform
SVar:DBTreasureTokens:DB$ Token | TokenAmount$ 3 | TokenName$ Treasure | TokenTypes$ Artifact,Treasure | TokenOwner$ You | TokenColors$ Colorless | TokenImage$ c treasure | TokenAbilities$ ABTreasureMana | TokenAltImages$ c_treasure2,c_treasure3,c_treasure4 | ConditionCheckSVar$ FoundTreasure | ConditionSVarCompare$ GE1 | SubAbility$ DBTransform | References$ FoundTreasure SVar:DBTransform:DB$ SetState | Defined$ Self | Mode$ Transform | SubAbility$ DBTreasureTokens
SVar:DBTransform:DB$ SetState | Defined$ Self | Mode$ Transform | ConditionCheckSVar$ FoundTreasure | ConditionSVarCompare$ GE1 | References$ FoundTreasure SVar:DBTreasureTokens:DB$ Token | TokenAmount$ 3 | TokenName$ Treasure | TokenTypes$ Artifact,Treasure | TokenOwner$ You | TokenColors$ Colorless | TokenImage$ c treasure | TokenAbilities$ ABTreasureMana | TokenAltImages$ c_treasure2,c_treasure3,c_treasure4 | References$ ABTreasureMana
SVar:ABTreasureMana:AB$ Mana | Cost$ T Sac<1/CARDNAME> | Produced$ Any | Amount$ 1 | SpellDescription$ Add one mana of any color to your mana pool. SVar:ABTreasureMana:AB$ Mana | Cost$ T Sac<1/CARDNAME> | Produced$ Any | Amount$ 1 | SpellDescription$ Add one mana of any color to your mana pool.
SVar:XMarksTheSpot:Count$Valid Card.Self+counters_GE3_LANDMARK SVar:XMarksTheSpot:Count$Valid Card.Self+counters_GE3_LANDMARK
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | Execute$ DBInitSVar | Static$ True
SVar:DBInitSVar:DB$ StoreSVar | SVar$ FoundTreasure | Type$ Number | Expression$ 0 | References$ FoundTreasure
SVar:FoundTreasure:Number$0
AlternateMode:DoubleFaced AlternateMode:DoubleFaced
DeckHas:Ability$Token DeckHas:Ability$Token
SVar:Picture:http://www.wizards.com/global/images/magic/general/treasure_map.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/treasure_map.jpg

View File

@@ -22,7 +22,7 @@ import java.util.Map;
* Created by maustin on 09/05/2017. * Created by maustin on 09/05/2017.
*/ */
public class CommanderDeckGenerator extends DeckProxy implements Comparable<CommanderDeckGenerator> { public class CommanderDeckGenerator extends DeckProxy implements Comparable<CommanderDeckGenerator> {
public static List<DeckProxy> getCommanderDecks(DeckFormat format, boolean isForAi, boolean isCardGen){ public static List<DeckProxy> getCommanderDecks(final DeckFormat format, boolean isForAi, boolean isCardGen){
ItemPool uniqueCards; ItemPool uniqueCards;
if(isCardGen){ if(isCardGen){
uniqueCards = new ItemPool<PaperCard>(PaperCard.class); uniqueCards = new ItemPool<PaperCard>(PaperCard.class);