mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-14 17:58:01 +00:00
Fix facedown permanent with adventure (#4355)
* Restore adventure text when card not in play * Remove obsolete code * Fix crash with Cybership * Fix NPE
This commit is contained in:
@@ -635,8 +635,7 @@ public class AttachAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cards that trigger on dealing damage
|
// Cards that trigger on dealing damage
|
||||||
private static Card attachAICuriosityPreference(final SpellAbility sa, final List<Card> list, final boolean mandatory,
|
private static Card attachAICuriosityPreference(final SpellAbility sa, final List<Card> list, final boolean mandatory, final Card attachSource) {
|
||||||
final Card attachSource) {
|
|
||||||
Card chosen = null;
|
Card chosen = null;
|
||||||
int priority = 0;
|
int priority = 0;
|
||||||
for (Card card : list) {
|
for (Card card : list) {
|
||||||
@@ -690,7 +689,6 @@ public class AttachAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return chosen;
|
return chosen;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ import forge.game.zone.ZoneType;
|
|||||||
public class FogAi extends SpellAbilityAi {
|
public class FogAi extends SpellAbilityAi {
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
|
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected boolean canPlayAI(Player ai, SpellAbility sa) {
|
protected boolean canPlayAI(Player ai, SpellAbility sa) {
|
||||||
final Game game = ai.getGame();
|
final Game game = ai.getGame();
|
||||||
@@ -121,7 +121,7 @@ public class FogAi extends SpellAbilityAi {
|
|||||||
int fogs = 0;
|
int fogs = 0;
|
||||||
for (Card c : ai.getCardsActivatableInExternalZones(false)) {
|
for (Card c : ai.getCardsActivatableInExternalZones(false)) {
|
||||||
for (SpellAbility ability : c.getSpellAbilities()) {
|
for (SpellAbility ability : c.getSpellAbilities()) {
|
||||||
if (ability.getApi().equals(ApiType.Fog)) {
|
if (ApiType.Fog.equals(ability.getApi())) {
|
||||||
fogs++;
|
fogs++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -130,7 +130,7 @@ public class FogAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
for (Card c : ai.getCardsIn(ZoneType.Hand)) {
|
for (Card c : ai.getCardsIn(ZoneType.Hand)) {
|
||||||
for (SpellAbility ability : c.getSpellAbilities()) {
|
for (SpellAbility ability : c.getSpellAbilities()) {
|
||||||
if (ability.getApi().equals(ApiType.Fog)) {
|
if (ApiType.Fog.equals(ability.getApi())) {
|
||||||
fogs++;
|
fogs++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -510,11 +510,6 @@ public class GameAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if an adventureCard is put from Stack somewhere else, need to reset to Original State
|
|
||||||
if (copied.isAdventureCard() && ((zoneFrom != null && zoneFrom.is(ZoneType.Stack)) || !zoneTo.is(ZoneType.Stack))) {
|
|
||||||
copied.setState(CardStateName.Original, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
GameEntityCounterTable table = new GameEntityCounterTable();
|
GameEntityCounterTable table = new GameEntityCounterTable();
|
||||||
|
|
||||||
if (mergedCards != null) {
|
if (mergedCards != null) {
|
||||||
@@ -992,11 +987,11 @@ public class GameAction {
|
|||||||
if (!lki.getController().equals(lki.getOwner())) {
|
if (!lki.getController().equals(lki.getOwner())) {
|
||||||
game.getTriggerHandler().registerActiveLTBTrigger(lki);
|
game.getTriggerHandler().registerActiveLTBTrigger(lki);
|
||||||
}
|
}
|
||||||
|
final Map<AbilityKey, Object> runParams = AbilityKey.mapFromCard(c);
|
||||||
|
runParams.put(AbilityKey.CardLKI, lki);
|
||||||
|
runParams.put(AbilityKey.Origin, c.getZone().getZoneType().name());
|
||||||
|
game.getTriggerHandler().runTrigger(TriggerType.ChangesZone, runParams, false);
|
||||||
}
|
}
|
||||||
final Map<AbilityKey, Object> runParams = AbilityKey.mapFromCard(c);
|
|
||||||
runParams.put(AbilityKey.CardLKI, lki);
|
|
||||||
runParams.put(AbilityKey.Origin, c.getZone().getZoneType().name());
|
|
||||||
game.getTriggerHandler().runTrigger(TriggerType.ChangesZone, runParams, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -143,13 +143,13 @@ public class GameLogFormatter extends IGameEventVisitor.Base<GameLogEntry> {
|
|||||||
for (final GameOutcome game : gamesPlayed) {
|
for (final GameOutcome game : gamesPlayed) {
|
||||||
RegisteredPlayer player = game.getWinningPlayer();
|
RegisteredPlayer player = game.getWinningPlayer();
|
||||||
|
|
||||||
int amount = winCount.containsKey(player) ? winCount.get(player) : 0;
|
int amount = winCount.getOrDefault(player, 0);
|
||||||
winCount.put(player, amount + 1);
|
winCount.put(player, amount + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
for (Entry<RegisteredPlayer, String> entry : players.entrySet()) {
|
for (Entry<RegisteredPlayer, String> entry : players.entrySet()) {
|
||||||
int amount = winCount.containsKey(entry.getKey()) ? winCount.get(entry.getKey()) : 0;
|
int amount = winCount.getOrDefault(entry.getKey(), 0);
|
||||||
|
|
||||||
sb.append(entry.getValue()).append(": ").append(amount).append(" ");
|
sb.append(entry.getValue()).append(": ").append(amount).append(" ");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,8 +58,6 @@ public enum PlanarDice {
|
|||||||
}
|
}
|
||||||
PlanarDice res = results.get(0);
|
PlanarDice res = results.get(0);
|
||||||
|
|
||||||
PlanarDice trigRes = res;
|
|
||||||
|
|
||||||
final Map<AbilityKey, Object> resRepParams = AbilityKey.mapFromAffected(roller);
|
final Map<AbilityKey, Object> resRepParams = AbilityKey.mapFromAffected(roller);
|
||||||
resRepParams.put(AbilityKey.Result, res);
|
resRepParams.put(AbilityKey.Result, res);
|
||||||
|
|
||||||
@@ -67,14 +65,14 @@ public enum PlanarDice {
|
|||||||
case NotReplaced:
|
case NotReplaced:
|
||||||
break;
|
break;
|
||||||
case Updated: {
|
case Updated: {
|
||||||
trigRes = (PlanarDice) resRepParams.get(AbilityKey.Result);
|
res = (PlanarDice) resRepParams.get(AbilityKey.Result);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<AbilityKey, Object> runParams = AbilityKey.mapFromPlayer(roller);
|
Map<AbilityKey, Object> runParams = AbilityKey.mapFromPlayer(roller);
|
||||||
runParams.put(AbilityKey.Result, trigRes);
|
runParams.put(AbilityKey.Result, res);
|
||||||
game.getTriggerHandler().runTrigger(TriggerType.PlanarDice, runParams,false);
|
game.getTriggerHandler().runTrigger(TriggerType.PlanarDice, runParams, false);
|
||||||
|
|
||||||
// Also run normal RolledDie and RolledDieOnce triggers
|
// Also run normal RolledDie and RolledDieOnce triggers
|
||||||
for (int r = 0; r < rolls; r++) {
|
for (int r = 0; r < rolls; r++) {
|
||||||
@@ -98,7 +96,6 @@ public enum PlanarDice {
|
|||||||
* @return enum equivalent
|
* @return enum equivalent
|
||||||
*/
|
*/
|
||||||
public static PlanarDice smartValueOf(String value) {
|
public static PlanarDice smartValueOf(String value) {
|
||||||
|
|
||||||
final String valToCompate = value.trim();
|
final String valToCompate = value.trim();
|
||||||
for (final PlanarDice v : PlanarDice.values()) {
|
for (final PlanarDice v : PlanarDice.values()) {
|
||||||
if (v.name().compareToIgnoreCase(valToCompate) == 0) {
|
if (v.name().compareToIgnoreCase(valToCompate) == 0) {
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ public abstract class TriggerReplacementBase extends CardTraitBase implements II
|
|||||||
public Set<ZoneType> getActiveZone() {
|
public Set<ZoneType> getActiveZone() {
|
||||||
return validHostZones;
|
return validHostZones;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setActiveZone(EnumSet<ZoneType> zones) {
|
public void setActiveZone(EnumSet<ZoneType> zones) {
|
||||||
validHostZones = zones;
|
validHostZones = zones;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -374,9 +374,8 @@ public class DigEffect extends SpellAbilityEffect {
|
|||||||
|
|
||||||
for (Card c : movedCards) {
|
for (Card c : movedCards) {
|
||||||
final ZoneType origin = c.getZone().getZoneType();
|
final ZoneType origin = c.getZone().getZoneType();
|
||||||
final PlayerZone zone = c.getOwner().getZone(destZone1);
|
|
||||||
|
|
||||||
if (zone.is(ZoneType.Library) || zone.is(ZoneType.PlanarDeck) || zone.is(ZoneType.SchemeDeck)) {
|
if (destZone1.equals(ZoneType.Library) || destZone1.equals(ZoneType.PlanarDeck) || destZone1.equals(ZoneType.SchemeDeck)) {
|
||||||
c = game.getAction().moveTo(destZone1, c, libraryPosition, sa);
|
c = game.getAction().moveTo(destZone1, c, libraryPosition, sa);
|
||||||
} else {
|
} else {
|
||||||
Map<AbilityKey, Object> moveParams = AbilityKey.newMap();
|
Map<AbilityKey, Object> moveParams = AbilityKey.newMap();
|
||||||
@@ -410,7 +409,7 @@ public class DigEffect extends SpellAbilityEffect {
|
|||||||
host.removeRemembered(c);
|
host.removeRemembered(c);
|
||||||
animate.setSVar("unanimateTimestamp", String.valueOf(game.getTimestamp()));
|
animate.setSVar("unanimateTimestamp", String.valueOf(game.getTimestamp()));
|
||||||
}
|
}
|
||||||
c = game.getAction().moveTo(zone, c, sa, moveParams);
|
c = game.getAction().moveTo(c.getController().getZone(destZone1), c, sa, moveParams);
|
||||||
if (destZone1.equals(ZoneType.Battlefield)) {
|
if (destZone1.equals(ZoneType.Battlefield)) {
|
||||||
if (addToCombat(c, c.getController(), sa, "Attacking", "Blocking")) {
|
if (addToCombat(c, c.getController(), sa, "Attacking", "Blocking")) {
|
||||||
combatChanged = true;
|
combatChanged = true;
|
||||||
|
|||||||
@@ -2682,11 +2682,6 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip Basic Spells
|
|
||||||
if (sa.isSpell() && sa.isBasicSpell()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// should not print Spelldescription for Morph
|
// should not print Spelldescription for Morph
|
||||||
if (sa.isCastFaceDown()) {
|
if (sa.isCastFaceDown()) {
|
||||||
continue;
|
continue;
|
||||||
@@ -2704,6 +2699,8 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
|||||||
sbSA.append(": ");
|
sbSA.append(": ");
|
||||||
sbSA.append(sAbility);
|
sbSA.append(sAbility);
|
||||||
sAbility = sbSA.toString();
|
sAbility = sbSA.toString();
|
||||||
|
} else if (sa.isSpell() && sa.isBasicSpell()) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sa.getManaPart() != null) {
|
if (sa.getManaPart() != null) {
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
Name:Blood for Bones
|
Name:Blood for Bones
|
||||||
ManaCost:3 B
|
ManaCost:3 B
|
||||||
Types:Sorcery
|
Types:Sorcery
|
||||||
A:SP$ ChangeZone | Cost$ 3 B Sac<1/Creature> | Origin$ Graveyard | Destination$ Battlefield | Hidden$ True | Mandatory$ True | ChangeType$ Creature.YouOwn | PrimaryPrompt$ Choose a creature card to return to the battlefield | ChangeTypeDesc$ creature | RememberChanged$ True | SubAbility$ DBChangeZone | SpellDescription$ Return a creature card from your graveyard to the battlefield, then return another creature card from your graveyard to your hand.
|
A:SP$ ChangeZone | Cost$ 3 B Sac<1/Creature> | Origin$ Graveyard | Destination$ Battlefield | Hidden$ True | Mandatory$ True | ChangeType$ Creature.YouOwn | PrimaryPrompt$ Choose a creature card to return to the battlefield | ChangeTypeDesc$ creature | SubAbility$ DBChangeZone | SpellDescription$ Return a creature card from your graveyard to the battlefield, then return another creature card from your graveyard to your hand.
|
||||||
SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Hand | Hidden$ True | Mandatory$ True | ChangeType$ Creature.YouOwn+IsNotRemembered | PrimaryPrompt$ Choose another creature card to return to your hand | ChangeNumDesc$ another | ChangeTypeDesc$ creature | SubAbility$ DBCleanup
|
SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Hand | Hidden$ True | Mandatory$ True | ChangeType$ Creature.YouOwn | PrimaryPrompt$ Choose another creature card to return to your hand | ChangeNumDesc$ another | ChangeTypeDesc$ creature
|
||||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
|
||||||
AI:RemoveDeck:Random
|
AI:RemoveDeck:Random
|
||||||
Oracle:As an additional cost to cast this spell, sacrifice a creature.\nReturn a creature card from your graveyard to the battlefield, then return another creature card from your graveyard to your hand.
|
Oracle:As an additional cost to cast this spell, sacrifice a creature.\nReturn a creature card from your graveyard to the battlefield, then return another creature card from your graveyard to your hand.
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ SVar:TrigToken:AB$ Token | Cost$ 1 ExileAnyGrave<1/Card.TriggeredNewCard> | Toke
|
|||||||
SVar:DBAnimate:DB$ Animate | Defined$ Imprinted | Duration$ Permanent | Triggers$ CDTrigger
|
SVar:DBAnimate:DB$ Animate | Defined$ Imprinted | Duration$ Permanent | Triggers$ CDTrigger
|
||||||
SVar:CDTrigger:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigSac | TriggerZones$ Battlefield | TriggerDescription$ When this creature deals combat damage to a player, sacrifice it and return the exiled card to the battlefield tapped.
|
SVar:CDTrigger:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigSac | TriggerZones$ Battlefield | TriggerDescription$ When this creature deals combat damage to a player, sacrifice it and return the exiled card to the battlefield tapped.
|
||||||
SVar:TrigSac:DB$ Sacrifice | SubAbility$ DBReturn
|
SVar:TrigSac:DB$ Sacrifice | SubAbility$ DBReturn
|
||||||
SVar:DBReturn:DB$ ChangeZone | Defined$ Remembered | Origin$ Exile | Destination$ Battlefield | Tapped$ True
|
SVar:DBReturn:DB$ ChangeZone | Defined$ Remembered | Origin$ Exile | Destination$ Battlefield | Tapped$ True | GainControl$ True
|
||||||
DeckNeeds:Type$Vampire
|
DeckNeeds:Type$Vampire
|
||||||
DeckHas:Ability$Token|Sacrifice
|
DeckHas:Ability$Token|Sacrifice
|
||||||
Oracle:Ward—Discard a card.\nWhenever another nontoken Vampire you control dies, you may pay {1} and exile it. If you do, create a 1/1 black Bat creature token with flying. It gains "When this creature deals combat damage to a player, sacrifice it and return the exiled card to the battlefield tapped."
|
Oracle:Ward—Discard a card.\nWhenever another nontoken Vampire you control dies, you may pay {1} and exile it. If you do, create a 1/1 black Bat creature token with flying. It gains "When this creature deals combat damage to a player, sacrifice it and return the exiled card to the battlefield tapped."
|
||||||
|
|||||||
Reference in New Issue
Block a user