- 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/SpellAiLogic.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/AlwaysPlayAi.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/UntapAllAi.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/AnimateAllEffect.java -text
src/main/java/forge/card/abilityfactory/effects/AnimateEffect.java -text

View File

@@ -1,8 +1,11 @@
Name:Finest Hour
ManaCost:2 G W U
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
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:Rarity:Rare
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 {
Abandon (AbandonEffect.class, AlwaysPlayAi.class),
AddPhase (AddPhaseEffect.class, AddPhaseAi.class),
AddTurn (AddTurnEffect.class, AddTurnAi.class),
Animate (AnimateEffect.class, AnimateAi.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.spellability.Ability;
import forge.card.spellability.SpellAbility;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType;
import forge.game.zone.ZoneType;
import forge.util.Expressions;
@@ -227,20 +228,27 @@ public abstract class Trigger extends TriggerReplacementBase {
* @return a boolean.
*/
public final boolean phasesCheck() {
PhaseHandler phaseHandler = Singletons.getModel().getGame().getPhaseHandler();
if (null != validPhases) {
if (!validPhases.contains(Singletons.getModel().getGame().getPhaseHandler().getPhase())) {
if (!validPhases.contains(phaseHandler.getPhase())) {
return false;
}
}
if (this.getMapParams().containsKey("PlayerTurn")) {
if (!Singletons.getModel().getGame().getPhaseHandler().isPlayerTurn(this.getHostCard().getController())) {
if (!phaseHandler.isPlayerTurn(this.getHostCard().getController())) {
return false;
}
}
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;
}
}

View File

@@ -3092,41 +3092,6 @@ public class CombatUtil {
}
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) {
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.List;
import java.util.Map;
import java.util.Stack;
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
private final transient Stack<ExtraTurn> extraTurns = new Stack<ExtraTurn>();
private int extraCombats = 0;
private final transient Map<PhaseType, Stack<PhaseType>> extraPhases = new HashMap<PhaseType, Stack<PhaseType>>();
private int nCombatsThisTurn = 0;
private boolean bPreventCombatDamageThisTurn = false;
@@ -465,17 +465,6 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
this.resetAttackedThisCombat(this.getPlayerTurn());
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;
case CLEANUP:
@@ -489,13 +478,29 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
default: // no action
}
StringBuilder sb = new StringBuilder();
if (this.bRepeat) { // for when Cleanup needs to repeat itself
this.bRepeat = false;
sb.append("Repeat Phase");
} else {
this.phase = phase.getNextPhase();
// 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 {
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
// this to handleBeginPhase
@@ -659,15 +664,20 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
return this.extraTurns.push(new ExtraTurn(player));
}
/**
* <p>
* addExtraCombat.
* addExtraPhase.
* </p>
*
*/
public final void addExtraCombat() {
// Extra combats can only happen
this.extraCombats++;
public final void addExtraPhase(final PhaseType afterPhase, final PhaseType extraPhase) {
// 300.7. Some effects can add phases to a turn. They do this by adding the phases directly after the specified phase.
// 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
*/
public PhaseType getNextPhase() {