Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
b7e1f3a
ContinuousEffects: Update timestamping
Jmlundeen May 24, 2025
083bb47
ContinuousEffects: Refactor apply and add dependency checking logic
Jmlundeen May 28, 2025
e3d147e
ContinuousEffect: Add methods for dynamic dependency checks
Jmlundeen May 28, 2025
9dd2656
GameImpl: add null check on playerList when trying to restore state i…
Jmlundeen May 28, 2025
1f89cb2
MageObjectReference: Add method to return generic MageObject
Jmlundeen May 28, 2025
c4508e7
Dependency: Add jgrapht to determine continuous effect dependency cycles
Jmlundeen May 28, 2025
7bd2100
Update March of the Machines, Humility, Mycosynth Lattice and their l…
Jmlundeen May 28, 2025
8a35b7a
Update Blood Moon, (Urborg) AddBasicLandTypeAllLandsEffect and their …
Jmlundeen May 28, 2025
5411166
Update Necrotic Ooze and yixlid Jailer
Jmlundeen May 28, 2025
a564176
Move TODO for calculateResult to method
Jmlundeen May 28, 2025
a565c93
Revert dependency changes
Jmlundeen May 29, 2025
48b9a6b
Merge branch 'master' into rework/continuous-effects-layers
Jmlundeen May 29, 2025
7cc245c
ContinuousEffects: Add queryAffectedObjects and applyToObjects methods
Jmlundeen May 29, 2025
f679b87
refactor common effects
Jmlundeen May 29, 2025
c5baa4a
refactor more common effects
Jmlundeen May 31, 2025
0d7246a
refactor more common effects
Jmlundeen May 31, 2025
0e6661c
refactor more common effects
Jmlundeen Jun 1, 2025
36fd6d2
refactor more common effects
Jmlundeen Jun 1, 2025
02d1d27
refactor more common effects
Jmlundeen Jun 1, 2025
a8b0c8d
ContinuousEffect: Update query and apply to use List<MageItem> since …
Jmlundeen Jun 1, 2025
efd717b
refactor more common effects
Jmlundeen Jun 2, 2025
bb37304
refactor more common effects
Jmlundeen Jun 2, 2025
34b0e5f
Merge branch 'master' into rework/continuous-effects-layers
Jmlundeen Jun 2, 2025
3d30999
Revert incorrect changes
Jmlundeen Jun 3, 2025
38c0a08
Update continuous effects with applyToObjects and queryAffectedObjects
Jmlundeen Jun 3, 2025
b6112e7
Refactor some continuous effects
Jmlundeen Jun 3, 2025
99673c7
Add test for EnduringGlimmerTriggeredAbility
Jmlundeen Jun 4, 2025
59012a8
fix affectedObjectsMap checking for single layer effects
Jmlundeen Jun 4, 2025
26aa703
fix ConditionalContinuousEffect to correctly clear affectedObjectMap …
Jmlundeen Jun 5, 2025
19f22f1
Refactor some more effects
Jmlundeen Jun 5, 2025
1487559
Fix affectedObjectMap wrongly assigning instead of adding keys/values…
Jmlundeen Jun 6, 2025
6851dc1
Merge branch 'refs/heads/master' into rework/continuous-effects-layers
Jmlundeen Jun 8, 2025
09af4b6
Readjust query+applyTo logic
Jmlundeen Jun 8, 2025
bc2db46
Refactor more effects
Jmlundeen Jun 9, 2025
3eb9d24
Refactor more effects
Jmlundeen Jun 11, 2025
102c18d
A little more refactoring
Jmlundeen Jun 13, 2025
0c7df6f
I "C" more refactors ahead
Jmlundeen Jul 8, 2025
e64a10b
Merge branch 'master' into rework/continuous-effects-layers
Jmlundeen Jul 9, 2025
64401be
"D"on't stop refactoring
Jmlundeen Jul 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 35 additions & 19 deletions Mage.Sets/src/mage/cards/a/AbuelosAwakening.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package mage.cards.a;

import mage.MageItem;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.common.GetXValue;
import mage.abilities.effects.ContinuousEffectImpl;
Expand All @@ -17,6 +18,8 @@
import mage.target.common.TargetCardInYourGraveyard;
import mage.target.targetpointer.FixedTarget;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
Expand Down Expand Up @@ -106,12 +109,29 @@ public AbuelosAwakeningContinuousEffect copy() {
}

@Override
public boolean apply(Game game, Ability source) {
return false;
public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List<MageItem> affectedObjects) {
for (MageItem object : affectedObjects) {
Permanent creature = (Permanent) object;
switch (layer) {
case TypeChangingEffects_4:
creature.addCardType(game, CardType.CREATURE);
creature.addSubType(game, SubType.SPIRIT);
break;
case AbilityAddingRemovingEffects_6:
creature.addAbility(FlyingAbility.getInstance(), source.getSourceId(), game);
break;
case PTChangingEffects_7:
if (sublayer == SubLayer.SetPT_7b) {
creature.getPower().setModifiedBaseValue(1);
creature.getToughness().setModifiedBaseValue(1);
}
break;
}
}
}

@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List<MageItem> affectedObjects) {
Permanent creature;
if (source.getTargets().getFirstTarget() == null) {
creature = game.getPermanent(getTargetPointer().getFirst(game, source));
Expand All @@ -122,27 +142,23 @@ public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game)
}
}
if (creature == null) {
this.used = true;
this.discard();
return false;
}
switch (layer) {
case TypeChangingEffects_4:
creature.addCardType(game, CardType.CREATURE);
creature.addSubType(game, SubType.SPIRIT);
break;
case AbilityAddingRemovingEffects_6:
creature.addAbility(FlyingAbility.getInstance(), source.getSourceId(), game);
break;
case PTChangingEffects_7:
if (sublayer == SubLayer.SetPT_7b) {
creature.getPower().setModifiedBaseValue(1);
creature.getToughness().setModifiedBaseValue(1);
}
break;
}
affectedObjects.add(creature);
return true;
}

@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
List<MageItem> affectedObjects = new ArrayList<>();
if (queryAffectedObjects(layer, source, game, affectedObjects)) {
applyToObjects(layer, sublayer, source, game, affectedObjects);
return true;
}
return false;
}

@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.TypeChangingEffects_4 ||
Expand Down
24 changes: 16 additions & 8 deletions Mage.Sets/src/mage/cards/a/ActOfAuthority.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package mage.cards.a;

import java.util.UUID;
import mage.MageItem;
import mage.abilities.Ability;
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
Expand All @@ -17,6 +17,9 @@
import mage.target.TargetPermanent;
import mage.target.targetpointer.FixedTarget;

import java.util.List;
import java.util.UUID;

/**
*
* @author LevelX2
Expand Down Expand Up @@ -106,17 +109,22 @@ public ActOfAuthorityGainControlEffect copy() {
}

@Override
public boolean apply(Game game, Ability source) {
Permanent permanent;
permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List<MageItem> affectedObjects) {
for (MageItem object : affectedObjects) {
((Permanent) object).changeControllerId(controller, game, source);
}
}

@Override
public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List<MageItem> affectedObjects) {
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent == null) {
permanent = game.getPermanent(source.getFirstTarget());
}

if (permanent == null) {
return false;
}

return permanent.changeControllerId(controller, game, source);
affectedObjects.add(permanent);
return true;
}
}
39 changes: 21 additions & 18 deletions Mage.Sets/src/mage/cards/a/AettirAndPriwen.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
package mage.cards.a;

import mage.MageItem;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.keyword.EquipAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.game.Controllable;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;

import java.util.Optional;
import java.util.List;
import java.util.UUID;

/**
Expand Down Expand Up @@ -60,23 +60,26 @@ public AettirAndPriwenEffect copy() {
}

@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = Optional
.ofNullable(source.getSourcePermanentIfItStillExists(game))
.map(Permanent::getAttachedTo)
.map(game::getPermanent)
.orElse(null);
if (permanent == null) {
public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List<MageItem> affectedObjects) {
int life = game.getPlayer(source.getControllerId()).getLife();
for (MageItem object : affectedObjects) {
Permanent permanent = (Permanent) object;
permanent.getPower().setModifiedBaseValue(life);
permanent.getToughness().setModifiedBaseValue(life);
}
}

@Override
public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List<MageItem> affectedObjects) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
Optional.ofNullable(source)
.map(Controllable::getControllerId)
.map(game::getPlayer)
.map(Player::getLife)
.ifPresent(life -> {
permanent.getPower().setModifiedBaseValue(life);
permanent.getToughness().setModifiedBaseValue(life);
});
return true;
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
affectedObjects.add(permanent);
return true;
}
return false;
}
}
13 changes: 11 additions & 2 deletions Mage.Sets/src/mage/cards/a/AeveProgenitorOoze.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package mage.cards.a;

import mage.MageInt;
import mage.MageItem;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.SimpleStaticAbility;
Expand All @@ -18,6 +19,7 @@
import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentToken;

import java.util.List;
import java.util.UUID;

/**
Expand Down Expand Up @@ -79,10 +81,17 @@ public AeveProgenitorOozeNonLegendaryEffect copy() {
}

@Override
public boolean apply(Game game, Ability source) {
public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List<MageItem> affectedObjects) {
for (MageItem object : affectedObjects) {
((Permanent) object).removeSuperType(game, SuperType.LEGENDARY);
}
}

@Override
public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List<MageItem> affectedObjects) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent instanceof PermanentToken) {
permanent.removeSuperType(game, SuperType.LEGENDARY);
affectedObjects.add(permanent);
return true;
}
return false;
Expand Down
31 changes: 24 additions & 7 deletions Mage.Sets/src/mage/cards/a/AgathasSoulCauldron.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package mage.cards.a;

import mage.MageItem;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
Expand Down Expand Up @@ -28,6 +29,7 @@
import mage.util.CardUtil;

import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -119,7 +121,26 @@ private AgathasSoulCauldronAbilityEffect(final AgathasSoulCauldronAbilityEffect
}

@Override
public boolean apply(Game game, Ability source) {
public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List<MageItem> affectedObjects) {
ExileZone exileZone = game.getExile().getExileZone(CardUtil.getExileZoneId(
game, source.getSourceId(), game.getState().getZoneChangeCounter(source.getSourceId())
));
Set<Ability> abilities = exileZone
.getCards(StaticFilters.FILTER_CARD_CREATURE, game)
.stream()
.map(card -> card.getAbilities(game))
.flatMap(Collection::stream)
.filter(Ability::isActivatedAbility)
.collect(Collectors.toSet());
for (MageItem object : affectedObjects) {
for (Ability ability : abilities) {
((Permanent) object).addAbility(ability, source.getSourceId(), game, true);
}
}
}

@Override
public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List<MageItem> affectedObjects) {
ExileZone exileZone = game.getExile().getExileZone(CardUtil.getExileZoneId(
game, source.getSourceId(), game.getState().getZoneChangeCounter(source.getSourceId())
));
Expand All @@ -136,12 +157,8 @@ public boolean apply(Game game, Ability source) {
if (abilities.isEmpty()) {
return false;
}
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) {
for (Ability ability : abilities) {
permanent.addAbility(ability, source.getSourceId(), game, true);
}
}
return true;
affectedObjects.addAll(game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game));
return !affectedObjects.isEmpty();
}

@Override
Expand Down
44 changes: 6 additions & 38 deletions Mage.Sets/src/mage/cards/a/AgelessSentinels.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.BlocksSourceTriggeredAbility;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.AddCardSubTypeSourceEffect;
import mage.abilities.effects.common.continuous.LoseAbilitySourceEffect;
import mage.abilities.keyword.DefenderAbility;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;

import java.util.UUID;

Expand All @@ -35,7 +35,8 @@ public AgelessSentinels(UUID ownerId, CardSetInfo setInfo) {
this.addAbility(FlyingAbility.getInstance());

// When Ageless Sentinels blocks, it becomes a Bird Giant, and it loses defender.
Ability ability = new BlocksSourceTriggeredAbility(new AgelessSentinelsEffect()).setTriggerPhrase("When {this} blocks, ");
Effect becomeBirdGiantEffect = new AddCardSubTypeSourceEffect(Duration.WhileOnBattlefield, SubType.BIRD, SubType.GIANT);
Ability ability = new BlocksSourceTriggeredAbility(becomeBirdGiantEffect).setTriggerPhrase("When {this} blocks, ");
Effect effect = new LoseAbilitySourceEffect(DefenderAbility.getInstance(), Duration.WhileOnBattlefield);
effect.setText(", and it loses defender. <i>(It's no longer a Wall. This effect lasts indefinitely.)</i>");
ability.addEffect(effect);
Expand All @@ -51,36 +52,3 @@ public AgelessSentinels copy() {
return new AgelessSentinels(this);
}
}

class AgelessSentinelsEffect extends ContinuousEffectImpl {

AgelessSentinelsEffect() {
super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.BecomeCreature);
staticText = "it becomes a Bird Giant";
}

private AgelessSentinelsEffect(final AgelessSentinelsEffect effect) {
super(effect);
}

@Override
public AgelessSentinelsEffect copy() {
return new AgelessSentinelsEffect(this);
}

@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent == null) {
return false;
}
permanent.removeAllCreatureTypes(game);
permanent.addSubType(game, SubType.BIRD, SubType.GIANT);
return true;
}

@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.TypeChangingEffects_4;
}
}
Loading