- Added very basic AddPhase AF

- Added support in PhaseHandler for Additional phases
- Convert Finest Hour to AddPhase
This commit is contained in:
Sol
2012-12-26 04:31:43 +00:00
parent ee98b3d0eb
commit bf898ddefb
9 changed files with 98 additions and 60 deletions

2
.gitattributes vendored
View File

@@ -12918,6 +12918,7 @@ src/main/java/forge/card/abilityfactory/CommonDrawback.java svneol=native#text/p
src/main/java/forge/card/abilityfactory/CommonSpell.java -text src/main/java/forge/card/abilityfactory/CommonSpell.java -text
src/main/java/forge/card/abilityfactory/SpellAiLogic.java -text src/main/java/forge/card/abilityfactory/SpellAiLogic.java -text
src/main/java/forge/card/abilityfactory/SpellEffect.java -text src/main/java/forge/card/abilityfactory/SpellEffect.java -text
src/main/java/forge/card/abilityfactory/ai/AddPhaseAi.java -text
src/main/java/forge/card/abilityfactory/ai/AddTurnAi.java svneol=native#text/plain src/main/java/forge/card/abilityfactory/ai/AddTurnAi.java svneol=native#text/plain
src/main/java/forge/card/abilityfactory/ai/AlwaysPlayAi.java -text src/main/java/forge/card/abilityfactory/ai/AlwaysPlayAi.java -text
src/main/java/forge/card/abilityfactory/ai/AnimateAi.java -text src/main/java/forge/card/abilityfactory/ai/AnimateAi.java -text
@@ -13013,6 +13014,7 @@ src/main/java/forge/card/abilityfactory/ai/UnattachAllAi.java -text
src/main/java/forge/card/abilityfactory/ai/UntapAi.java -text src/main/java/forge/card/abilityfactory/ai/UntapAi.java -text
src/main/java/forge/card/abilityfactory/ai/UntapAllAi.java -text src/main/java/forge/card/abilityfactory/ai/UntapAllAi.java -text
src/main/java/forge/card/abilityfactory/effects/AbandonEffect.java -text src/main/java/forge/card/abilityfactory/effects/AbandonEffect.java -text
src/main/java/forge/card/abilityfactory/effects/AddPhaseEffect.java -text
src/main/java/forge/card/abilityfactory/effects/AddTurnEffect.java -text src/main/java/forge/card/abilityfactory/effects/AddTurnEffect.java -text
src/main/java/forge/card/abilityfactory/effects/AnimateAllEffect.java -text src/main/java/forge/card/abilityfactory/effects/AnimateAllEffect.java -text
src/main/java/forge/card/abilityfactory/effects/AnimateEffect.java -text src/main/java/forge/card/abilityfactory/effects/AnimateEffect.java -text

View File

@@ -1,8 +1,11 @@
Name:Finest Hour Name:Finest Hour
ManaCost:2 G W U ManaCost:2 G W U
Types:Enchantment Types:Enchantment
Text:Whenever a creature you control attacks alone, if it's the first combat phase of the turn, untap that creature. After this phase, there is an additional combat phase. Text:no text
K:Exalted K:Exalted
T:Mode$ Attacks | ValidCard$ Creature.YouCtrl | Alone$ True | TriggerZones$ Battlefield | Execute$ TrigUntap | FirstCombat$ True | TriggerDescription$ Whenever a creature you control attacks alone, if it's the first combat phase of the turn, untap that creature. After this phase, there is an additional combat phase.
SVar:TrigUntap:DB$ Untap | Defined$ TriggeredAttacker | SubAbility$ DBAddCombat
SVar:DBAddCombat:DB$ AddPhase | ExtraPhase$ BeginCombat | AfterPhase$ EndCombat
SVar:PlayMain1:TRUE SVar:PlayMain1:TRUE
SVar:Rarity:Rare SVar:Rarity:Rare
SVar:Picture:http://www.wizards.com/global/images/magic/general/finest_hour.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/finest_hour.jpg

View File

@@ -11,6 +11,7 @@ import forge.card.abilityfactory.effects.*;
public enum ApiType { public enum ApiType {
Abandon (AbandonEffect.class, AlwaysPlayAi.class), Abandon (AbandonEffect.class, AlwaysPlayAi.class),
AddPhase (AddPhaseEffect.class, AddPhaseAi.class),
AddTurn (AddTurnEffect.class, AddTurnAi.class), AddTurn (AddTurnEffect.class, AddTurnAi.class),
Animate (AnimateEffect.class, AnimateAi.class), Animate (AnimateEffect.class, AnimateAi.class),
AnimateAll (AnimateAllEffect.class, AnimateAllAi.class), AnimateAll (AnimateAllEffect.class, AnimateAllAi.class),

View File

@@ -0,0 +1,18 @@
package forge.card.abilityfactory.ai;
import forge.card.abilityfactory.SpellAiLogic;
import forge.card.spellability.SpellAbility;
import forge.game.player.Player;
/**
* TODO: Write javadoc for this type.
*
*/
public class AddPhaseAi extends SpellAiLogic {
@Override
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
return false;
}
}

View File

@@ -0,0 +1,31 @@
package forge.card.abilityfactory.effects;
import forge.Singletons;
import forge.card.abilityfactory.SpellEffect;
import forge.card.spellability.SpellAbility;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType;
/**
* TODO: Write javadoc for this type.
*
*/
public class AddPhaseEffect extends SpellEffect {
@Override
public void resolve(SpellAbility sa) {
PhaseHandler phaseHandler = Singletons.getModel().getGame().getPhaseHandler();
PhaseType extra = PhaseType.smartValueOf(sa.getParam("ExtraPhase"));
PhaseType after;
if (sa.hasParam("AfterPhase")) {
after = PhaseType.smartValueOf(sa.getParam("AfterPhase"));
}
else {
after = phaseHandler.getPhase();
}
phaseHandler.addExtraPhase(after, extra);
}
}

View File

@@ -32,6 +32,7 @@ import forge.card.abilityfactory.AbilityFactory;
import forge.card.cardfactory.CardFactoryUtil; import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.Ability; import forge.card.spellability.Ability;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.util.Expressions; import forge.util.Expressions;
@@ -227,20 +228,27 @@ public abstract class Trigger extends TriggerReplacementBase {
* @return a boolean. * @return a boolean.
*/ */
public final boolean phasesCheck() { public final boolean phasesCheck() {
PhaseHandler phaseHandler = Singletons.getModel().getGame().getPhaseHandler();
if (null != validPhases) { if (null != validPhases) {
if (!validPhases.contains(Singletons.getModel().getGame().getPhaseHandler().getPhase())) { if (!validPhases.contains(phaseHandler.getPhase())) {
return false; return false;
} }
} }
if (this.getMapParams().containsKey("PlayerTurn")) { if (this.getMapParams().containsKey("PlayerTurn")) {
if (!Singletons.getModel().getGame().getPhaseHandler().isPlayerTurn(this.getHostCard().getController())) { if (!phaseHandler.isPlayerTurn(this.getHostCard().getController())) {
return false; return false;
} }
} }
if (this.getMapParams().containsKey("OpponentTurn")) { if (this.getMapParams().containsKey("OpponentTurn")) {
if (Singletons.getModel().getGame().getPhaseHandler().isPlayerTurn(this.getHostCard().getController())) { if (phaseHandler.isPlayerTurn(this.getHostCard().getController())) {
return false;
}
}
if (this.getMapParams().containsKey("FirstCombat")) {
if (!phaseHandler.isFirstCombat()) {
return false; return false;
} }
} }

View File

@@ -3092,41 +3092,6 @@ public class CombatUtil {
} }
final Player phasingPlayer = c.getController(); final Player phasingPlayer = c.getController();
// Finest Hour untaps the creature on the first combat phase
if ((phasingPlayer.getCardsIn(ZoneType.Battlefield, "Finest Hour").size() > 0)
&& Singletons.getModel().getGame().getPhaseHandler().isFirstCombat()) {
// Untap the attacking creature
final Ability fhUntap = new Ability(c, "0") {
@Override
public void resolve() {
crd.untap();
}
};
final StringBuilder sbUntap = new StringBuilder();
sbUntap.append(c).append(" - (Finest Hour) untap.");
fhUntap.setDescription(sbUntap.toString());
fhUntap.setStackDescription(sbUntap.toString());
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(fhUntap);
// If any Finest Hours, queue up a new combat phase
for (int ix = 0; ix < phasingPlayer.getCardsIn(ZoneType.Battlefield, "Finest Hour").size(); ix++) {
final Ability fhAddCombat = new Ability(c, "0") {
@Override
public void resolve() {
Singletons.getModel().getGame().getPhaseHandler().addExtraCombat();
}
};
final StringBuilder sbACom = new StringBuilder();
sbACom.append(c).append(" - (Finest Hour) ").append(phasingPlayer).append(" gets Extra Combat Phase.");
fhAddCombat.setDescription(sbACom.toString());
fhAddCombat.setStackDescription(sbACom.toString());
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(fhAddCombat);
}
}
if (phasingPlayer.getCardsIn(ZoneType.Battlefield, "Sovereigns of Lost Alara").size() > 0) { if (phasingPlayer.getCardsIn(ZoneType.Battlefield, "Sovereigns of Lost Alara").size() > 0) {
for (int i = 0; i < phasingPlayer.getCardsIn(ZoneType.Battlefield, "Sovereigns of Lost Alara").size(); i++) { for (int i = 0; i < phasingPlayer.getCardsIn(ZoneType.Battlefield, "Sovereigns of Lost Alara").size(); i++) {

View File

@@ -19,6 +19,7 @@ package forge.game.phase;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Stack; import java.util.Stack;
import com.esotericsoftware.minlog.Log; import com.esotericsoftware.minlog.Log;
@@ -59,8 +60,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
// Start turn at 0, so first untap step will turn it to 1 // Start turn at 0, so first untap step will turn it to 1
private final transient Stack<ExtraTurn> extraTurns = new Stack<ExtraTurn>(); private final transient Stack<ExtraTurn> extraTurns = new Stack<ExtraTurn>();
private final transient Map<PhaseType, Stack<PhaseType>> extraPhases = new HashMap<PhaseType, Stack<PhaseType>>();
private int extraCombats = 0;
private int nCombatsThisTurn = 0; private int nCombatsThisTurn = 0;
private boolean bPreventCombatDamageThisTurn = false; private boolean bPreventCombatDamageThisTurn = false;
@@ -465,17 +465,6 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
this.resetAttackedThisCombat(this.getPlayerTurn()); this.resetAttackedThisCombat(this.getPlayerTurn());
this.bCombat = false; this.bCombat = false;
// TODO: ExtraCombat needs to be changed for other spell/abilities
// that give extra combat can do it like ExtraTurn stack ExtraPhases
if (this.extraCombats > 0) {
final Player player = this.getPlayerTurn();
this.bCombat = true;
this.extraCombats--;
game.getCombat().reset();
game.getCombat().setAttackingPlayer(player);
this.phase = PhaseType.COMBAT_BEGIN;
}
break; break;
case CLEANUP: case CLEANUP:
@@ -489,13 +478,29 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
default: // no action default: // no action
} }
StringBuilder sb = new StringBuilder();
if (this.bRepeat) { // for when Cleanup needs to repeat itself if (this.bRepeat) { // for when Cleanup needs to repeat itself
this.bRepeat = false; this.bRepeat = false;
sb.append("Repeat Phase");
} else {
// If the phase that's ending has a stack of additional phases
// Take the LIFO one and move to that instead of the normal one
if (this.extraPhases.containsKey(phase)) {
PhaseType nextPhase = this.extraPhases.get(phase).pop();
// If no more additional phases are available, remove it from the map
// and let the next add, reput the key
if (this.extraPhases.get(phase).isEmpty()) {
this.extraPhases.remove(phase);
}
this.phase = nextPhase;
sb.append("Additional Phase");
} else { } else {
this.phase = phase.getNextPhase(); this.phase = phase.getNextPhase();
sb.append("Phase");
}
} }
game.getGameLog().add("Phase", this.getPlayerTurn() + " " + this.getPhase().Name, 6); game.getGameLog().add(sb.toString(), this.getPlayerTurn() + " " + this.getPhase().Name, 6);
// **** Anything BELOW Here is actually in the next phase. Maybe move // **** Anything BELOW Here is actually in the next phase. Maybe move
// this to handleBeginPhase // this to handleBeginPhase
@@ -659,15 +664,20 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
return this.extraTurns.push(new ExtraTurn(player)); return this.extraTurns.push(new ExtraTurn(player));
} }
/** /**
* <p> * <p>
* addExtraCombat. * addExtraPhase.
* </p> * </p>
*
*/ */
public final void addExtraCombat() { public final void addExtraPhase(final PhaseType afterPhase, final PhaseType extraPhase) {
// Extra combats can only happen // 300.7. Some effects can add phases to a turn. They do this by adding the phases directly after the specified phase.
this.extraCombats++; // If multiple extra phases are created after the same phase, the most recently created phase will occur first.
if (!this.extraPhases.containsKey(afterPhase)) {
this.extraPhases.put(afterPhase, new Stack<PhaseType>());
}
this.extraPhases.get(afterPhase).push(extraPhase);
} }
/** /**

View File

@@ -105,7 +105,7 @@ public enum PhaseType {
} }
/** /**
* TODO: Write javadoc for this method. * Get the next PhaseType in turn order.
* @return * @return
*/ */
public PhaseType getNextPhase() { public PhaseType getNextPhase() {