From eed1220c31b9d7e02cd3669809476ee44507753e Mon Sep 17 00:00:00 2001 From: TRT <> Date: Fri, 12 May 2023 22:14:26 +0200 Subject: [PATCH] Tweak TextChange transformation --- .../src/main/java/forge/game/ForgeScript.java | 7 --- .../java/forge/game/ability/AbilityUtils.java | 43 ++++++------------- .../src/main/java/forge/game/card/Card.java | 2 +- .../main/java/forge/game/cost/CostReveal.java | 1 - .../a/aberrant_researcher_perfected_form.txt | 2 +- .../res/cardsfolder/d/devout_invocation.txt | 2 +- .../m/minsc_boo_timeless_heroes.txt | 3 +- 7 files changed, 19 insertions(+), 41 deletions(-) diff --git a/forge-game/src/main/java/forge/game/ForgeScript.java b/forge-game/src/main/java/forge/game/ForgeScript.java index 1a5029cbde0..ee625766e9a 100644 --- a/forge-game/src/main/java/forge/game/ForgeScript.java +++ b/forge-game/src/main/java/forge/game/ForgeScript.java @@ -45,7 +45,6 @@ public class ForgeScript { int desiredColor = MagicColor.fromName(colorName); boolean hasColor = colors.hasAnyColor(desiredColor); return mustHave == hasColor; - } else if (property.contains("Colorless")) { // ... Card is colorless boolean non = property.startsWith("non"); boolean withSource = property.endsWith("Source"); @@ -53,34 +52,28 @@ public class ForgeScript { return false; } return non != colors.isColorless(); - } else if (property.contains("MultiColor")) { // ... Card is multicolored if (property.endsWith("Source") && isColorlessSource) return false; return property.startsWith("non") != colors.isMulticolor(); - } else if (property.contains("AllColors")) { if (property.endsWith("Source") && isColorlessSource) return false; return property.startsWith("non") != colors.isAllColors(); - } else if (property.contains("MonoColor")) { // ... Card is monocolored if (property.endsWith("Source") && isColorlessSource) return false; return property.startsWith("non") != colors.isMonoColor(); - } else if (property.startsWith("ChosenColor")) { if (property.endsWith("Source") && isColorlessSource) return false; return source.hasChosenColor() && colors.hasAnyColor(MagicColor.fromName(source.getChosenColor())); - } else if (property.startsWith("AnyChosenColor")) { if (property.endsWith("Source") && isColorlessSource) return false; return source.hasChosenColor() && colors.hasAnyColor(ColorSet.fromNames(source.getChosenColors()).getColor()); - } else if (property.equals("AssociatedWithChosenColor")) { final String color = source.getChosenColor(); switch (color) { diff --git a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java index 3badeee718b..5d09f5b19d4 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -79,8 +79,6 @@ import io.sentry.Sentry; public class AbilityUtils { private final static ImmutableList cmpList = ImmutableList.of("LT", "LE", "EQ", "GE", "GT", "NE"); - static public final String WITH_DELIMITER = "((?<=%1$s)|(?=%1$s))"; - // should the three getDefined functions be merged into one? Or better to // have separate? // If we only have one, each function needs to Cast the Object to the @@ -3012,10 +3010,8 @@ public class AbilityUtils { public static final String applyDescriptionTextChangeEffects(final String def, final Card card) { return applyTextChangeEffects(def, card, true); } - private static final String applyTextChangeEffects(final String def, final Card card, final boolean isDescriptive) { - return applyTextChangeEffects(def, isDescriptive, - card.getChangedTextColorWords(), card.getChangedTextTypeWords()); + return applyTextChangeEffects(def, isDescriptive, card.getChangedTextColorWords(), card.getChangedTextTypeWords()); } public static final String applyTextChangeEffects(final String def, final boolean isDescriptive, @@ -3027,7 +3023,6 @@ public class AbilityUtils { String replaced = def; for (final Entry e : colorMap.entrySet()) { final String key = e.getKey(); - String value; if (key.equals("Any")) { for (final byte c : MagicColor.WUBRG) { final String colorLowerCase = MagicColor.toLongString(c).toLowerCase(), @@ -3036,38 +3031,28 @@ public class AbilityUtils { if (e.getValue().equalsIgnoreCase(colorLowerCase)) { continue; } - value = getReplacedText(colorLowerCase, e.getValue(), isDescriptive); - replaced = replaced.replaceAll("(?)" + colorLowerCase, value.toLowerCase()); - value = getReplacedText(colorCaptCase, e.getValue(), isDescriptive); - replaced = replaced.replaceAll("(?)" + colorCaptCase, StringUtils.capitalize(value)); + replaced = getReplacedText(replaced, colorLowerCase, e.getValue().toLowerCase(), isDescriptive); + replaced = getReplacedText(replaced, colorCaptCase, e.getValue(), isDescriptive); } } else { - value = getReplacedText(key, e.getValue(), isDescriptive); - replaced = replaced.replaceAll("(?)" + key, value); + replaced = getReplacedText(replaced, key, e.getValue(), isDescriptive); } } - StringBuilder sb = new StringBuilder(); - for (String replacedPart : replaced.split(String.format(WITH_DELIMITER, "\\."))) { - if (!replacedPart.equals("Self") && !replacedPart.equals(".")) { - for (final Entry e : typeMap.entrySet()) { - final String key = e.getKey(); - final String pkey = CardType.getPluralType(key); - final String pvalue = getReplacedText(pkey, CardType.getPluralType(e.getValue()), isDescriptive); - replacedPart = replacedPart.replaceAll("(?)" + pkey, pvalue); - final String value = getReplacedText(key, e.getValue(), isDescriptive); - replacedPart = replacedPart.replaceAll("(?)" + key, value); - } - } - sb.append(replacedPart); + for (final Entry e : typeMap.entrySet()) { + final String key = e.getKey(); + replaced = getReplacedText(replaced, CardType.getPluralType(key), CardType.getPluralType(e.getValue()), isDescriptive); + replaced = getReplacedText(replaced, key, e.getValue(), isDescriptive); } - return sb.toString(); + + return replaced; } - private static final String getReplacedText(final String originalWord, final String newWord, final boolean isDescriptive) { + private static final String getReplacedText(final String text, final String originalWord, String newWord, final boolean isDescriptive) { if (isDescriptive) { - return "" + originalWord + " " + newWord; + newWord = "" + originalWord + " " + newWord; } - return newWord; + // use word boundaries and keep negations + return text.replaceAll((isDescriptive ? "(?)" : "") + "\\b(non)?" + originalWord, "$1" + newWord); } public static final String getSVar(final CardTraitBase ability, final String sVarName) { diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index 2e8cb693437..4f9a094df18 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -1602,7 +1602,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } runParams.put(AbilityKey.CounterAmount, delta); runParams.put(AbilityKey.NewCounterAmount, newValue); - getGame().getTriggerHandler().runTrigger(TriggerType.CounterRemovedOnce, AbilityKey.newMap(runParams), false); + getGame().getTriggerHandler().runTrigger(TriggerType.CounterRemovedOnce, runParams, false); } @Override diff --git a/forge-game/src/main/java/forge/game/cost/CostReveal.java b/forge-game/src/main/java/forge/game/cost/CostReveal.java index 8f10c61158f..9e7f9fc8866 100644 --- a/forge-game/src/main/java/forge/game/cost/CostReveal.java +++ b/forge-game/src/main/java/forge/game/cost/CostReveal.java @@ -97,7 +97,6 @@ public class CostReveal extends CostPartWithList { } else { return amount <= getMaxAmountX(ability, payer, effect); } - } @Override diff --git a/forge-gui/res/cardsfolder/a/aberrant_researcher_perfected_form.txt b/forge-gui/res/cardsfolder/a/aberrant_researcher_perfected_form.txt index cd87477bdb2..d67070223c5 100644 --- a/forge-gui/res/cardsfolder/a/aberrant_researcher_perfected_form.txt +++ b/forge-gui/res/cardsfolder/a/aberrant_researcher_perfected_form.txt @@ -5,7 +5,7 @@ PT:3/2 K:Flying T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigMill | TriggerDescription$ At the beginning of your upkeep, mill a card. If an instant or sorcery card was milled this way, transform CARDNAME. SVar:TrigMill:DB$ Mill | Defined$ You | RememberMilled$ True | SubAbility$ DBTransform -SVar:DBTransform:DB$ SetState | Defined$ Self | ConditionDefined$ Remembered | ConditionPresent$ Card.Instant,Card.Sorcery | ConditionCompare$ EQ1 | SubAbility$ Cleanup | Mode$ Transform +SVar:DBTransform:DB$ SetState | Defined$ Self | ConditionDefined$ Remembered | ConditionPresent$ Card.Instant,Card.Sorcery | SubAbility$ Cleanup | Mode$ Transform SVar:Cleanup:DB$ Cleanup | ClearRemembered$ True DeckHints:Ability$Delirium & Type$Instant|Sorcery AlternateMode:DoubleFaced diff --git a/forge-gui/res/cardsfolder/d/devout_invocation.txt b/forge-gui/res/cardsfolder/d/devout_invocation.txt index 919a81c5179..6abf307ae7a 100644 --- a/forge-gui/res/cardsfolder/d/devout_invocation.txt +++ b/forge-gui/res/cardsfolder/d/devout_invocation.txt @@ -1,7 +1,7 @@ Name:Devout Invocation ManaCost:6 W Types:Sorcery -A:SP$ Tap | CardChoices$ Creature.YouCtrl+untapped | AnyNumber$ True | ChoiceAmount$ Count$Valid Creature.YouCtrl+untapped | RememberTapped$ True | SpellDescription$ Tap any number of untapped creatures you control. Create a 4/4 white Angel creature token with flying for each creature tapped this way. | StackDescription$ SpellDescription +A:SP$ Tap | CardChoices$ Creature.YouCtrl+untapped | AnyNumber$ True | ChoiceAmount$ Count$Valid Creature.YouCtrl+untapped | RememberTapped$ True | SubAbility$ DBToken | SpellDescription$ Tap any number of untapped creatures you control. Create a 4/4 white Angel creature token with flying for each creature tapped this way. | StackDescription$ SpellDescription SVar:DBToken:DB$ Token | TokenAmount$ Y | TokenScript$ w_4_4_angel_flying | TokenOwner$ You | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:Y:Remembered$Amount diff --git a/forge-gui/res/cardsfolder/m/minsc_boo_timeless_heroes.txt b/forge-gui/res/cardsfolder/m/minsc_boo_timeless_heroes.txt index f079f6059da..2c806061aa1 100644 --- a/forge-gui/res/cardsfolder/m/minsc_boo_timeless_heroes.txt +++ b/forge-gui/res/cardsfolder/m/minsc_boo_timeless_heroes.txt @@ -7,9 +7,10 @@ T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ TrigToken | TriggerZ SVar:TrigToken:DB$ Token | TokenScript$ boo A:AB$ PutCounter | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | ValidTgts$ Creature.withTrample,Creature.withHaste | TgtPrompt$ Select target creature with trample or haste | TargetMin$ 0 | TargetMax$ 1 | CounterType$ P1P1 | CounterNum$ 3 | SpellDescription$ Put three +1/+1 counters on up to one target creature with trample or haste. A:AB$ Sacrifice | Cost$ SubCounter<2/LOYALTY> | Planeswalker$ True | SacValid$ Creature | RememberSacrificed$ True | SubAbility$ DBImmediateTrigger | SpellDescription$ Sacrifice a creature. -SVar:DBImmediateTrigger:DB$ ImmediateTrigger | Execute$ TrigDamage | ConditionDefined$ RememberedLKI | ConditionPresent$ Creature | RememberObjects$ RememberedLKI | SpellDescription$ When you do, CARDNAME deals X damage to any target, where X is that creature's power. If the sacrificed creature was a Hamster, draw X cards. +SVar:DBImmediateTrigger:DB$ ImmediateTrigger | Execute$ TrigDamage | ConditionDefined$ RememberedLKI | ConditionPresent$ Creature | RememberObjects$ RememberedLKI | SubAbility$ DBCleanup | SpellDescription$ When you do, CARDNAME deals X damage to any target, where X is that creature's power. If the sacrificed creature was a Hamster, draw X cards. SVar:TrigDamage:DB$ DealDamage | ValidTgts$ Any | NumDmg$ X | SubAbility$ DBDraw SVar:DBDraw:DB$ Draw | ConditionDefined$ DelayTriggerRememberedLKI | ConditionPresent$ Hamster | NumCards$ X +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:X:TriggerRemembered$CardPower K:CARDNAME can be your commander. DeckHas:Ability$Sacrifice|Counters|Token