mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 12:18:00 +00:00
@@ -3580,6 +3580,18 @@ public class AbilityUtils {
|
||||
}
|
||||
return doXMath(amount, m, source, ctb);
|
||||
}
|
||||
if (value.startsWith("PlaneswalkedToThisTurn")) {
|
||||
int found = 0;
|
||||
String name = value.split(" ")[1];
|
||||
List<Card> pwTo = player.getPlaneswalkedToThisTurn();
|
||||
for (Card c : pwTo) {
|
||||
if (c.getName().equals(name)) {
|
||||
found++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return doXMath(found, m, source, ctb);
|
||||
}
|
||||
|
||||
return doXMath(0, m, source, ctb);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ public enum ApiType {
|
||||
BecomeMonarch (BecomeMonarchEffect.class),
|
||||
BecomesBlocked (BecomesBlockedEffect.class),
|
||||
BidLife (BidLifeEffect.class),
|
||||
BlankLine (BlankLineEffect.class),
|
||||
Block (BlockEffect.class),
|
||||
Bond (BondEffect.class),
|
||||
Branch (BranchEffect.class),
|
||||
@@ -37,6 +38,7 @@ public enum ApiType {
|
||||
ChangeX (ChangeXEffect.class),
|
||||
ChangeZone (ChangeZoneEffect.class),
|
||||
ChangeZoneAll (ChangeZoneAllEffect.class),
|
||||
ChaosEnsues (ChaosEnsuesEffect.class),
|
||||
Charm (CharmEffect.class),
|
||||
ChooseCard (ChooseCardEffect.class),
|
||||
ChooseColor (ChooseColorEffect.class),
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package forge.game.ability.effects;
|
||||
|
||||
import forge.game.ability.SpellAbilityEffect;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
|
||||
public class BlankLineEffect extends SpellAbilityEffect {
|
||||
@Override
|
||||
protected String getStackDescription(SpellAbility sa) {
|
||||
return "\r\n";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolve(SpellAbility sa) {
|
||||
// this "effect" just allows spacing to look better for certain card displays
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package forge.game.ability.effects;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.SpellAbilityEffect;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.trigger.Trigger;
|
||||
import forge.game.trigger.TriggerType;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class ChaosEnsuesEffect extends SpellAbilityEffect {
|
||||
/** 311.7. Each plane card has a triggered ability that triggers “Whenever chaos ensues.” These are called
|
||||
chaos abilities. Each one is indicated by a chaos symbol to the left of the ability, though the symbol
|
||||
itself has no special rules meaning. This ability triggers if the chaos symbol is rolled on the planar
|
||||
die (see rule 901.9b), if a resolving spell or ability says that chaos ensues, or if a resolving spell or
|
||||
ability states that chaos ensues for a particular object. In the last case, the chaos ability can trigger
|
||||
even if that plane card is still in the planar deck but revealed. A chaos ability is controlled by the
|
||||
current planar controller. **/
|
||||
|
||||
@Override
|
||||
public void resolve(SpellAbility sa) {
|
||||
final Card host = sa.getHostCard();
|
||||
final Player activator = sa.getActivatingPlayer();
|
||||
final Game game = activator.getGame();
|
||||
|
||||
if (game.getActivePlanes() == null) { // not a planechase game, nothing happens
|
||||
return;
|
||||
}
|
||||
|
||||
Map<AbilityKey, Object> runParams = AbilityKey.mapFromPlayer(activator);
|
||||
Map<Integer, EnumSet<ZoneType>> tweakedTrigs = new HashMap<>();
|
||||
|
||||
List<Card> affected = Lists.newArrayList();
|
||||
if (sa.hasParam("Defined")) {
|
||||
for (final Card c : AbilityUtils.getDefinedCards(host, sa.getParam("Defined"), sa)) {
|
||||
for (Trigger t : c.getTriggers()) {
|
||||
if (t.getMode() == TriggerType.ChaosEnsues) { // also allow current zone for any Defined
|
||||
//String zones = t.getParam("TriggerZones");
|
||||
//t.putParam("TriggerZones", zones + "," + c.getZone().getZoneType().toString());
|
||||
EnumSet<ZoneType> zones = (EnumSet<ZoneType>) t.getActiveZone();
|
||||
tweakedTrigs.put(t.getId(), zones);
|
||||
zones.add(c.getZone().getZoneType());
|
||||
t.setActiveZone(zones);
|
||||
affected.add(c);
|
||||
game.getTriggerHandler().registerOneTrigger(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
runParams.put(AbilityKey.Affected, affected);
|
||||
if (affected.isEmpty()) { // if no Defined has chaos ability, don't trigger non Defined
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
game.getTriggerHandler().runTrigger(TriggerType.ChaosEnsues, runParams,false);
|
||||
|
||||
for (Map.Entry<Integer, EnumSet<ZoneType>> e : tweakedTrigs.entrySet()) {
|
||||
for (Card c : affected) {
|
||||
for (Trigger t : c.getTriggers()) {
|
||||
if (t.getId() == e.getKey()) {
|
||||
EnumSet<ZoneType> zones = e.getValue();
|
||||
t.setActiveZone(zones);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,8 +13,14 @@ public class PlaneswalkEffect extends SpellAbilityEffect {
|
||||
public void resolve(SpellAbility sa) {
|
||||
Game game = sa.getActivatingPlayer().getGame();
|
||||
|
||||
for (Player p : game.getPlayers()) {
|
||||
p.leaveCurrentPlane();
|
||||
if (game.getActivePlanes() == null) { // not a planechase game, nothing happens
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sa.hasParam("DontPlaneswalkAway")) {
|
||||
for (Player p : game.getPlayers()) {
|
||||
p.leaveCurrentPlane();
|
||||
}
|
||||
}
|
||||
if (sa.hasParam("Defined")) {
|
||||
CardCollectionView destinations = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("Defined"), sa);
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
package forge.game.ability.effects;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.game.PlanarDice;
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.SpellAbilityEffect;
|
||||
import forge.game.card.Card;
|
||||
@@ -16,17 +10,17 @@ import forge.game.trigger.Trigger;
|
||||
import forge.game.trigger.TriggerType;
|
||||
import forge.game.trigger.WrappedAbility;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class RunChaosEffect extends SpellAbilityEffect {
|
||||
|
||||
@Override
|
||||
public void resolve(SpellAbility sa) {
|
||||
Map<AbilityKey, Object> map = AbilityKey.mapFromPlayer(sa.getActivatingPlayer());
|
||||
map.put(AbilityKey.Result, PlanarDice.Chaos);
|
||||
|
||||
List<SpellAbility> validSA = Lists.newArrayList();
|
||||
for (final Card c : getTargetCards(sa)) {
|
||||
for (Trigger t : c.getTriggers()) {
|
||||
if (TriggerType.PlanarDice.equals(t.getMode()) && t.performTest(map)) {
|
||||
if (t.getMode() == TriggerType.ChaosEnsues) {
|
||||
SpellAbility triggerSA = t.ensureAbility().copy(sa.getActivatingPlayer());
|
||||
|
||||
Player decider = sa.getActivatingPlayer();
|
||||
@@ -44,5 +38,4 @@ public class RunChaosEffect extends SpellAbilityEffect {
|
||||
}
|
||||
sa.getActivatingPlayer().getController().orderAndPlaySimultaneousSa(validSA);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import forge.util.Lang;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
@@ -35,13 +36,13 @@ public class VoteEffect extends SpellAbilityEffect {
|
||||
@Override
|
||||
protected String getStackDescription(final SpellAbility sa) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append(StringUtils.join(getDefinedPlayersOrTargeted(sa), ", "));
|
||||
sb.append(" vote ");
|
||||
sb.append(Lang.joinHomogenous(getDefinedPlayersOrTargeted(sa))).append(" vote ");
|
||||
if (sa.hasParam("VoteType")) {
|
||||
sb.append(StringUtils.join(sa.getParam("VoteType").split(","), " or "));
|
||||
sb.append("for ").append(StringUtils.join(sa.getParam("VoteType").split(","), " or "));
|
||||
} else if (sa.hasParam("VoteMessage")) {
|
||||
sb.append(sa.getParam("VoteMessage"));
|
||||
}
|
||||
sb.append(".");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
@@ -350,9 +350,17 @@ public class CardFactory {
|
||||
planesWalkTrigger.setOverridingAbility(AbilityFactory.getAbility(rolledWalk, card));
|
||||
card.addTrigger(planesWalkTrigger);
|
||||
|
||||
String chaosTrig = "Mode$ PlanarDice | Result$ Chaos | TriggerZones$ Command | Static$ True";
|
||||
|
||||
String rolledChaos = "DB$ ChaosEnsues";
|
||||
|
||||
Trigger chaosTrigger = TriggerHandler.parseTrigger(chaosTrig, card, true);
|
||||
chaosTrigger.setOverridingAbility(AbilityFactory.getAbility(rolledChaos, card));
|
||||
card.addTrigger(chaosTrigger);
|
||||
|
||||
String specialA = "ST$ RollPlanarDice | Cost$ X | SorcerySpeed$ True | Activator$ Player | SpecialAction$ True" +
|
||||
" | ActivationZone$ Command | SpellDescription$ Roll the planar dice. X is equal to the number of " +
|
||||
"times you have previously taken this action this turn.";
|
||||
"times you have previously taken this action this turn. | CostDesc$ {X}: ";
|
||||
|
||||
SpellAbility planarRoll = AbilityFactory.getAbility(specialA, card);
|
||||
planarRoll.setSVar("X", "Count$PlanarDiceSpecialActionThisTurn");
|
||||
|
||||
@@ -209,6 +209,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
private Map<Card, Card> maingameCardsMap = Maps.newHashMap();
|
||||
|
||||
private CardCollection currentPlanes = new CardCollection();
|
||||
private CardCollection planeswalkedToThisTurn = new CardCollection();
|
||||
|
||||
private PlayerStatistics stats = new PlayerStatistics();
|
||||
private PlayerController controller;
|
||||
@@ -1918,6 +1919,10 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
completedDungeons.clear();
|
||||
}
|
||||
|
||||
public final List<Card> getPlaneswalkedToThisTurn() {
|
||||
return planeswalkedToThisTurn;
|
||||
}
|
||||
|
||||
public final void altWinBySpellEffect(final String sourceName) {
|
||||
if (cantWin()) {
|
||||
System.out.println("Tried to win, but currently can't.");
|
||||
@@ -2458,6 +2463,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
setNumManaConversion(0);
|
||||
|
||||
damageReceivedThisTurn.clear();
|
||||
planeswalkedToThisTurn.clear();
|
||||
|
||||
// set last turn nr
|
||||
if (game.getPhaseHandler().isPlayerTurn(this)) {
|
||||
@@ -2617,7 +2623,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
* Then runs triggers.
|
||||
*/
|
||||
public void planeswalkTo(SpellAbility sa, final CardCollectionView destinations) {
|
||||
System.out.println(getName() + ": planeswalk to " + destinations.toString());
|
||||
System.out.println(getName() + " planeswalks to " + destinations.toString());
|
||||
currentPlanes.addAll(destinations);
|
||||
game.getView().updatePlanarPlayer(getView());
|
||||
|
||||
@@ -2625,8 +2631,9 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
moveParams.put(AbilityKey.LastStateBattlefield, sa.getLastStateBattlefield());
|
||||
moveParams.put(AbilityKey.LastStateGraveyard, sa.getLastStateGraveyard());
|
||||
|
||||
for (Card c : currentPlanes) {
|
||||
for (Card c : destinations) {
|
||||
game.getAction().moveTo(ZoneType.Command, c, sa, moveParams);
|
||||
planeswalkedToThisTurn.add(c);
|
||||
//getZone(ZoneType.PlanarDeck).remove(c);
|
||||
//getZone(ZoneType.Command).add(c);
|
||||
}
|
||||
@@ -2634,7 +2641,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
game.setActivePlanes(currentPlanes);
|
||||
//Run PlaneswalkedTo triggers here.
|
||||
final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
|
||||
runParams.put(AbilityKey.Cards, currentPlanes);
|
||||
runParams.put(AbilityKey.Cards, destinations);
|
||||
game.getTriggerHandler().runTrigger(TriggerType.PlaneswalkedTo, runParams, false);
|
||||
view.updateCurrentPlaneName(currentPlanes.toString().replaceAll(" \\(.*","").replace("[",""));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package forge.game.trigger;
|
||||
|
||||
import forge.game.GameObject;
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class TriggerChaosEnsues extends Trigger {
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Constructor for Trigger_ChaosEnsues
|
||||
* </p>
|
||||
*
|
||||
* @param params
|
||||
* a {@link java.util.HashMap} object.
|
||||
* @param host
|
||||
* a {@link forge.game.card.Card} object.
|
||||
* @param intrinsic
|
||||
* the intrinsic
|
||||
*/
|
||||
public TriggerChaosEnsues(final Map<String, String> params, final Card host, final boolean intrinsic) {
|
||||
super(params, host, intrinsic);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.trigger.Trigger#performTest(java.util.Map)
|
||||
*/
|
||||
@Override
|
||||
public boolean performTest(Map<AbilityKey, Object> runParams) {
|
||||
if (!matchesValidParam("ValidPlayer", runParams.get(AbilityKey.Player))) {
|
||||
return false;
|
||||
}
|
||||
if (runParams.containsKey(AbilityKey.Affected)) {
|
||||
final Object o = runParams.get(AbilityKey.Affected);
|
||||
if (o instanceof GameObject) {
|
||||
final GameObject c = (GameObject) o;
|
||||
if (!c.equals(this.getHostCard())) {
|
||||
return false;
|
||||
}
|
||||
} else if (o instanceof Iterable<?>) {
|
||||
for (Object o2 : (Iterable<?>) o) {
|
||||
if (!o2.equals(this.getHostCard())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTriggeringObjects(SpellAbility sa, Map<AbilityKey, Object> runParams) {
|
||||
sa.setTriggeringObjectsFrom(runParams, AbilityKey.Player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getImportantStackObjects(SpellAbility sa) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,7 @@ public enum TriggerType {
|
||||
ChangesController(TriggerChangesController.class),
|
||||
ChangesZone(TriggerChangesZone.class),
|
||||
ChangesZoneAll(TriggerChangesZoneAll.class),
|
||||
ChaosEnsues(TriggerChaosEnsues.class),
|
||||
Clashed(TriggerClashed.class),
|
||||
ClassLevelGained(TriggerClassLevelGained.class),
|
||||
ConjureAll(TriggerConjureAll.class),
|
||||
|
||||
Reference in New Issue
Block a user