mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 19:58:00 +00:00
Events are fired when static abilities recalculate
This commit is contained in:
@@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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.
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 )
|
||||||
|
|||||||
Reference in New Issue
Block a user