mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 19:58:00 +00:00
Ranar v2
This commit is contained in:
committed by
Michael Kamensky
parent
8468c5ac52
commit
b33e262de6
@@ -1260,7 +1260,7 @@ public class GameAction {
|
||||
if (game.getCombat() != null) {
|
||||
game.getCombat().removeAbsentCombatants();
|
||||
}
|
||||
table.triggerChangesZoneAll(game);
|
||||
table.triggerChangesZoneAll(game, null);
|
||||
if (!checkAgain) {
|
||||
break; // do not continue the loop
|
||||
}
|
||||
|
||||
@@ -657,7 +657,7 @@ public abstract class SpellAbilityEffect {
|
||||
untilTable.put(cell.getColumnKey(), cell.getRowKey(), movedCard);
|
||||
}
|
||||
}
|
||||
untilTable.triggerChangesZoneAll(game);
|
||||
untilTable.triggerChangesZoneAll(game, null);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -74,7 +74,7 @@ public class AmassEffect extends TokenEffectBase {
|
||||
makeTokens(prototype, activator, sa, 1, true, false, triggerList, combatChanged);
|
||||
|
||||
if (!useZoneTable) {
|
||||
triggerList.triggerChangesZoneAll(game);
|
||||
triggerList.triggerChangesZoneAll(game, sa);
|
||||
triggerList.clear();
|
||||
}
|
||||
game.fireEvent(new GameEventTokenCreated());
|
||||
|
||||
@@ -43,7 +43,7 @@ public class AttachEffect extends SpellAbilityEffect {
|
||||
if (newZone != previousZone) {
|
||||
table.put(previousZone, newZone, c);
|
||||
}
|
||||
table.triggerChangesZoneAll(game);
|
||||
table.triggerChangesZoneAll(game, sa);
|
||||
}
|
||||
|
||||
final Card source = sa.getHostCard();
|
||||
|
||||
@@ -68,6 +68,6 @@ public class BalanceEffect extends SpellAbilityEffect {
|
||||
discard(sa, table, discardedMap);
|
||||
}
|
||||
|
||||
table.triggerChangesZoneAll(game);
|
||||
table.triggerChangesZoneAll(game, sa);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,7 +268,7 @@ public class ChangeZoneAllEffect extends SpellAbilityEffect {
|
||||
}
|
||||
}
|
||||
|
||||
triggerList.triggerChangesZoneAll(game);
|
||||
triggerList.triggerChangesZoneAll(game, sa);
|
||||
|
||||
if (sa.hasParam("UntilHostLeavesPlay")) {
|
||||
source.addLeavesPlayCommand(untilHostLeavesPlayCommand(triggerList, source));
|
||||
|
||||
@@ -811,7 +811,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
||||
game.getAction().reveal(commandCards, player, true, "Revealed cards in ");
|
||||
}
|
||||
|
||||
triggerList.triggerChangesZoneAll(game);
|
||||
triggerList.triggerChangesZoneAll(game, sa);
|
||||
counterTable.triggerCountersPutAll(game);
|
||||
|
||||
|
||||
@@ -1411,7 +1411,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
||||
game.updateCombatForView();
|
||||
game.fireEvent(new GameEventCombatChanged());
|
||||
}
|
||||
triggerList.triggerChangesZoneAll(game);
|
||||
triggerList.triggerChangesZoneAll(game, sa);
|
||||
|
||||
if (sa.hasParam("UntilHostLeavesPlay")) {
|
||||
source.addLeavesPlayCommand(untilHostLeavesPlayCommand(triggerList, source));
|
||||
|
||||
@@ -17,7 +17,7 @@ public class ChangeZoneResolveEffect extends SpellAbilityEffect {
|
||||
CardZoneTable table = sa.getChangeZoneTable();
|
||||
if (table != null) {
|
||||
|
||||
table.triggerChangesZoneAll(game);
|
||||
table.triggerChangesZoneAll(game, sa);
|
||||
table.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ public class CopyPermanentEffect extends TokenEffectBase {
|
||||
} // end foreach Card
|
||||
|
||||
if (!useZoneTable) {
|
||||
triggerList.triggerChangesZoneAll(game);
|
||||
triggerList.triggerChangesZoneAll(game, sa);
|
||||
triggerList.clear();
|
||||
}
|
||||
if (combatChanged.isTrue()) {
|
||||
|
||||
@@ -97,7 +97,7 @@ public class DestroyAllEffect extends SpellAbilityEffect {
|
||||
card.addRemembered(CardUtil.getLKICopy(c, cachedMap));
|
||||
}
|
||||
}
|
||||
table.triggerChangesZoneAll(game);
|
||||
table.triggerChangesZoneAll(game, sa);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ public class DestroyEffect extends SpellAbilityEffect {
|
||||
}
|
||||
}
|
||||
|
||||
table.triggerChangesZoneAll(game);
|
||||
table.triggerChangesZoneAll(game, sa);
|
||||
}
|
||||
|
||||
protected void internalDestroy(Card gameCard, SpellAbility sa, CardZoneTable table, Map<Integer, Card> cachedMap) {
|
||||
|
||||
@@ -406,7 +406,7 @@ public class DigEffect extends SpellAbilityEffect {
|
||||
game.fireEvent(new GameEventCombatChanged());
|
||||
}
|
||||
//table trigger there
|
||||
table.triggerChangesZoneAll(game);
|
||||
table.triggerChangesZoneAll(game, sa);
|
||||
counterTable.triggerCountersPutAll(game);
|
||||
}
|
||||
|
||||
|
||||
@@ -183,7 +183,7 @@ public class DigMultipleEffect extends SpellAbilityEffect {
|
||||
}
|
||||
}
|
||||
//table trigger there
|
||||
table.triggerChangesZoneAll(game);
|
||||
table.triggerChangesZoneAll(game, sa);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -260,7 +260,7 @@ public class DigUntilEffect extends SpellAbilityEffect {
|
||||
game.updateCombatForView();
|
||||
game.fireEvent(new GameEventCombatChanged());
|
||||
}
|
||||
table.triggerChangesZoneAll(game);
|
||||
table.triggerChangesZoneAll(game, sa);
|
||||
} // end resolve
|
||||
|
||||
}
|
||||
|
||||
@@ -292,6 +292,6 @@ public class DiscardEffect extends SpellAbilityEffect {
|
||||
discard(sa, table, discardedMap);
|
||||
|
||||
// run trigger if something got milled
|
||||
table.triggerChangesZoneAll(game);
|
||||
table.triggerChangesZoneAll(game, sa);
|
||||
} // discardResolve()
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ public class ExploreEffect extends SpellAbilityEffect {
|
||||
game.getTriggerHandler().runTrigger(TriggerType.Explores, AbilityKey.mapFromCard(c), false);
|
||||
}
|
||||
table.triggerCountersPutAll(game);
|
||||
triggerList.triggerChangesZoneAll(game);
|
||||
triggerList.triggerChangesZoneAll(game, sa);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ public class InvestigateEffect extends TokenEffectBase {
|
||||
MutableBoolean combatChanged = new MutableBoolean(false);
|
||||
makeTokens(prototype, p, sa, 1, true, false, triggerList, combatChanged);
|
||||
|
||||
triggerList.triggerChangesZoneAll(game);
|
||||
triggerList.triggerChangesZoneAll(game, sa);
|
||||
p.addInvestigatedThisTurn();
|
||||
|
||||
game.fireEvent(new GameEventTokenCreated());
|
||||
|
||||
@@ -21,7 +21,7 @@ public class LearnEffect extends SpellAbilityEffect {
|
||||
for (Player p : getTargetPlayers(sa)) {
|
||||
p.learnLesson(sa, table);
|
||||
}
|
||||
table.triggerChangesZoneAll(game);
|
||||
table.triggerChangesZoneAll(game, sa);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ public class MillEffect extends SpellAbilityEffect {
|
||||
}
|
||||
|
||||
// run trigger if something got milled
|
||||
table.triggerChangesZoneAll(game);
|
||||
table.triggerChangesZoneAll(game, sa);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -40,6 +40,6 @@ public class PermanentEffect extends SpellAbilityEffect {
|
||||
if (newZone != previousZone) {
|
||||
table.put(previousZone, newZone, c);
|
||||
}
|
||||
table.triggerChangesZoneAll(game);
|
||||
table.triggerChangesZoneAll(game, sa);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ public class RepeatEachEffect extends SpellAbilityEffect {
|
||||
sa.setDamageMap(null);
|
||||
}
|
||||
if (sa.hasParam("ChangeZoneTable")) {
|
||||
sa.getChangeZoneTable().triggerChangesZoneAll(game);
|
||||
sa.getChangeZoneTable().triggerChangesZoneAll(game, sa);
|
||||
sa.setChangeZoneTable(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ public class SacrificeAllEffect extends SpellAbilityEffect {
|
||||
}
|
||||
}
|
||||
}
|
||||
table.triggerChangesZoneAll(game);
|
||||
table.triggerChangesZoneAll(game, sa);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ public class SacrificeEffect extends SpellAbilityEffect {
|
||||
}
|
||||
}
|
||||
|
||||
table.triggerChangesZoneAll(game);
|
||||
table.triggerChangesZoneAll(game, sa);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -92,7 +92,7 @@ public class TokenEffect extends TokenEffectBase {
|
||||
}
|
||||
|
||||
if (!useZoneTable) {
|
||||
triggerList.triggerChangesZoneAll(game);
|
||||
triggerList.triggerChangesZoneAll(game, sa);
|
||||
triggerList.clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -5,14 +5,12 @@ package forge.game.card;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.ForwardingTable;
|
||||
import com.google.common.collect.HashBasedTable;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Table;
|
||||
import com.google.common.collect.*;
|
||||
|
||||
import forge.game.CardTraitBase;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.trigger.TriggerType;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
@@ -53,11 +51,12 @@ public class CardZoneTable extends ForwardingTable<ZoneType, ZoneType, CardColle
|
||||
return dataMap;
|
||||
}
|
||||
|
||||
public void triggerChangesZoneAll(final Game game) {
|
||||
public void triggerChangesZoneAll(final Game game, final SpellAbility cause) {
|
||||
if (!isEmpty()) {
|
||||
final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
|
||||
runParams.put(AbilityKey.Cards, new CardZoneTable(this));
|
||||
game.getTriggerHandler().runTrigger(TriggerType.ChangesZoneAll, runParams, false);
|
||||
runParams.put(AbilityKey.Cause, cause);
|
||||
game.getTriggerHandler().runTrigger(TriggerType.ChangesZoneAll, AbilityKey.newMap(runParams), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -237,7 +237,7 @@ public class CostAdjustment {
|
||||
table.put(ZoneType.Graveyard, d.getZone().getZoneType(), d);
|
||||
}
|
||||
}
|
||||
table.triggerChangesZoneAll(game);
|
||||
table.triggerChangesZoneAll(game, null);
|
||||
}
|
||||
if (sa.getHostCard().hasKeyword(Keyword.CONVOKE)) {
|
||||
adjustCostByConvokeOrImprovise(cost, sa, false, test);
|
||||
@@ -510,6 +510,13 @@ public class CostAdjustment {
|
||||
if (!sa.isPwAbility()) {
|
||||
return false;
|
||||
}
|
||||
} else if (type.equals("Foretell")) {
|
||||
if (!sa.isForetelling()) {
|
||||
return false;
|
||||
}
|
||||
if (st.hasParam("FirstForetell") && activator.getNumForetoldThisTurn() > 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (st.hasParam("AffectedZone")) {
|
||||
|
||||
@@ -101,7 +101,7 @@ public class CostMill extends CostPart {
|
||||
public final boolean payAsDecided(final Player ai, final PaymentDecision decision, SpellAbility ability) {
|
||||
CardZoneTable table = new CardZoneTable();
|
||||
ability.getPaidHash().put("Milled", (CardCollection) ai.mill(decision.c, ZoneType.Graveyard, false, ability, table));
|
||||
table.triggerChangesZoneAll(ai.getGame());
|
||||
table.triggerChangesZoneAll(ai.getGame(), null);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -64,8 +64,6 @@ public abstract class CostPartWithList extends CostPart {
|
||||
*
|
||||
* @param sa
|
||||
* the sa
|
||||
* @param hash
|
||||
* the hash
|
||||
*/
|
||||
public final void reportPaidCardsTo(final SpellAbility sa) {
|
||||
if (sa == null) {
|
||||
@@ -177,7 +175,7 @@ public abstract class CostPartWithList extends CostPart {
|
||||
// copy table because the original get cleaned after the cost is done
|
||||
final CardZoneTable copyTable = new CardZoneTable();
|
||||
copyTable.putAll(table);
|
||||
copyTable.triggerChangesZoneAll(payer.getGame());
|
||||
copyTable.triggerChangesZoneAll(payer.getGame(), null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -398,7 +398,7 @@ public class PhaseHandler implements java.io.Serializable {
|
||||
discarded.add(c);
|
||||
}
|
||||
}
|
||||
table.triggerChangesZoneAll(game);
|
||||
table.triggerChangesZoneAll(game, null);
|
||||
|
||||
if (!discarded.isEmpty()) {
|
||||
final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
|
||||
@@ -1068,7 +1068,7 @@ public class PhaseHandler implements java.io.Serializable {
|
||||
// currently there can be only one Spell put on the Stack at once, or Land Abilities be played
|
||||
final CardZoneTable triggerList = new CardZoneTable();
|
||||
triggerList.put(originZone.getZoneType(), currentZone.getZoneType(), saHost);
|
||||
triggerList.triggerChangesZoneAll(game);
|
||||
triggerList.triggerChangesZoneAll(game, null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1262,7 +1262,7 @@ public class PhaseHandler implements java.io.Serializable {
|
||||
|
||||
/**
|
||||
* returns the continuous extra turn count
|
||||
* @param PLayer p
|
||||
* @param p
|
||||
* @return int
|
||||
*/
|
||||
public int getExtraTurnForPlayer(final Player p) {
|
||||
|
||||
@@ -2599,6 +2599,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
resetPreventNextDamageWithEffect();
|
||||
resetNumDrawnThisTurn();
|
||||
resetNumDiscardedThisTurn();
|
||||
resetNumForetoldThisTurn();
|
||||
resetNumTokenCreatedThisTurn();
|
||||
setNumCardsInHandStartedThisTurnWith(getCardsIn(ZoneType.Hand).size());
|
||||
clearCreaturesAttackedThisTurn();
|
||||
|
||||
@@ -2003,6 +2003,9 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (incR[0].equals("SpellAbility")) {
|
||||
// Match anything
|
||||
}
|
||||
else { //not a spell/ability type
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,10 @@ public class TriggerChangesZoneAll extends Trigger {
|
||||
public boolean performTest(Map<AbilityKey, Object> runParams) {
|
||||
final CardZoneTable table = (CardZoneTable) runParams.get(AbilityKey.Cards);
|
||||
|
||||
if (!matchesValidParam("ValidCause", runParams.get(AbilityKey.Cause))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !filterCards(table).isEmpty();
|
||||
}
|
||||
|
||||
@@ -32,6 +36,7 @@ public class TriggerChangesZoneAll extends Trigger {
|
||||
|
||||
sa.setTriggeringObject(AbilityKey.Cards, allCards);
|
||||
sa.setTriggeringObject(AbilityKey.Amount, allCards.size());
|
||||
sa.setTriggeringObjectsFrom(runParams, AbilityKey.Cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
12
forge-gui/res/cardsfolder/h/hero_of_bretagard.txt
Normal file
12
forge-gui/res/cardsfolder/h/hero_of_bretagard.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
Name:Hero of Bretagard
|
||||
ManaCost:2 W
|
||||
Types:Creature Human Warrior
|
||||
PT:1/1
|
||||
T:Mode$ ChangesZoneAll | ValidCause$ SpellAbility.YouCtrl | Origin$ Hand,Battlefield | Destination$ Exile | ValidCards$ Card.YouOwn,Card.inZoneBattlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever a spell or ability you control exiles one or more cards from your hand and/or permanents from the battlefield, put that many +1/+1 counters on CARDNAME.
|
||||
SVar:TrigPutCounter:DB$PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ X
|
||||
S:Mode$ Continuous | Affected$ Card.Self | CheckSVar$ Y | SVarCompare$ GT4 | AddKeyword$ Flying | AddType$ Angel | Description$ As long as CARDNAME has five or more counters on it, it has flying and is an Angel in addition to its other types.
|
||||
S:Mode$ Continuous | Affected$ Card.Self | CheckSVar$ Y | SVarCompare$ GT9 | AddKeyword$ Indestructible | AddType$ Angel & God | Description$ As long as CARDNAME has ten or more counters on it, it indestructible and is a God in addition to its other types.
|
||||
SVar:X:TriggerCount$Amount
|
||||
SVar:Y:Count$CardCounters.ALL
|
||||
DeckHas:Ability$Counters
|
||||
Oracle:Whenever a spell or ability you control exiles one or more cards from your hand and/or permanents from the battlefield, put that many +1/+1 counters on Hero of Bretagard.\nAs long as Hero of Bretagard has five or more counters on it, it has flying and is an Angel in addition to its other types.\nAs long as Hero of Bretagard has ten or more counters on it, it has indestructible and is a God in addition to its other types.
|
||||
13
forge-gui/res/cardsfolder/l/laelia_the_blade_reforged.txt
Normal file
13
forge-gui/res/cardsfolder/l/laelia_the_blade_reforged.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
Name:Laelia, the Blade Reforged
|
||||
ManaCost:2 R
|
||||
Types:Legendary Creature Spirit Warrior
|
||||
PT:2/2
|
||||
K:Haste
|
||||
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigExile | TriggerDescription$ Whenever CARDNAME attacks, exile the top card of your library. You may play that card this turn.
|
||||
SVar:TrigExile:DB$ Dig | Defined$ You | DigNum$ 1 | ChangeNum$ All | DestinationZone$ Exile | RememberChanged$ True | SubAbility$ DBEffect
|
||||
SVar:DBEffect:DB$ Effect | StaticAbilities$ STPlay | RememberObjects$ Remembered | ForgetOnMoved$ Exile | SubAbility$ DBCleanup
|
||||
SVar:STPlay:Mode$ Continuous | MayPlay$ True | EffectZone$ Command | Affected$ Card.IsRemembered | AffectedZone$ Exile | Description$ You may play this card this turn.
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||
T:Mode$ ChangesZoneAll | ValidCause$ SpellAbility.YouCtrl | Origin$ Library,Graveyard | Destination$ Exile | ValidCards$ Card.YouOwn | Execute$ TrigPutCounter | TriggerDescription$ Whenever you exile one or more cards from your library and/or your graveyard, put a +1/+1 counter on NICKNAME.
|
||||
SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1
|
||||
Oracle:Haste\nWhenever Laelia, the Blade Reforged attacks, exile the top card of your library. You may play that card this turn.\nWhenever you exile one or more cards from your library and/or your graveyard, put a +1/+1 counter on Laelia.
|
||||
11
forge-gui/res/cardsfolder/r/ranar_the_ever_watchful.txt
Normal file
11
forge-gui/res/cardsfolder/r/ranar_the_ever_watchful.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
Name:Ranar the Ever-Watchful
|
||||
ManaCost:2 W U
|
||||
Types:Legendary Creature Spirit Warrior
|
||||
PT:2/3
|
||||
K:Flying
|
||||
K:Vigilance
|
||||
S:Mode$ ReduceCost | ValidCard$ Card | Type$ Foretell | Amount$ 2 | FirstForetell$ True | Activator$ You | Description$ The first card you foretell each turn costs {0} to foretell.
|
||||
T:Mode$ ChangesZoneAll | ValidCause$ SpellAbility.YouCtrl | Origin$ Hand,Battlefield | Destination$ Exile | ValidCards$ Card.YouOwn,Card.inZoneBattlefield | Execute$ TrigToken | TriggerDescription$ Whenever a spell or ability you control exiles one or more cards from your hand and/or permanents from the battlefield, create a 1/1 white Spirit creature token with flying.
|
||||
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ w_1_1_spirit_flying | TokenOwner$ You
|
||||
DeckHas:Ability$Token
|
||||
Oracle:Flying, vigilance\nThe first card you foretell each turn costs {0} to foretell.\nWhenever a spell or ability you control exiles one or more cards from your hand and/or permanents from the battlefield, create a 1/1 white Spirit creature token with flying.
|
||||
@@ -698,7 +698,7 @@ public class HumanPlay {
|
||||
ability.clearTappedForConvoke();
|
||||
}
|
||||
if (!table.isEmpty() && !manaInputCancelled) {
|
||||
table.triggerChangesZoneAll(game);
|
||||
table.triggerChangesZoneAll(game, null);
|
||||
}
|
||||
return !manaInputCancelled;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user