mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-14 17:58:01 +00:00
Merge branch '1372-used-memory-grows-quadratic-in-the-number-of-triggered-spells' into 'master'
Resolve "Used memory grows quadratic in the number of triggered spells" Closes #1372 See merge request core-developers/forge!2756
This commit is contained in:
@@ -1352,7 +1352,7 @@ public class ComputerUtil {
|
||||
if (valid.contains("Creature.YouCtrl")
|
||||
|| valid.contains("Other+YouCtrl") ) {
|
||||
|
||||
final SpellAbility sa = t.getTriggeredSA();
|
||||
final SpellAbility sa = t.getOverridingAbility();
|
||||
if (sa != null && sa.getApi() == ApiType.Pump && sa.hasParam("KW")
|
||||
&& sa.getParam("KW").contains("Haste")) {
|
||||
return true;
|
||||
|
||||
@@ -894,6 +894,9 @@ public class Game {
|
||||
public void clearCaches() {
|
||||
spabCache.clear();
|
||||
cardCache.clear();
|
||||
|
||||
lastStateBattlefield.clear();
|
||||
lastStateGraveyard.clear();
|
||||
//playerCache.clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -1056,23 +1056,6 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
}
|
||||
}
|
||||
|
||||
public final Object getTriggeringObject(final AbilityKey typeIn) {
|
||||
Object triggered = null;
|
||||
if (!currentState.getTriggers().isEmpty()) {
|
||||
for (final Trigger t : currentState.getTriggers()) {
|
||||
final SpellAbility sa = t.getTriggeredSA();
|
||||
if (sa == null) {
|
||||
continue;
|
||||
}
|
||||
triggered = sa.hasTriggeringObject(typeIn) ? sa.getTriggeringObject(typeIn) : null;
|
||||
if (triggered != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return triggered;
|
||||
}
|
||||
|
||||
public final int getSunburstValue() {
|
||||
return sunburstValue;
|
||||
}
|
||||
|
||||
@@ -680,7 +680,6 @@ public class CardFactory {
|
||||
wrapperAbility.setTrigger(true);
|
||||
wrapperAbility.setMandatory(sa.isMandatory());
|
||||
wrapperAbility.setDescription(wrapperAbility.getStackDescription());
|
||||
t.setTriggeredSA(wrapperAbility);
|
||||
return wrapperAbility;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ import forge.game.GameEntity;
|
||||
import forge.game.GameEntityCounterTable;
|
||||
import forge.game.GameLogEntryType;
|
||||
import forge.game.ability.AbilityFactory;
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.card.CardPredicates.Presets;
|
||||
@@ -954,11 +953,6 @@ public class CardFactoryUtil {
|
||||
return doXMath(c.getRegeneratedThisTurn(), m, c);
|
||||
}
|
||||
|
||||
// TriggeringObjects
|
||||
if (sq[0].startsWith("Triggered")) {
|
||||
return doXMath(xCount((Card) c.getTriggeringObject(AbilityKey.Card), sq[0].substring(9)), m, c);
|
||||
}
|
||||
|
||||
if (sq[0].contains("YourStartingLife")) {
|
||||
return doXMath(cc.getStartingLife(), m, c);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import forge.card.MagicColor;
|
||||
import forge.game.Direction;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameEntity;
|
||||
import forge.game.GameObject;
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.CardPredicates.Presets;
|
||||
@@ -15,7 +16,6 @@ import forge.game.keyword.Keyword;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.OptionalCost;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.trigger.Trigger;
|
||||
import forge.game.zone.Zone;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.Expressions;
|
||||
@@ -392,30 +392,20 @@ public class CardProperty {
|
||||
}
|
||||
} else if (property.startsWith("AttachedTo")) {
|
||||
final String restriction = property.split("AttachedTo ")[1];
|
||||
if (restriction.equals("Targeted")) {
|
||||
if (!source.getCurrentState().getTriggers().isEmpty()) {
|
||||
for (final Trigger t : source.getCurrentState().getTriggers()) {
|
||||
final SpellAbility sa = t.getTriggeredSA();
|
||||
final CardCollectionView cards = AbilityUtils.getDefinedCards(source, "Targeted", sa);
|
||||
for (final Card c : cards) {
|
||||
if (card.getEquipping() != c && !c.equals(card.getEntityAttachedTo())) {
|
||||
|
||||
if (card.getEntityAttachedTo() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!card.getEntityAttachedTo().isValid(restriction, sourceController, source, spellAbility)) {
|
||||
boolean found = false;
|
||||
for (final GameObject o : AbilityUtils.getDefinedObjects(source, restriction, spellAbility)) {
|
||||
if (o.equals(card.getEntityAttachedTo())) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (final SpellAbility sa : source.getCurrentState().getNonManaAbilities()) {
|
||||
final CardCollectionView cards = AbilityUtils.getDefinedCards(source, "Targeted", sa);
|
||||
for (final Card c : cards) {
|
||||
if (card.getEquipping() == c || c.equals(card.getEntityAttachedTo())) { // handle multiple targets
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if ((card.getEntityAttachedTo() == null || !card.getEntityAttachedTo().isValid(restriction, sourceController, source, spellAbility))) {
|
||||
if (!found) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -856,15 +846,6 @@ public class CardProperty {
|
||||
}
|
||||
}
|
||||
return false;
|
||||
case "TriggeredCard":
|
||||
final Object triggeringObject = source.getTriggeringObject(AbilityKey.fromString(restriction.substring("Triggered".length())));
|
||||
if (!(triggeringObject instanceof Card)) {
|
||||
return false;
|
||||
}
|
||||
if (card.sharesCardTypeWith((Card) triggeringObject)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case "EachTopLibrary":
|
||||
final CardCollection cards = new CardCollection();
|
||||
for (Player p : game.getPlayers()) {
|
||||
|
||||
@@ -1996,4 +1996,24 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
public void setXManaCostPaid(final Integer n) {
|
||||
xManaCostPaid = n;
|
||||
}
|
||||
|
||||
public void removeFromGame() {
|
||||
if (getHostCard() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
getHostCard().getGame().removeSpellAbility(this);
|
||||
|
||||
if (subAbility != null) {
|
||||
subAbility.removeFromGame();
|
||||
}
|
||||
for (AbilitySub sa : additionalAbilities.values()) {
|
||||
sa.removeFromGame();
|
||||
}
|
||||
for (List<AbilitySub> list : additionalAbilityLists.values()) {
|
||||
for (AbilitySub sa : list) {
|
||||
sa.removeFromGame();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import forge.game.card.CardState;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.Ability;
|
||||
import forge.game.spellability.OptionalCost;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
@@ -472,27 +471,6 @@ public abstract class Trigger extends TriggerReplacementBase {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
private Ability triggeredSA;
|
||||
|
||||
/**
|
||||
* Gets the triggered sa.
|
||||
*
|
||||
* @return the triggered sa
|
||||
*/
|
||||
public final Ability getTriggeredSA() {
|
||||
return this.triggeredSA;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the triggered sa.
|
||||
*
|
||||
* @param sa
|
||||
* the triggered sa to set
|
||||
*/
|
||||
public void setTriggeredSA(final Ability sa) {
|
||||
this.triggeredSA = sa;
|
||||
}
|
||||
|
||||
public void addRemembered(Object o) {
|
||||
this.triggerRemembered.add(o);
|
||||
}
|
||||
|
||||
@@ -628,7 +628,6 @@ public class TriggerHandler {
|
||||
else {
|
||||
game.getStack().addSimultaneousStackEntry(wrapperAbility);
|
||||
}
|
||||
regtrig.setTriggeredSA(wrapperAbility);
|
||||
|
||||
regtrig.triggerRun();
|
||||
|
||||
|
||||
@@ -563,4 +563,10 @@ public class WrappedAbility extends Ability {
|
||||
public void setXManaCostPaid(final Integer n) {
|
||||
sa.setXManaCostPaid(n);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFromGame() {
|
||||
super.removeFromGame();
|
||||
getHostCard().getGame().removeSpellAbility(this.getWrappedAbility());
|
||||
}
|
||||
}
|
||||
@@ -638,7 +638,13 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
|
||||
frozenStack.remove(si);
|
||||
game.updateStackForView();
|
||||
SpellAbility sa = si.getSpellAbility(true);
|
||||
sa.setLastStateBattlefield(CardCollection.EMPTY);
|
||||
sa.setLastStateGraveyard(CardCollection.EMPTY);
|
||||
game.fireEvent(new GameEventSpellRemovedFromStack(sa));
|
||||
|
||||
if (sa.isTrigger()) {
|
||||
sa.removeFromGame();
|
||||
}
|
||||
}
|
||||
|
||||
public final void remove(final Card c) {
|
||||
|
||||
Reference in New Issue
Block a user