mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 10:48:00 +00:00
Merge pull request #3723 from tool4ever/universes
CardDb: support rebranded versions
This commit is contained in:
@@ -293,6 +293,9 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
|
||||
CardEdition upcomingSet = null;
|
||||
Date today = new Date();
|
||||
|
||||
// do this first so they're not considered missing
|
||||
buildRenamedCards();
|
||||
|
||||
for (CardEdition e : editions.getOrderedEditions()) {
|
||||
boolean coreOrExpSet = e.getType() == CardEdition.Type.CORE || e.getType() == CardEdition.Type.EXPANSION;
|
||||
boolean isCoreExpSet = coreOrExpSet || e.getType() == CardEdition.Type.REPRINT;
|
||||
@@ -353,6 +356,38 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
|
||||
reIndex();
|
||||
}
|
||||
|
||||
private void buildRenamedCards() {
|
||||
// for now just check Universes Within
|
||||
for (CardInSet cis : editions.get("SLX").getCards()) {
|
||||
String orgName = alternateName.get(cis.name);
|
||||
if (orgName != null) {
|
||||
// found original (beyond) print
|
||||
CardRules org = getRules(orgName);
|
||||
|
||||
CardFace renamedMain = (CardFace) ((CardFace) org.getMainPart()).clone();
|
||||
renamedMain.setName(renamedMain.getAltName());
|
||||
renamedMain.setAltName(null);
|
||||
// TODO this could mess up some "named ..." cardname literals but there's no printing like that currently
|
||||
renamedMain.setOracleText(renamedMain.getOracleText().replace(orgName, renamedMain.getName()));
|
||||
facesByName.put(renamedMain.getName(), renamedMain);
|
||||
CardFace renamedOther = null;
|
||||
if (org.getOtherPart() != null) {
|
||||
renamedOther = (CardFace) ((CardFace) org.getOtherPart()).clone();
|
||||
orgName = renamedOther.getName();
|
||||
renamedOther.setName(renamedOther.getAltName());
|
||||
renamedOther.setAltName(null);
|
||||
renamedOther.setOracleText(renamedOther.getOracleText().replace(orgName, renamedOther.getName()));
|
||||
facesByName.put(renamedOther.getName(), renamedOther);
|
||||
}
|
||||
|
||||
CardRules within = new CardRules(new ICardFace[] { renamedMain, renamedOther, null, null, null, null, null }, org.getSplitType(), org.getAiHints());
|
||||
// so workshop can edit same script
|
||||
within.setNormalizedName(org.getNormalizedName());
|
||||
rulesByName.put(cis.name, within);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addCard(PaperCard paperCard) {
|
||||
if (excludeCard(paperCard.getName(), paperCard.getEdition()))
|
||||
return;
|
||||
@@ -930,7 +965,11 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
|
||||
}
|
||||
|
||||
public String getName(final String cardName) {
|
||||
if (alternateName.containsKey(cardName)) {
|
||||
return getName(cardName, false);
|
||||
}
|
||||
public String getName(final String cardName, boolean engine) {
|
||||
if (alternateName.containsKey(cardName) && engine) {
|
||||
// TODO might want to implement GUI option so it always fetches the Within version
|
||||
return alternateName.get(cardName);
|
||||
}
|
||||
return cardName;
|
||||
|
||||
@@ -20,7 +20,7 @@ import forge.card.mana.ManaCost;
|
||||
* <br><br>
|
||||
* <i>Do not use reference to class except for card parsing.<br>Always use reference to interface type outside of package.</i>
|
||||
*/
|
||||
final class CardFace implements ICardFace {
|
||||
final class CardFace implements ICardFace, Cloneable {
|
||||
|
||||
public enum FaceSelectionMethod { //
|
||||
USE_ACTIVE_FACE,
|
||||
@@ -32,7 +32,7 @@ final class CardFace implements ICardFace {
|
||||
private final static List<String> emptyList = Collections.unmodifiableList(new ArrayList<>());
|
||||
private final static Map<String, String> emptyMap = Collections.unmodifiableMap(new TreeMap<>());
|
||||
|
||||
private final String name;
|
||||
private String name;
|
||||
private String altName = null;
|
||||
private CardType type = null;
|
||||
private ManaCost manaCost = ManaCost.NO_COST;
|
||||
@@ -86,6 +86,7 @@ final class CardFace implements ICardFace {
|
||||
throw new RuntimeException("Card name is empty");
|
||||
}
|
||||
// Here come setters to allow parser supply values
|
||||
void setName(String name) { this.name = name; }
|
||||
void setAltName(String name) { this.altName = name; }
|
||||
void setType(CardType type0) { this.type = type0; }
|
||||
void setManaCost(ManaCost manaCost0) { this.manaCost = manaCost0; }
|
||||
@@ -153,4 +154,14 @@ final class CardFace implements ICardFace {
|
||||
public int compareTo(ICardFace o) {
|
||||
return getName().compareTo(o.getName());
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final Object clone() {
|
||||
try {
|
||||
return super.clone();
|
||||
} catch (final Exception ex) {
|
||||
throw new RuntimeException("CardFace : clone() error, " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ public final class CardRules implements ICardCharacteristics {
|
||||
private String partnerWith;
|
||||
private boolean custom;
|
||||
|
||||
private CardRules(ICardFace[] faces, CardSplitType altMode, CardAiHints cah) {
|
||||
public CardRules(ICardFace[] faces, CardSplitType altMode, CardAiHints cah) {
|
||||
splitType = altMode;
|
||||
mainPart = faces[0];
|
||||
otherPart = faces[1];
|
||||
|
||||
@@ -130,6 +130,7 @@ public abstract class DeckGeneratorBase {
|
||||
int res = 0;
|
||||
while (res < cnt) {
|
||||
PaperCard cp = source.get(MyRandom.getRandom().nextInt(srcLen));
|
||||
// TODO AltName conversion needed?
|
||||
int newCount = cardCounts.get(cp.getName()) + 1;
|
||||
|
||||
//add card to deck if not already maxed out on card
|
||||
|
||||
@@ -859,21 +859,23 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
|
||||
@Override
|
||||
public final String getName() {
|
||||
return getName(currentState);
|
||||
return getName(currentState, false);
|
||||
}
|
||||
|
||||
public final String getName(boolean alt) {
|
||||
return getName(currentState, alt);
|
||||
}
|
||||
public final String getName(CardStateName stateName) {
|
||||
return getName(getState(stateName));
|
||||
return getName(getState(stateName), false);
|
||||
}
|
||||
|
||||
public final String getName(CardState state) {
|
||||
public final String getName(CardState state, boolean alt) {
|
||||
String name = state.getName();
|
||||
for (CardChangedName change : this.changedCardNames.values()) {
|
||||
if (change.isOverwrite()) {
|
||||
name = change.getNewName();
|
||||
}
|
||||
}
|
||||
return name;
|
||||
return alt ? StaticData.instance().getCommonCards().getName(name, true) : name;
|
||||
}
|
||||
|
||||
public final boolean hasNonLegendaryCreatureNames() {
|
||||
@@ -5526,7 +5528,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return sharesNameWith(c1.getName());
|
||||
return sharesNameWith(c1.getName(true));
|
||||
}
|
||||
|
||||
public final boolean sharesNameWith(final String name) {
|
||||
@@ -5535,7 +5537,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean shares = getName().equals(name);
|
||||
boolean shares = getName(true).equals(name);
|
||||
|
||||
// Split cards has extra logic to check if it does share a name with
|
||||
if (isSplitCard()) {
|
||||
|
||||
@@ -1184,7 +1184,7 @@ public class CardView extends GameEntityView {
|
||||
}
|
||||
void updateName(CardState c) {
|
||||
Card card = c.getCard();
|
||||
setName(card.getName(c));
|
||||
setName(card.getName(c, false));
|
||||
|
||||
if (CardView.this.getCurrentState() == this) {
|
||||
if (card != null) {
|
||||
|
||||
@@ -215,7 +215,7 @@ public abstract class ACEditorBase<TItem extends InventoryItem, TModel extends D
|
||||
Iterable<Entry<String,Integer>> cardsByName = null;
|
||||
if (deck != null) {
|
||||
final CardPool allCards = deck.getAllCardsInASinglePool(deck.has(DeckSection.Commander));
|
||||
cardsByName = Aggregates.groupSumBy(allCards, PaperCard.FN_GET_NAME);
|
||||
cardsByName = Aggregates.groupSumBy(allCards, pc -> pc.getRules().getNormalizedName());
|
||||
}
|
||||
|
||||
for (final Entry<TItem, Integer> itemEntry : itemsToAdd) {
|
||||
@@ -237,7 +237,7 @@ public abstract class ACEditorBase<TItem extends InventoryItem, TModel extends D
|
||||
Entry<String, Integer> cardAmountInfo = Iterables.find(cardsByName, new Predicate<Entry<String, Integer>>() {
|
||||
@Override
|
||||
public boolean apply(Entry<String, Integer> t) {
|
||||
return t.getKey().equals(card.getName());
|
||||
return t.getKey().equals(card.getRules().getNormalizedName());
|
||||
}
|
||||
}, null);
|
||||
if (cardAmountInfo != null) {
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
Name:Havengul Laboratory
|
||||
ManaCost:no cost
|
||||
Types:Legendary Land
|
||||
A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}.
|
||||
A:AB$ Investigate | Cost$ 4 T | SpellDescription$ Investigate. (Create a Clue token. It's an artifact with "{2}, Sacrifice this artifact: Draw a card.")
|
||||
T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | CheckSVar$ ClueResearch | SVarCompare$ GE3 | Execute$ TrigTransform | TriggerDescription$ At the beginning of your end step, if you sacrificed three or more clues this turn, transform CARDNAME.
|
||||
SVar:TrigTransform:DB$ SetState | Defined$ Self | Mode$ Transform
|
||||
SVar:ClueResearch:PlayerCountPropertyYou$SacrificedThisTurn Clue
|
||||
DeckHas:Ability$Investigate|Token|Sacrifice|Graveyard
|
||||
DeckHints:Ability$Investigate
|
||||
AlternateMode:DoubleFaced
|
||||
Oracle:{T}: Add {C}.\n{4}, {T}: Investigate. (Create a Clue token. It's an artifact with "{2}, Sacrifice this artifact: Draw a card.")\nAt the beginning of your end step, if you sacrificed three or more clues this turn, transform Havengul Laboratory.
|
||||
|
||||
ALTERNATE
|
||||
|
||||
Name:Havengul Mystery
|
||||
ManaCost:no cost
|
||||
Types:Legendary Land
|
||||
T:Mode$ Transformed | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When this land transforms into CARDNAME, return target creature card from your graveyard to the battlefield.
|
||||
SVar:TrigReturn:DB$ ChangeZone | ValidTgts$ Creature.YouOwn | TgtPrompt$ Select target creature card from your graveyard | Origin$ Graveyard | Destination$ Battlefield | RememberTargets$ True
|
||||
T:Mode$ ChangesZone | ValidCard$ Card.IsRemembered | Origin$ Battlefield | Destination$ Any | Execute$ TrigTransform2 | TriggerZones$ Battlefield | TriggerDescription$ When the creature card put onto the battlefield with CARDNAME leaves the battlefield, transform CARDNAME.
|
||||
SVar:TrigTransform2:DB$ SetState | Defined$ Self | Mode$ Transform | SubAbility$ DBCleanup
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||
A:AB$ Mana | Cost$ T PayLife<1> | Produced$ B | SpellDescription$ Add {B}.
|
||||
Oracle:When this land transforms into Havengul Mystery, return target creature card from your graveyard to the battlefield.\nWhen the creature card put onto the battlefield with Havengul Mystery leaves the battlefield, transform Havengul Mystery.\n{T}, Pay 1 life: Add {B}.
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Hawkins National Laboratory
|
||||
AltName:Havengul Laboratory
|
||||
ManaCost:no cost
|
||||
Types:Legendary Land
|
||||
A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}.
|
||||
@@ -14,6 +15,7 @@ Oracle:{T}: Add {C}.\n{4}, {T}: Investigate.\nAt the beginning of your end step,
|
||||
ALTERNATE
|
||||
|
||||
Name:The Upside Down
|
||||
AltName:Havengul Mystery
|
||||
ManaCost:no cost
|
||||
Types:Legendary Land
|
||||
T:Mode$ Transformed | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When this land transforms into CARDNAME, return target creature card from your graveyard to the battlefield.
|
||||
|
||||
Reference in New Issue
Block a user