mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 12:18:00 +00:00
Re-implement skip turn using replacement effect
This commit is contained in:
@@ -61,6 +61,7 @@ public enum AbilityKey {
|
||||
EffectOnly("EffectOnly"),
|
||||
Exploited("Exploited"),
|
||||
Explorer("Explorer"),
|
||||
ExtraTurn("ExtraTurn"),
|
||||
Event("Event"),
|
||||
Fighter("Fighter"),
|
||||
Fighters("Fighters"),
|
||||
|
||||
@@ -1,9 +1,19 @@
|
||||
package forge.game.ability.effects;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityFactory;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.SpellAbilityEffect;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.replacement.ReplacementEffect;
|
||||
import forge.game.replacement.ReplacementHandler;
|
||||
import forge.game.replacement.ReplacementLayer;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.trigger.TriggerType;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.Lang;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -25,12 +35,33 @@ public class SkipTurnEffect extends SpellAbilityEffect {
|
||||
|
||||
@Override
|
||||
public void resolve(SpellAbility sa) {
|
||||
final Card hostCard = sa.getHostCard();
|
||||
final Game game = hostCard.getGame();
|
||||
final String name = hostCard.getName() + "'s Effect";
|
||||
final String image = hostCard.getImageKey();
|
||||
final int numTurns = AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("NumTurns"), sa);
|
||||
String repeffstr = "Event$ BeginTurn | ActiveZones$ Command | ValidPlayer$ You " +
|
||||
"| Description$ Skip your next " + (numTurns > 1 ? Lang.getNumeral(numTurns) + " turns." : "turn.");
|
||||
String effect = "DB$ StoreSVar | SVar$ NumTurns | Type$ CountSVar | Expression$ NumTurns/Minus.1";
|
||||
String exile = "DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile " +
|
||||
"| ConditionCheckSVar$ NumTurns | ConditionSVarCompare$ EQ0";
|
||||
|
||||
List<Player> tgtPlayers = getTargetPlayers(sa);
|
||||
for (final Player player : tgtPlayers) {
|
||||
for(int i = 0; i < numTurns; i++) {
|
||||
player.addKeyword("Skip your next turn.");
|
||||
}
|
||||
final Card eff = createEffect(sa, player, name, image);
|
||||
eff.setSVar("NumTurns", "Number$" + numTurns);
|
||||
SpellAbility calcTurn = AbilityFactory.getAbility(effect, eff);
|
||||
calcTurn.setSubAbility((AbilitySub) AbilityFactory.getAbility(exile, eff));
|
||||
|
||||
ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, eff, true);
|
||||
re.setLayer(ReplacementLayer.Other);
|
||||
re.setOverridingAbility(calcTurn);
|
||||
eff.addReplacementEffect(re);
|
||||
eff.updateStateForView();
|
||||
|
||||
game.getTriggerHandler().suppressMode(TriggerType.ChangesZone);
|
||||
game.getAction().moveTo(ZoneType.Command, eff, sa);
|
||||
game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,8 +36,9 @@ import forge.game.cost.Cost;
|
||||
import forge.game.event.*;
|
||||
import forge.game.keyword.Keyword;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerController.BinaryChoiceType;
|
||||
import forge.game.player.PlayerController.ManaPaymentPurpose;
|
||||
import forge.game.replacement.ReplacementResult;
|
||||
import forge.game.replacement.ReplacementType;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.LandAbility;
|
||||
import forge.game.staticability.StaticAbility;
|
||||
@@ -837,55 +838,28 @@ public class PhaseHandler implements java.io.Serializable {
|
||||
private Player getNextActivePlayer() {
|
||||
ExtraTurn extraTurn = !extraTurns.isEmpty() ? extraTurns.pop() : null;
|
||||
Player nextPlayer = extraTurn != null ? extraTurn.getPlayer() : game.getNextPlayerAfter(playerTurn);
|
||||
// The bottom of the extra turn stack is the normal turn
|
||||
boolean isExtraTurn = !extraTurns.isEmpty();
|
||||
|
||||
// update ExtraTurn Count for all players
|
||||
for (final Player p : game.getPlayers()) {
|
||||
p.setExtraTurnCount(getExtraTurnForPlayer(p));
|
||||
}
|
||||
// update ExtraTurn Count
|
||||
nextPlayer.setExtraTurnCount(getExtraTurnForPlayer(nextPlayer));
|
||||
|
||||
if (extraTurn != null) {
|
||||
// The bottom of the extra turn stack is the normal turn
|
||||
nextPlayer.setExtraTurn(!extraTurns.isEmpty());
|
||||
if (nextPlayer.hasKeyword("If you would begin an extra turn, skip that turn instead.")) {
|
||||
return getNextActivePlayer();
|
||||
}
|
||||
for (Trigger deltrig : extraTurn.getDelayedTriggers()) {
|
||||
game.getTriggerHandler().registerThisTurnDelayedTrigger(deltrig);
|
||||
}
|
||||
}
|
||||
else {
|
||||
nextPlayer.setExtraTurn(false);
|
||||
}
|
||||
|
||||
if (nextPlayer.hasKeyword("Skip your next turn.")) {
|
||||
nextPlayer.removeKeyword("Skip your next turn.", false);
|
||||
// Replacement effects
|
||||
final Map<AbilityKey, Object> repRunParams = AbilityKey.mapFromAffected(nextPlayer);
|
||||
repRunParams.put(AbilityKey.ExtraTurn, isExtraTurn);
|
||||
ReplacementResult repres = game.getReplacementHandler().run(ReplacementType.BeginTurn, repRunParams);
|
||||
if (repres != ReplacementResult.NotReplaced) {
|
||||
if (extraTurn == null) {
|
||||
setPlayerTurn(nextPlayer);
|
||||
}
|
||||
return getNextActivePlayer();
|
||||
}
|
||||
|
||||
// TODO: This shouldn't filter by Time Vault, just in case Time Vault doesn't have it's normal ability.
|
||||
CardCollection vaults = CardLists.filter(nextPlayer.getCardsIn(ZoneType.Battlefield, "Time Vault"), Presets.TAPPED);
|
||||
if (!vaults.isEmpty()) {
|
||||
Card crd = vaults.getFirst();
|
||||
SpellAbility fakeSA = new SpellAbility.EmptySa(crd, nextPlayer);
|
||||
boolean untapTimeVault = nextPlayer.getController().chooseBinary(fakeSA, "Skip a turn to untap a Time Vault?", BinaryChoiceType.UntapTimeVault, false);
|
||||
if (untapTimeVault) {
|
||||
if (vaults.size() > 1) {
|
||||
Card c = nextPlayer.getController().chooseSingleEntityForEffect(vaults, fakeSA, "Which Time Vault do you want to Untap?", null);
|
||||
if (c != null)
|
||||
crd = c;
|
||||
}
|
||||
crd.untap();
|
||||
if (extraTurn == null) {
|
||||
setPlayerTurn(nextPlayer);
|
||||
}
|
||||
return getNextActivePlayer();
|
||||
}
|
||||
}
|
||||
|
||||
nextPlayer.setExtraTurn(isExtraTurn);
|
||||
if (extraTurn != null) {
|
||||
for (Trigger deltrig : extraTurn.getDelayedTriggers()) {
|
||||
game.getTriggerHandler().registerThisTurnDelayedTrigger(deltrig);
|
||||
}
|
||||
if (extraTurn.isSkipUntap()) {
|
||||
nextPlayer.addKeyword("Skip the untap step of this turn.");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package forge.game.replacement;
|
||||
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class ReplaceBeginTurn extends ReplacementEffect {
|
||||
|
||||
public ReplaceBeginTurn(final Map<String, String> mapParams, final Card host, final boolean intrinsic) {
|
||||
super(mapParams, host, intrinsic);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canReplace(Map<AbilityKey, Object> runParams) {
|
||||
if (hasParam("ValidPlayer")) {
|
||||
if (!matchesValid(runParams.get(AbilityKey.Affected), getParam("ValidPlayer").split(","), getHostCard())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (hasParam("ExtraTurn")) {
|
||||
if (!(boolean) runParams.get(AbilityKey.ExtraTurn)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReplacingObjects(Map<AbilityKey, Object> runParams, SpellAbility sa) {
|
||||
sa.setReplacingObject(AbilityKey.Player, runParams.get(AbilityKey.Affected));
|
||||
}
|
||||
}
|
||||
@@ -349,6 +349,12 @@ public class ReplacementHandler {
|
||||
}
|
||||
}
|
||||
|
||||
if (mapParams.containsKey("Skip")) {
|
||||
if (mapParams.get("Skip").equals("True")) {
|
||||
return ReplacementResult.Skipped; // Event is skipped.
|
||||
}
|
||||
}
|
||||
|
||||
Player player = host.getController();
|
||||
|
||||
player.getController().playSpellAbilityNoStack(effectSA, true);
|
||||
|
||||
@@ -8,5 +8,6 @@ public enum ReplacementResult {
|
||||
Replaced,
|
||||
NotReplaced,
|
||||
Prevented,
|
||||
Updated
|
||||
Updated,
|
||||
Skipped
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ public enum ReplacementType {
|
||||
AddCounter(ReplaceAddCounter.class),
|
||||
AssignDealDamage(ReplaceAssignDealDamage.class),
|
||||
Attached(ReplaceAttached.class),
|
||||
BeginTurn(ReplaceBeginTurn.class),
|
||||
Counter(ReplaceCounter.class),
|
||||
CopySpell(ReplaceCopySpell.class),
|
||||
CreateToken(ReplaceToken.class),
|
||||
|
||||
Reference in New Issue
Block a user