Support functional variants in translations

This commit is contained in:
Jetz
2024-08-26 00:25:43 -04:00
parent ab11c10fd4
commit 4afc86b4b4
22 changed files with 282 additions and 99 deletions

View File

@@ -82,8 +82,7 @@ public abstract class SpellAbilityEffect {
if (params.containsKey("SpellDescription")) {
if (rawSDesc.contains(",,,,,,")) rawSDesc = rawSDesc.replaceAll(",,,,,,", " ");
if (rawSDesc.contains(",,,")) rawSDesc = rawSDesc.replaceAll(",,,", " ");
String spellDesc = CardTranslation.translateSingleDescriptionText(rawSDesc,
sa.getHostCard().getName());
String spellDesc = CardTranslation.translateSingleDescriptionText(rawSDesc, sa.getHostCard());
//trim reminder text from StackDesc
int idxL = spellDesc.indexOf(" (");
@@ -113,7 +112,7 @@ public abstract class SpellAbilityEffect {
} else {
final String condDesc = sa.getParam("ConditionDescription");
final String afterDesc = sa.getParam("AfterDescription");
final String baseDesc = CardTranslation.translateSingleDescriptionText(this.getStackDescription(sa), sa.getHostCard().getName());
final String baseDesc = CardTranslation.translateSingleDescriptionText(this.getStackDescription(sa), sa.getHostCard());
if (condDesc != null) {
sb.append(condDesc).append(" ");
}

View File

@@ -76,7 +76,7 @@ import java.util.Map.Entry;
* @author Forge
* @version $Id$
*/
public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITranslatable {
private Game game;
private final IPaperCard paperCard;
@@ -2227,7 +2227,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
sbLong.append("\r\n");
}
sb.append(sbLong);
return CardTranslation.translateMultipleDescriptionText(sb.toString(), getName());
return CardTranslation.translateMultipleDescriptionText(sb.toString(), this);
}
// convert a keyword list to the String that should be displayed in game
@@ -2632,7 +2632,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
sbLong.append("\r\n");
}
sb.append(sbLong);
return CardTranslation.translateMultipleDescriptionText(sb.toString(), getName());
return CardTranslation.translateMultipleDescriptionText(sb.toString(), this);
}
private String kickerDesc(String keyword, String remText) {
@@ -3194,7 +3194,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
}
}
sb.append(CardTranslation.translateMultipleDescriptionText(sbBefore.toString(), state.getName()));
sb.append(CardTranslation.translateMultipleDescriptionText(sbBefore.toString(), state));
// add Spells there to main StringBuilder
sb.append(strSpell);
@@ -3223,7 +3223,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
}
}
sb.append(CardTranslation.translateMultipleDescriptionText(sbAfter.toString(), state.getName()));
sb.append(CardTranslation.translateMultipleDescriptionText(sbAfter.toString(), state));
return sb;
}
@@ -3553,8 +3553,10 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
public final void setCopiedPermanent(final Card c) {
if (copiedPermanent == c) { return; }
copiedPermanent = c;
if(c != null)
if(c != null) {
currentState.setOracleText(c.getOracleText());
currentState.setFunctionalVariantName(c.getCurrentState().getFunctionalVariantName());
}
//Could fetch the card rules oracle text in an "else" clause here,
//but CardRules isn't aware of the card's state. May be better to
//just stash the original oracle text if this comes up.
@@ -7558,6 +7560,23 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
currentState.setOracleText(oracleText);
}
@Override
public String getTranslationKey() {
return currentState.getTranslationKey();
}
@Override
public String getUntranslatedName() {
return this.getName();
}
@Override
public String getUntranslatedType() {
return currentState.getUntranslatedType();
}
@Override
public String getUntranslatedOracle() {
return currentState.getUntranslatedOracle();
}
@Override
public CardView getView() {
return view;

View File

@@ -355,13 +355,16 @@ public class CardFactory {
}
private static void readCardFace(Card c, ICardFace face) {
String variantName = null;
//If it's a functional variant card, switch to that first.
if(face.hasFunctionalVariants()) {
String variantName = c.getPaperCard().getFunctionalVariant();
variantName = c.getPaperCard().getFunctionalVariant();
if (!IPaperCard.NO_FUNCTIONAL_VARIANT.equals(variantName)) {
ICardFace variant = face.getFunctionalVariant(variantName);
if (variant != null)
if (variant != null) {
face = variant;
c.getCurrentState().setFunctionalVariantName(variantName);
}
else
System.err.printf("Tried to apply unknown or unsupported variant - Card: \"%s\"; Variant: %s\n", face.getName(), variantName);
}
@@ -369,7 +372,7 @@ public class CardFactory {
// Build English oracle and translated oracle mapping
if (c.getId() >= 0) {
CardTranslation.buildOracleMapping(face.getName(), face.getOracleText());
CardTranslation.buildOracleMapping(face.getName(), face.getOracleText(), variantName);
}
// Name first so Senty has the Card name

View File

@@ -47,17 +47,20 @@ import forge.game.spellability.SpellAbility;
import forge.game.spellability.SpellAbilityPredicates;
import forge.game.staticability.StaticAbility;
import forge.game.trigger.Trigger;
import forge.util.ITranslatable;
import forge.util.collect.FCollection;
import forge.util.collect.FCollectionView;
import io.sentry.Breadcrumb;
import io.sentry.Sentry;
import org.apache.commons.lang3.StringUtils;
public class CardState extends GameObject implements IHasSVars {
public class CardState extends GameObject implements IHasSVars, ITranslatable {
private String name = "";
private CardType type = new CardType(false);
private ManaCost manaCost = ManaCost.NO_COST;
private byte color = MagicColor.COLORLESS;
private String oracleText = "";
private String functionalVariantName = null;
private int basePower = 0;
private int baseToughness = 0;
private String basePowerString = null;
@@ -202,6 +205,16 @@ public class CardState extends GameObject implements IHasSVars {
view.setOracleText(oracleText);
}
public String getFunctionalVariantName() {
return functionalVariantName;
}
public void setFunctionalVariantName(String functionalVariantName) {
if(functionalVariantName != null && functionalVariantName.isEmpty())
functionalVariantName = null;
this.functionalVariantName = functionalVariantName;
view.setFunctionalVariantName(functionalVariantName);
}
public final int getBasePower() {
return basePower;
@@ -605,6 +618,7 @@ public class CardState extends GameObject implements IHasSVars {
setManaCost(source.getManaCost());
setColor(source.getColor());
setOracleText(source.getOracleText());
setFunctionalVariantName(source.getFunctionalVariantName());
setBasePower(source.getBasePower());
setBaseToughness(source.getBaseToughness());
setBaseLoyalty(source.getBaseLoyalty());
@@ -804,4 +818,21 @@ public class CardState extends GameObject implements IHasSVars {
}
return cloakUp;
}
@Override
public String getTranslationKey() {
if(StringUtils.isNotEmpty(functionalVariantName))
return name + " $" + functionalVariantName;
return name;
}
@Override
public String getUntranslatedType() {
return getType().toString();
}
@Override
public String getUntranslatedOracle() {
return getOracleText();
}
}

View File

@@ -22,10 +22,7 @@ import forge.trackable.TrackableCollection;
import forge.trackable.TrackableObject;
import forge.trackable.TrackableProperty;
import forge.trackable.Tracker;
import forge.util.CardTranslation;
import forge.util.Lang;
import forge.util.Localizer;
import forge.util.TextUtil;
import forge.util.*;
import forge.util.collect.FCollectionView;
import org.apache.commons.lang3.StringUtils;
@@ -1165,7 +1162,7 @@ public class CardView extends GameEntityView {
return (zone + ' ' + CardTranslation.getTranslatedName(name) + " (" + getId() + ")").trim();
}
public class CardStateView extends TrackableObject {
public class CardStateView extends TrackableObject implements ITranslatable {
private static final long serialVersionUID = 6673944200513430607L;
private final CardStateName state;
@@ -1318,6 +1315,13 @@ public class CardView extends GameEntityView {
set(TrackableProperty.OracleText, oracleText.replace("\\n", "\r\n\r\n").trim());
}
public String getFunctionalVariantName() {
return get(TrackableProperty.FunctionalVariant);
}
void setFunctionalVariantName(String functionalVariant) {
set(TrackableProperty.FunctionalVariant, functionalVariant);
}
public String getRulesText() {
return get(TrackableProperty.RulesText);
}
@@ -1741,6 +1745,25 @@ public class CardView extends GameEntityView {
public boolean isAttraction() {
return getType().isAttraction();
}
@Override
public String getTranslationKey() {
String key = getName();
String variant = getFunctionalVariantName();
if(StringUtils.isNotEmpty(variant))
key = key + " $" + variant;
return key;
}
@Override
public String getUntranslatedType() {
return getType().toString();
}
@Override
public String getUntranslatedOracle() {
return getOracleText();
}
}
//special methods for updating card and player properties as needed and returning the new collection

View File

@@ -23,6 +23,7 @@ import java.util.Objects;
import com.google.common.collect.*;
import forge.util.ITranslatable;
import org.apache.commons.lang3.StringUtils;
import forge.game.Game;
@@ -221,15 +222,16 @@ public abstract class ReplacementEffect extends TriggerReplacementBase {
public String getDescription() {
if (hasParam("Description") && !this.isSuppressed()) {
String desc = AbilityUtils.applyDescriptionTextChangeEffects(getParam("Description"), this);
String currentName;
ITranslatable nameSource;
if (this.isIntrinsic() && cardState != null && cardState.getCard() == getHostCard()) {
currentName = cardState.getName();
nameSource = cardState;
} else {
currentName = getHostCard().getName();
nameSource = getHostCard();
}
desc = CardTranslation.translateSingleDescriptionText(desc, currentName);
desc = TextUtil.fastReplace(desc, "CARDNAME", CardTranslation.getTranslatedName(currentName));
desc = TextUtil.fastReplace(desc, "NICKNAME", Lang.getInstance().getNickName(CardTranslation.getTranslatedName(currentName)));
desc = CardTranslation.translateMultipleDescriptionText(desc, nameSource);
String translatedName = CardTranslation.getTranslatedName(nameSource);
desc = TextUtil.fastReplace(desc, "CARDNAME", translatedName);
desc = TextUtil.fastReplace(desc, "NICKNAME", Lang.getInstance().getNickName(translatedName));
if (desc.contains("EFFECTSOURCE")) {
desc = TextUtil.fastReplace(desc, "EFFECTSOURCE", getHostCard().getEffectSource().toString());
}

View File

@@ -20,6 +20,7 @@ package forge.game.spellability;
import java.util.*;
import forge.game.cost.CostSacrifice;
import forge.util.*;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
@@ -68,11 +69,6 @@ import forge.game.staticability.StaticAbilityMustTarget;
import forge.game.trigger.Trigger;
import forge.game.trigger.TriggerType;
import forge.game.zone.ZoneType;
import forge.util.Aggregates;
import forge.util.CardTranslation;
import forge.util.Lang;
import forge.util.Localizer;
import forge.util.TextUtil;
//only SpellAbility can go on the stack
//override any methods as needed
@@ -988,16 +984,17 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
}
String desc = node.getDescription();
if (node.getHostCard() != null) {
String currentName;
ITranslatable nameSource;
// if alternate state is viewed while card uses original
if (node.isIntrinsic() && node.cardState != null && node.cardState.getCard() == node.getHostCard()) {
currentName = node.cardState.getName();
nameSource = node.cardState;
} else {
currentName = node.getHostCard().getName();
nameSource = node.getHostCard();
}
desc = CardTranslation.translateMultipleDescriptionText(desc, currentName);
desc = TextUtil.fastReplace(desc, "CARDNAME", CardTranslation.getTranslatedName(currentName));
desc = TextUtil.fastReplace(desc, "NICKNAME", Lang.getInstance().getNickName(CardTranslation.getTranslatedName(currentName)));
desc = CardTranslation.translateMultipleDescriptionText(desc, nameSource);
String translatedName = CardTranslation.getTranslatedName(nameSource);
desc = TextUtil.fastReplace(desc, "CARDNAME", translatedName);
desc = TextUtil.fastReplace(desc, "NICKNAME", Lang.getInstance().getNickName(translatedName));
if (node.getOriginalHost() != null) {
desc = TextUtil.fastReplace(desc, "ORIGINALHOST", node.getOriginalHost().getName());
}

View File

@@ -45,11 +45,7 @@ import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.zone.Zone;
import forge.game.zone.ZoneType;
import forge.util.CardTranslation;
import forge.util.Expressions;
import forge.util.FileSection;
import forge.util.Lang;
import forge.util.TextUtil;
import forge.util.*;
/**
* The Class StaticAbility.
@@ -187,15 +183,16 @@ public class StaticAbility extends CardTraitBase implements IIdentifiable, Clone
@Override
public final String toString() {
if (hasParam("Description") && !this.isSuppressed()) {
String currentName;
ITranslatable nameSource;
if (this.isIntrinsic() && cardState != null && cardState.getCard() == getHostCard()) {
currentName = cardState.getName();
nameSource = cardState;
} else {
currentName = getHostCard().getName();
nameSource = getHostCard();
}
String desc = CardTranslation.translateSingleDescriptionText(getParam("Description"), currentName);
desc = TextUtil.fastReplace(desc, "CARDNAME", CardTranslation.getTranslatedName(currentName));
desc = TextUtil.fastReplace(desc, "NICKNAME", Lang.getInstance().getNickName(CardTranslation.getTranslatedName(currentName)));
String desc = CardTranslation.translateSingleDescriptionText(getParam("Description"), nameSource);
String translatedName = CardTranslation.getTranslatedName(nameSource);
desc = TextUtil.fastReplace(desc, "CARDNAME", translatedName);
desc = TextUtil.fastReplace(desc, "NICKNAME", Lang.getInstance().getNickName(translatedName));
return desc;
} else {

View File

@@ -36,6 +36,7 @@ import forge.game.spellability.SpellAbility;
import forge.game.zone.CostPaymentStack;
import forge.game.zone.ZoneType;
import forge.util.CardTranslation;
import forge.util.ITranslatable;
import forge.util.Lang;
import forge.util.TextUtil;
@@ -119,17 +120,18 @@ public abstract class Trigger extends TriggerReplacementBase {
public String toString(boolean active) {
if (hasParam("TriggerDescription") && !this.isSuppressed()) {
StringBuilder sb = new StringBuilder();
String currentName;
ITranslatable nameSource;
if (this.isIntrinsic() && cardState != null && cardState.getCard() == getHostCard()) {
currentName = cardState.getName();
nameSource = cardState;
} else {
currentName = getHostCard().getName();
nameSource = getHostCard();
}
String desc = getParam("TriggerDescription");
if (!desc.contains("ABILITY")) {
desc = CardTranslation.translateSingleDescriptionText(getParam("TriggerDescription"), currentName);
desc = TextUtil.fastReplace(desc,"CARDNAME", CardTranslation.getTranslatedName(currentName));
desc = TextUtil.fastReplace(desc,"NICKNAME", Lang.getInstance().getNickName(CardTranslation.getTranslatedName(currentName)));
desc = CardTranslation.translateSingleDescriptionText(getParam("TriggerDescription"), nameSource);
String translatedName = CardTranslation.getTranslatedName(nameSource);
desc = TextUtil.fastReplace(desc,"CARDNAME", translatedName);
desc = TextUtil.fastReplace(desc,"NICKNAME", Lang.getInstance().getNickName(translatedName));
if (desc.contains("ORIGINALHOST") && this.getOriginalHost() != null) {
desc = TextUtil.fastReplace(desc, "ORIGINALHOST", this.getOriginalHost().getName());
}
@@ -220,10 +222,10 @@ public abstract class Trigger extends TriggerReplacementBase {
}
result = TextUtil.fastReplace(result, "ABILITY", saDesc);
String currentName = sa.getHostCard().getName();
result = CardTranslation.translateMultipleDescriptionText(result, currentName);
result = TextUtil.fastReplace(result,"CARDNAME", CardTranslation.getTranslatedName(currentName));
result = TextUtil.fastReplace(result,"NICKNAME", Lang.getInstance().getNickName(CardTranslation.getTranslatedName(currentName)));
result = CardTranslation.translateMultipleDescriptionText(result, sa.getHostCard());
String translatedName = CardTranslation.getTranslatedName(sa.getHostCard());
result = TextUtil.fastReplace(result,"CARDNAME", translatedName);
result = TextUtil.fastReplace(result,"NICKNAME", Lang.getInstance().getNickName(translatedName));
}
return result;

View File

@@ -123,6 +123,7 @@ public enum TrackableProperty {
ManaCost(TrackableTypes.ManaCostType),
SetCode(TrackableTypes.StringType),
Rarity(TrackableTypes.EnumType(CardRarity.class)),
FunctionalVariant(TrackableTypes.StringType),
OracleText(TrackableTypes.StringType),
RulesText(TrackableTypes.StringType),
Power(TrackableTypes.IntegerType),