Events are fired when static abilities recalculate

This commit is contained in:
Maxmtg
2013-07-05 15:06:15 +00:00
parent 628430f0e9
commit b12abc4533
10 changed files with 70 additions and 60 deletions

View File

@@ -21,7 +21,9 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import com.esotericsoftware.minlog.Log; import com.esotericsoftware.minlog.Log;
@@ -44,26 +46,23 @@ import forge.game.zone.ZoneType;
public class StaticEffects { public class StaticEffects {
// **************** StaticAbility system ************************** // **************** StaticAbility system **************************
/** private final ArrayList<StaticEffect> staticEffects = new ArrayList<StaticEffect>();
* staticEffects.
*/
private ArrayList<StaticEffect> staticEffects;
//Global rule changes //Global rule changes
private final EnumSet<GlobalRuleChange> ruleChanges; private final EnumSet<GlobalRuleChange> ruleChanges = EnumSet.noneOf(GlobalRuleChange.class);
private final Game game; private final Game game;
/** public final Set<Card> clearStaticEffects() {
* clearStaticEffect. TODO Write javadoc for this method.
*/
public final void clearStaticEffects() {
ruleChanges.clear(); ruleChanges.clear();
Set<Card> clearedCards = new HashSet<Card>();
// remove all static effects // remove all static effects
for (int i = 0; i < this.staticEffects.size(); i++) { for (StaticEffect se : staticEffects) {
this.removeStaticEffect(this.staticEffects.get(i)); clearedCards.addAll(this.removeStaticEffect(se));
} }
this.staticEffects = new ArrayList<StaticEffect>(); this.staticEffects.clear();
return clearedCards;
} }
public void setGlobalRuleChange(GlobalRuleChange change) { public void setGlobalRuleChange(GlobalRuleChange change) {
@@ -84,20 +83,13 @@ public class StaticEffects {
this.staticEffects.add(staticEffect); this.staticEffects.add(staticEffect);
} }
/**
* @return the staticEffects
*/
public ArrayList<StaticEffect> getStaticEffects() {
return staticEffects;
}
/** /**
* removeStaticEffect TODO Write javadoc for this method. * removeStaticEffect TODO Write javadoc for this method.
* *
* @param se * @param se
* a StaticEffect * a StaticEffect
*/ */
final void removeStaticEffect(final StaticEffect se) { private final List<Card> removeStaticEffect(final StaticEffect se) {
final List<Card> affectedCards = se.getAffectedCards(); final List<Card> affectedCards = se.getAffectedCards();
final ArrayList<Player> affectedPlayers = se.getAffectedPlayers(); final ArrayList<Player> affectedPlayers = se.getAffectedPlayers();
final HashMap<String, String> params = se.getParams(); final HashMap<String, String> params = se.getParams();
@@ -189,9 +181,7 @@ public class StaticEffects {
} }
// modify the affected card // modify the affected card
for (int i = 0; i < affectedCards.size(); i++) { for (final Card affectedCard : affectedCards) {
final Card affectedCard = affectedCards.get(i);
// Gain control // Gain control
if (params.containsKey("GainControl")) { if (params.containsKey("GainControl")) {
affectedCard.removeTempController(se.getTimestamp()); affectedCard.removeTempController(se.getTimestamp());
@@ -262,6 +252,7 @@ public class StaticEffects {
} }
} }
se.clearTimestamps(); se.clearTimestamps();
return affectedCards;
} }
// **************** End StaticAbility system ************************** // **************** End StaticAbility system **************************
@@ -283,8 +274,6 @@ public class StaticEffects {
public StaticEffects(Game game) { public StaticEffects(Game game) {
this.game = game; this.game = game;
this.initStateBasedEffectsList(); this.initStateBasedEffectsList();
this.staticEffects = new ArrayList<StaticEffect>();
this.ruleChanges = EnumSet.noneOf(GlobalRuleChange.class);
} }
/** /**

View File

@@ -9,7 +9,6 @@ import org.apache.commons.lang3.StringUtils;
import forge.Card; import forge.Card;
import forge.card.ability.SpellAbilityEffect; import forge.card.ability.SpellAbilityEffect;
import forge.card.cardfactory.CardFactoryUtil; import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.Ability;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.TargetRestrictions; import forge.card.spellability.TargetRestrictions;
import forge.card.trigger.TriggerType; import forge.card.trigger.TriggerType;

View File

@@ -1982,6 +1982,7 @@ public class CardFactoryUtil {
String regularPart = String.format("AB$ Pump | Cost$ 0 | Defined$ CardUID_%d | NumAtt$ +%d | NumDef$ +%d | StackDescription$ %s", c.getUniqueNumber(), magnitude, magnitude, description); String regularPart = String.format("AB$ Pump | Cost$ 0 | Defined$ CardUID_%d | NumAtt$ +%d | NumDef$ +%d | StackDescription$ %s", c.getUniqueNumber(), magnitude, magnitude, description);
SpellAbility ability = AbilityFactory.getAbility( regularPart, c); SpellAbility ability = AbilityFactory.getAbility( regularPart, c);
ability.setDescription(ability.getStackDescription());
list.add(ability); list.add(ability);
} }
} }

View File

@@ -227,21 +227,24 @@ public class StaticAbility {
* *
* @param mode * @param mode
* the mode * the mode
* @return
*/ */
public final void applyAbility(final String mode) { public final List<Card> applyAbility(final String mode) {
// don't apply the ability if it hasn't got the right mode // don't apply the ability if it hasn't got the right mode
if (!this.params.get("Mode").equals(mode)) { if (!this.params.get("Mode").equals(mode)) {
return; return null;
} }
if (this.isSuppressed() || !this.checkConditions()) { if (this.isSuppressed() || !this.checkConditions()) {
return; return null;
} }
if (mode.equals("Continuous")) { if (mode.equals("Continuous")) {
StaticAbilityContinuous.applyContinuousAbility(this); return StaticAbilityContinuous.applyContinuousAbility(this);
} }
return null;
} }
// apply the ability if it has the right mode // apply the ability if it has the right mode

View File

@@ -56,9 +56,10 @@ public class StaticAbilityContinuous {
* *
* @param stAb * @param stAb
* a StaticAbility * a StaticAbility
* @return
* *
*/ */
public static void applyContinuousAbility(final StaticAbility stAb) { public static List<Card> applyContinuousAbility(final StaticAbility stAb) {
final HashMap<String, String> params = stAb.getMapParams(); final HashMap<String, String> params = stAb.getMapParams();
final Card hostCard = stAb.getHostCard(); final Card hostCard = stAb.getHostCard();
@@ -476,6 +477,8 @@ public class StaticAbilityContinuous {
} }
} }
} }
return affectedCards;
} }
private static ArrayList<Player> getAffectedPlayers(final StaticAbility stAb) { private static ArrayList<Player> getAffectedPlayers(final StaticAbility stAb) {

View File

@@ -1,6 +1,9 @@
package forge.control; package forge.control;
import java.util.Collection;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.Vector; import java.util.Vector;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@@ -236,7 +239,7 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
} }
private final List<Card> cardsToUpdate = new Vector<Card>(); private final Set<Card> cardsToUpdate = new HashSet<Card>();
private final Runnable updCards = new Runnable() { private final Runnable updCards = new Runnable() {
@Override public void run() { @Override public void run() {
synchronized (cardsToUpdate) { synchronized (cardsToUpdate) {
@@ -275,14 +278,24 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
return null; return null;
} }
private Void updateManyCards(Collection<Card> cc) {
boolean needUpdate = false;
synchronized (cardsToUpdate) {
needUpdate = cardsToUpdate.isEmpty();
cardsToUpdate.addAll(cc);
}
if( needUpdate )
FThreads.invokeInEdtNowOrLater(updCards);
return null;
}
/* (non-Javadoc) /* (non-Javadoc)
* @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventCardStatsChanged) * @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventCardStatsChanged)
*/ */
@Override @Override
public Void visit(GameEventCardStatsChanged event) { public Void visit(GameEventCardStatsChanged event) {
// TODO Smart partial updates // TODO Smart partial updates
PlayerZone z = (PlayerZone) event.card.getGame().getZoneOf(event.card); return updateManyCards(event.cards);
return updateZone(z);
} }
// Update manapool // Update manapool

View File

@@ -24,6 +24,7 @@ import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
@@ -63,6 +64,7 @@ import forge.game.event.GameEventCardChangeZone;
import forge.game.event.GameEventCardDestroyed; import forge.game.event.GameEventCardDestroyed;
import forge.game.event.GameEventCardRegenerated; import forge.game.event.GameEventCardRegenerated;
import forge.game.event.GameEventCardSacrificed; import forge.game.event.GameEventCardSacrificed;
import forge.game.event.GameEventCardStatsChanged;
import forge.game.event.GameEventGameFinished; import forge.game.event.GameEventGameFinished;
import forge.game.event.GameEventFlipCoin; import forge.game.event.GameEventFlipCoin;
import forge.game.event.GameEventGameStarted; import forge.game.event.GameEventGameStarted;
@@ -790,7 +792,7 @@ public class GameAction {
return; return;
// remove old effects // remove old effects
game.getStaticEffects().clearStaticEffects(); Set<Card> affectedCards = game.getStaticEffects().clearStaticEffects();
game.getTriggerHandler().cleanUpTemporaryTriggers(); game.getTriggerHandler().cleanUpTemporaryTriggers();
game.getReplacementHandler().cleanUpTemporaryReplacements(); game.getReplacementHandler().cleanUpTemporaryReplacements();
@@ -817,7 +819,9 @@ public class GameAction {
}; };
Collections.sort(staticAbilities, comp); Collections.sort(staticAbilities, comp);
for (final StaticAbility stAb : staticAbilities) { for (final StaticAbility stAb : staticAbilities) {
stAb.applyAbility("Continuous"); List<Card> affectedHere = stAb.applyAbility("Continuous");
if ( null != affectedHere )
affectedCards.addAll(affectedHere);
} }
// card state effects like Glorious Anthem // card state effects like Glorious Anthem
@@ -827,6 +831,9 @@ public class GameAction {
} }
GameActionUtil.grantBasicLandsManaAbilities(game); GameActionUtil.grantBasicLandsManaAbilities(game);
if ( !affectedCards.isEmpty() )
game.fireEvent(new GameEventCardStatsChanged(affectedCards));
} }
/** /**

View File

@@ -42,7 +42,6 @@ import forge.card.ability.AbilityFactory;
import forge.card.ability.AbilityFactory.AbilityRecordType; import forge.card.ability.AbilityFactory.AbilityRecordType;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.ApiType; import forge.card.ability.ApiType;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost; import forge.card.cost.Cost;
import forge.card.mana.ManaCost; import forge.card.mana.ManaCost;
import forge.card.mana.ManaCostBeingPaid; import forge.card.mana.ManaCostBeingPaid;
@@ -533,23 +532,6 @@ public final class GameActionUtil {
} }
} }
/** stores the Command. */
private static Function<Game, ?> umbraStalker = new Function<Game, Object>() {
@Override
public Object apply(Game game) {
// get all creatures
final List<Card> cards = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals("Umbra Stalker"));
for (final Card c : cards) {
final Player player = c.getController();
final List<Card> grave = player.getCardsIn(ZoneType.Graveyard);
final int pt = CardFactoryUtil.getNumberOfManaSymbolsByColor("B", grave);
c.setBaseAttack(pt);
c.setBaseDefense(pt);
}
return null;
} // execute()
};
/** Constant <code>oldManOfTheSea</code>. */ /** Constant <code>oldManOfTheSea</code>. */
private static Function<Game, ?> oldManOfTheSea = new Function<Game, Object>() { private static Function<Game, ?> oldManOfTheSea = new Function<Game, Object>() {
@@ -614,7 +596,6 @@ public final class GameActionUtil {
GameActionUtil.getCommands().put("Liu_Bei", GameActionUtil.liuBei); GameActionUtil.getCommands().put("Liu_Bei", GameActionUtil.liuBei);
GameActionUtil.getCommands().put("Old_Man_of_the_Sea", GameActionUtil.oldManOfTheSea); GameActionUtil.getCommands().put("Old_Man_of_the_Sea", GameActionUtil.oldManOfTheSea);
GameActionUtil.getCommands().put("Umbra_Stalker", GameActionUtil.umbraStalker);
// The commands above are in alphabetical order by cardname. // The commands above are in alphabetical order by cardname.
} }

View File

@@ -1,7 +1,11 @@
package forge.game.event; package forge.game.event;
import java.util.Arrays;
import java.util.Collection;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import com.google.common.collect.Iterables;
import forge.Card; import forge.Card;
/** /**
@@ -9,9 +13,13 @@ import forge.Card;
*/ */
public class GameEventCardStatsChanged extends GameEvent { public class GameEventCardStatsChanged extends GameEvent {
public final Card card; public final Collection<Card> cards;
public GameEventCardStatsChanged(Card affected) { public GameEventCardStatsChanged(Card affected) {
card = affected; cards = Arrays.asList(affected);
}
public GameEventCardStatsChanged(Collection<Card> affected) {
cards = affected;
} }
/* (non-Javadoc) /* (non-Javadoc)
@@ -25,7 +33,13 @@ public class GameEventCardStatsChanged extends GameEvent {
@Override @Override
public String toString() { public String toString() {
return String.format("Card state changes: %s (%s) %d/%d", card.getName(), StringUtils.join(card.getType(), ' '), card.getNetAttack(), card.getNetDefense() ); Card card = Iterables.getFirst(cards, null);
if ( null == card )
return "Card state changes: (empty list)";
if( cards.size() == 1)
return String.format("Card state changes: %s (%s) %d/%d", card.getName(), StringUtils.join(card.getType(), ' '), card.getNetAttack(), card.getNetDefense() );
else
return String.format("Card state changes: %s (%s) %d/%d and %d more", card.getName(), StringUtils.join(card.getType(), ' '), card.getNetAttack(), card.getNetDefense(), cards.size() - 1 );
} }
} }

View File

@@ -338,7 +338,7 @@ public enum CMatchUI {
} }
public void updateCards(List<Card> cardsToUpdate) { public void updateCards(Set<Card> cardsToUpdate) {
for(Card c : cardsToUpdate) { for(Card c : cardsToUpdate) {
Zone zone = c.getGame().getZoneOf(c); Zone zone = c.getGame().getZoneOf(c);
if ( null == zone ) if ( null == zone )