mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 20:28:00 +00:00
eye_of_ojer_taq_apex_observatory.txt + support
This commit is contained in:
@@ -506,13 +506,7 @@ public class GameAction {
|
||||
}
|
||||
|
||||
if (cause != null && cause.isCraft() && toBattlefield) { // retain cards crafted while ETB transformed
|
||||
for (Card craft : cause.getPaidList("ExiledCards")) {
|
||||
if (!craft.equals(copied) && !craft.isToken()) {
|
||||
copied.addExiledCard(craft);
|
||||
craft.setExiledWith(copied);
|
||||
craft.setExiledBy(cause.getActivatingPlayer());
|
||||
}
|
||||
}
|
||||
copied.retainPaidList(cause, "ExiledCards");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import forge.card.CardType;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.SpellAbilityEffect;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardFactoryUtil;
|
||||
import forge.game.player.Player;
|
||||
@@ -88,6 +89,24 @@ public class ChooseTypeEffect extends SpellAbilityEffect {
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "Shared":
|
||||
if (sa.hasParam("TypesFromDefined")) {
|
||||
CardCollection def = AbilityUtils.getDefinedCards(card, sa.getParam("TypesFromDefined"), sa);
|
||||
if (def.size() < 2) break; // need at least 2 cards to work with to find shared types
|
||||
final Card card1 = def.get(0);
|
||||
def.remove(0);
|
||||
for (final CardType.CoreType ct : card1.getType().getCoreTypes()) {
|
||||
boolean shared = true;
|
||||
for (final Card c : def) {
|
||||
if (!c.getType().hasType(ct)) {
|
||||
shared = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (shared) validTypes.add(ct.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -622,6 +622,9 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
|
||||
boolean result = c.changeToState(c.backside ? CardStateName.Transformed : CardStateName.Original);
|
||||
retResult = retResult || result;
|
||||
if (cause != null && cause.isCraft()) { // retain cards crafted while transforming in exile
|
||||
c.retainPaidList(cause, "ExiledCards");
|
||||
}
|
||||
}
|
||||
if (hasMergedCard()) {
|
||||
rebuildMutatedStates(cause);
|
||||
@@ -1283,6 +1286,17 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
}
|
||||
}
|
||||
|
||||
public final void retainPaidList(final SpellAbility cause, final String list) {
|
||||
for (Card craft : cause.getPaidList(list)) {
|
||||
if (!craft.equals(this) && !craft.isToken()) {
|
||||
addExiledCard(craft);
|
||||
craft.setExiledWith(this);
|
||||
craft.setExiledBy(cause.getActivatingPlayer());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final List<Integer> getStoredRolls() {
|
||||
return storedRolls;
|
||||
}
|
||||
|
||||
@@ -2942,8 +2942,8 @@ public class CardFactoryUtil {
|
||||
// Create return transformed ability string
|
||||
String ab = "AB$ ChangeZone | CostDesc$ " + cd.toString() + " | Cost$ " + cost + " | Origin$ Exile | " +
|
||||
"Destination$ Battlefield | Transformed$ True | Defined$ CorrectedSelf | Craft$ True | " +
|
||||
"XAnnounceTitle$ " + Localizer.getInstance().getMessage("lblCraft") + " | " +
|
||||
"StackDescription$ Return this card transformed under its owner's control. (Craft) | " +
|
||||
"XAnnounceTitle$ " + Localizer.getInstance().getMessage("lblCraft") + " | SorcerySpeed$ True" +
|
||||
" | StackDescription$ Return this card transformed under its owner's control. (Craft) | " +
|
||||
"SpellDescription$ (" + inst.getReminderText() + ")";
|
||||
final SpellAbility newSA = AbilityFactory.getAbility(ab, card);
|
||||
newSA.setIntrinsic(intrinsic);
|
||||
|
||||
@@ -195,10 +195,31 @@ public class CostExile extends CostPartWithList {
|
||||
type = TextUtil.fastReplace(type, TextUtil.concatNoSpace("+withTotalCMCEQ", totalM), "");
|
||||
}
|
||||
|
||||
boolean sharedType = false;
|
||||
if (type.contains("+withSharedCardType")) {
|
||||
sharedType = true;
|
||||
type = TextUtil.fastReplace(type, "+withSharedCardType", "");
|
||||
}
|
||||
|
||||
if (!type.contains("X") || ability.getXManaCostPaid() != null) {
|
||||
list = CardLists.getValidCards(list, type.split(";"), payer, source, ability);
|
||||
}
|
||||
|
||||
int amount = this.getAbilityAmount(ability);
|
||||
|
||||
if (sharedType) { // will need more logic if cost ever wants more than 2 that share a type
|
||||
if (list.size() < amount) return false;
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
final Card card1 = list.get(i);
|
||||
for (final Card compare : list) {
|
||||
if (!compare.equals(card1) && compare.sharesCardTypeWith(card1)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (totalCMC) {
|
||||
int needed = Integer.parseInt(this.getAmount().split("\\+")[0]);
|
||||
if (list.size() < needed) return false;
|
||||
@@ -209,8 +230,6 @@ public class CostExile extends CostPartWithList {
|
||||
return CardLists.cmcCanSumTo(i, list);
|
||||
}
|
||||
|
||||
int amount = this.getAbilityAmount(ability);
|
||||
|
||||
// for cards like Allosaurus Rider, do not count it
|
||||
if (this.from.size() == 1 && this.from.get(0).equals(ZoneType.Hand) && source.isInZone(ZoneType.Hand)
|
||||
&& list.contains(source)) {
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
Name:Eye of Ojer Taq
|
||||
ManaCost:3
|
||||
Types:Artifact
|
||||
A:AB$ Mana | Cost$ T | Produced$ Any | SpellDescription$ Add one mana of any color.
|
||||
K:Craft:6 ExileCtrlOrGrave<2/Permanent.Other+withSharedCardType/permanent>:two that share a card type:the two
|
||||
AlternateMode:DoubleFaced
|
||||
DeckHints:Ability$Discard|Mill|Sacrifice
|
||||
DeckHas:Ability$Mill|Graveyard|Token
|
||||
Oracle:{T}: Add one mana of any color.\nCraft with two that share a card type {6} ({6}, Exile this artifact, Exile the two from among other permanents you control and/or cards from your graveyard: Return this card transformed under its owner's control. Craft only as a sorcery.)
|
||||
|
||||
ALTERNATE
|
||||
|
||||
Name:Apex Observatory
|
||||
ManaCost:no cost
|
||||
Types:Artifact
|
||||
K:ETBReplacement:Other:Tap
|
||||
SVar:Tap:DB$ Tap | Defined$ Self | ETB$ True | SubAbility$ DBChooseType | SpellDescription$ CARDNAME enters the battlefield tapped. As it enters, choose a card type shared among two exiled cards used to craft it.
|
||||
SVar:DBChooseType:DB$ ChooseType | Type$ Shared | TypesFromDefined$ ExiledWith | AILogic$ MostProminentComputerControlsOrOwns
|
||||
A:AB$ Effect | Cost$ T | StaticAbilities$ Play | Triggers$ CastTrig | SpellDescription$ The next spell you cast this turn of the chosen type can be cast without paying its mana cost.
|
||||
SVar:Play:Mode$ Continuous | MayPlay$ True | MayPlayWithoutManaCost$ True | MayPlayDontGrantZonePermissions$ True | EffectZone$ Command | Affected$ Card.ChosenType | AffectedZone$ Hand,Graveyard,Library,Exile,Command | Description$ The next spell you cast this turn of the chosen type can be cast without paying its mana cost.
|
||||
SVar:CastTrig:Mode$ SpellCast | ValidCard$ Card.ChosenType | ValidActivatingPlayer$ You | Execute$ ExileSelf | Static$ True
|
||||
SVar:ExileSelf:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile
|
||||
Oracle:Apex Observatory enters the battlefield tapped. As it enters, choose a card type shared among two exiled cards used to craft it.\n{T}: The next spell you cast this turn of the chosen type can be cast without paying its mana cost.
|
||||
@@ -5,4 +5,5 @@ A:AB$ Mana | Cost$ T | Produced$ W | RestrictValid$ Spell.Artifact,Activated.Art
|
||||
A:AB$ ChangeZone | Cost$ 2 W T Exile<1+/Artifact.Other+withTotalCMCEQX/other artifacts you control with total mana value X> | Announce$ X | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Artifact.YouOwn+cmcLEX | TgtPrompt$ Select target artifact card with mana value X or less | SorcerySpeed$ True | SpellDescription$ Return target artifact card with mana value X or less from your graveyard to the battlefield. Activate only as a sorcery.
|
||||
SVar:X:Count$xPaid
|
||||
DeckNeeds:Type$Artifact
|
||||
AI:RemoveDeck:All
|
||||
Oracle:{T}: Add {W}. Spend this mana only to cast an artifact spell or activate an ability of an artifact source.\n{2}{W}, {T}, Exile one or more other artifacts you control with total mana value X: Return target artifact card with mana value X or less from your graveyard to the battlefield. Activate only as a sorcery.
|
||||
|
||||
@@ -241,6 +241,11 @@ public class HumanCostDecision extends CostDecisionMakerBase {
|
||||
totalM = type.split("withTotalCMCEQ")[1];
|
||||
type = TextUtil.fastReplace(type, TextUtil.concatNoSpace("+withTotalCMCEQ", totalM), "");
|
||||
}
|
||||
boolean sharedType = false;
|
||||
if (type.contains("+withSharedCardType")) {
|
||||
sharedType = true;
|
||||
type = TextUtil.fastReplace(type, "+withSharedCardType", "");
|
||||
}
|
||||
|
||||
CardCollection list;
|
||||
if (cost.zoneRestriction != 1) {
|
||||
@@ -292,7 +297,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
|
||||
if (fromZone == ZoneType.Library) { return exileFromTop(cost, c); }
|
||||
}
|
||||
if (fromTopGrave) { return exileFromTopGraveType(c, list); }
|
||||
if (cost.zoneRestriction != 0) { return exileFromMiscZone(cost, c, list); }
|
||||
if (cost.zoneRestriction != 0) { return exileFromMiscZone(cost, c, list, sharedType); }
|
||||
|
||||
final FCollectionView<Player> players = game.getPlayers();
|
||||
final List<Player> payableZone = new ArrayList<>();
|
||||
@@ -394,7 +399,8 @@ public class HumanCostDecision extends CostDecisionMakerBase {
|
||||
return PaymentDecision.card(list);
|
||||
}
|
||||
|
||||
private PaymentDecision exileFromMiscZone(final CostExile cost, final int nNeeded, final CardCollection typeList) {
|
||||
private PaymentDecision exileFromMiscZone(final CostExile cost, final int nNeeded, final CardCollection typeList,
|
||||
final boolean sharedType) {
|
||||
// when it's always a single triggered card getting exiled don't act like it might be different by offering the zone for choice
|
||||
if (cost.zoneRestriction == -1 && ability.isTrigger() && nNeeded == 1 && typeList.size() == 1) {
|
||||
if (confirmAction(cost, Localizer.getInstance().getMessage("lblExileConfirm", CardTranslation.getTranslatedName(typeList.getFirst().getName())))) {
|
||||
@@ -405,9 +411,15 @@ public class HumanCostDecision extends CostDecisionMakerBase {
|
||||
|
||||
final List<ZoneType> origin = Lists.newArrayList(cost.from);
|
||||
final CardCollection exiled = new CardCollection();
|
||||
final String required = sharedType ? " (must share a card type)" : "";
|
||||
|
||||
|
||||
final List<Card> chosen = controller.chooseCardsForZoneChange(ZoneType.Exile, origin, ability, typeList,
|
||||
mandatory ? nNeeded : 0, nNeeded, null, cost.toString(nNeeded), null);
|
||||
mandatory ? nNeeded : 0, nNeeded, null, cost.toString(nNeeded) + required,
|
||||
null);
|
||||
if (sharedType) {
|
||||
if (!chosen.get(1).sharesCardTypeWith(chosen.get(0))) return null;
|
||||
}
|
||||
|
||||
exiled.addAll(chosen);
|
||||
if (exiled.size() < nNeeded) {
|
||||
|
||||
Reference in New Issue
Block a user