mirror of
https://github.com/magefree/mage.git
synced 2025-12-24 20:41:58 -08:00
- Fixed #6236
This commit is contained in:
parent
b75a5d86b1
commit
d6c2f031d0
28 changed files with 813 additions and 650 deletions
|
|
@ -168,8 +168,12 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
|
|||
case PTChangingEffects_7:
|
||||
this.affectedObjectsSet = true;
|
||||
}
|
||||
} else if (hasLayer(Layer.CopyEffects_1) || hasLayer(Layer.ControlChangingEffects_2) || hasLayer(Layer.TextChangingEffects_3)
|
||||
|| hasLayer(Layer.TypeChangingEffects_4) || hasLayer(Layer.ColorChangingEffects_5) || hasLayer(Layer.AbilityAddingRemovingEffects_6)
|
||||
} else if (hasLayer(Layer.CopyEffects_1)
|
||||
|| hasLayer(Layer.ControlChangingEffects_2)
|
||||
|| hasLayer(Layer.TextChangingEffects_3)
|
||||
|| hasLayer(Layer.TypeChangingEffects_4)
|
||||
|| hasLayer(Layer.ColorChangingEffects_5)
|
||||
|| hasLayer(Layer.AbilityAddingRemovingEffects_6)
|
||||
|| hasLayer(Layer.PTChangingEffects_7)) {
|
||||
this.affectedObjectsSet = true;
|
||||
}
|
||||
|
|
@ -185,7 +189,8 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
|
|||
@Override
|
||||
public void setStartingControllerAndTurnNum(Game game, UUID startingController, UUID activePlayerId) {
|
||||
this.startingControllerId = startingController;
|
||||
this.startingTurnWasActive = activePlayerId != null && activePlayerId.equals(startingController); // you can't use "game" for active player cause it's called from tests/cheat too
|
||||
this.startingTurnWasActive = activePlayerId != null
|
||||
&& activePlayerId.equals(startingController); // you can't use "game" for active player cause it's called from tests/cheat too
|
||||
this.yourTurnNumPlayed = 0;
|
||||
}
|
||||
|
||||
|
|
@ -197,9 +202,11 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
|
|||
@Override
|
||||
public boolean isYourNextTurn(Game game) {
|
||||
if (this.startingTurnWasActive) {
|
||||
return yourTurnNumPlayed == 1 && game.isActivePlayer(startingControllerId);
|
||||
return yourTurnNumPlayed == 1
|
||||
&& game.isActivePlayer(startingControllerId);
|
||||
} else {
|
||||
return yourTurnNumPlayed == 0 && game.isActivePlayer(startingControllerId);
|
||||
return yourTurnNumPlayed == 0
|
||||
&& game.isActivePlayer(startingControllerId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -231,14 +238,18 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
|
|||
switch (duration) {
|
||||
case UntilYourNextTurn:
|
||||
case UntilEndOfYourNextTurn:
|
||||
canDelete = player == null || (!player.isInGame() && player.hasReachedNextTurnAfterLeaving());
|
||||
canDelete = player == null
|
||||
|| (!player.isInGame()
|
||||
&& player.hasReachedNextTurnAfterLeaving());
|
||||
}
|
||||
|
||||
// discard on another conditions (start of your turn)
|
||||
switch (duration) {
|
||||
case UntilYourNextTurn:
|
||||
if (player != null && player.isInGame()) {
|
||||
canDelete = canDelete || this.isYourNextTurn(game);
|
||||
if (player != null
|
||||
&& player.isInGame()) {
|
||||
canDelete = canDelete
|
||||
|| this.isYourNextTurn(game);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -305,7 +316,7 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
|
|||
|
||||
@Override
|
||||
public Set<UUID> isDependentTo(List<ContinuousEffect> allEffectsInLayer) {
|
||||
Set<UUID> dependentToEffects = new HashSet<UUID>();
|
||||
Set<UUID> dependentToEffects = new HashSet<>();
|
||||
if (dependendToTypes != null) {
|
||||
for (ContinuousEffect effect : allEffectsInLayer) {
|
||||
if (!effect.getId().equals(this.getId())) {
|
||||
|
|
@ -354,7 +365,8 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
|
|||
}
|
||||
|
||||
/**
|
||||
* Auto-generates dependencies on different effects (what's apply first and what's apply second)
|
||||
* Auto-generates dependencies on different effects (what's apply first and
|
||||
* what's apply second)
|
||||
*/
|
||||
public void generateGainAbilityDependencies(Ability abilityToGain, Filter filterToSearch) {
|
||||
this.addDependencyType(DependencyType.AddingAbility);
|
||||
|
|
@ -369,14 +381,18 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
|
|||
}
|
||||
|
||||
private void generateGainAbilityDependenciesFromAbility(CompoundAbility compoundAbility) {
|
||||
if (compoundAbility == null) return;
|
||||
if (compoundAbility == null) {
|
||||
return;
|
||||
}
|
||||
for (Ability ability : compoundAbility) {
|
||||
generateGainAbilityDependenciesFromAbility(ability);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateGainAbilityDependenciesFromAbility(Ability ability) {
|
||||
if (ability == null) return;
|
||||
if (ability == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. "Is all type" ability (changeling)
|
||||
// make dependency
|
||||
|
|
@ -386,7 +402,9 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
|
|||
}
|
||||
|
||||
private void generateGainAbilityDependenciesFromFilter(Filter filter) {
|
||||
if (filter == null) return;
|
||||
if (filter == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. "Is all type" ability (changeling)
|
||||
// wait dependency
|
||||
|
|
|
|||
|
|
@ -338,7 +338,7 @@ public class ContinuousEffects implements Serializable {
|
|||
}
|
||||
// boolean checkLKI = event.getType().equals(EventType.ZONE_CHANGE) || event.getType().equals(EventType.DESTROYED_PERMANENT);
|
||||
//get all applicable transient Replacement effects
|
||||
for (Iterator<ReplacementEffect> iterator = replacementEffects.iterator(); iterator.hasNext(); ) {
|
||||
for (Iterator<ReplacementEffect> iterator = replacementEffects.iterator(); iterator.hasNext();) {
|
||||
ReplacementEffect effect = iterator.next();
|
||||
if (!effect.checksEventType(event, game)) {
|
||||
continue;
|
||||
|
|
@ -371,7 +371,7 @@ public class ContinuousEffects implements Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
for (Iterator<PreventionEffect> iterator = preventionEffects.iterator(); iterator.hasNext(); ) {
|
||||
for (Iterator<PreventionEffect> iterator = preventionEffects.iterator(); iterator.hasNext();) {
|
||||
PreventionEffect effect = iterator.next();
|
||||
if (!effect.checksEventType(event, game)) {
|
||||
continue;
|
||||
|
|
@ -740,8 +740,8 @@ public class ContinuousEffects implements Serializable {
|
|||
* @param event
|
||||
* @param targetAbility ability the event is attached to. can be null.
|
||||
* @param game
|
||||
* @param silentMode true if the event does not really happen but
|
||||
* it's checked if the event would be replaced
|
||||
* @param silentMode true if the event does not really happen but it's
|
||||
* checked if the event would be replaced
|
||||
* @return
|
||||
*/
|
||||
public boolean preventedByRuleModification(GameEvent event, Ability targetAbility, Game game, boolean silentMode) {
|
||||
|
|
@ -789,7 +789,7 @@ public class ContinuousEffects implements Serializable {
|
|||
do {
|
||||
Map<ReplacementEffect, Set<Ability>> rEffects = getApplicableReplacementEffects(event, game);
|
||||
// Remove all consumed effects (ability dependant)
|
||||
for (Iterator<ReplacementEffect> it1 = rEffects.keySet().iterator(); it1.hasNext(); ) {
|
||||
for (Iterator<ReplacementEffect> it1 = rEffects.keySet().iterator(); it1.hasNext();) {
|
||||
ReplacementEffect entry = it1.next();
|
||||
if (consumed.containsKey(entry.getId()) /*&& !(entry instanceof CommanderReplacementEffect) */) { // 903.9.
|
||||
Set<UUID> consumedAbilitiesIds = consumed.get(entry.getId());
|
||||
|
|
@ -980,7 +980,7 @@ public class ContinuousEffects implements Serializable {
|
|||
|
||||
if (!waitingEffects.isEmpty()) {
|
||||
// check if waiting effects can be applied now
|
||||
for (Iterator<Map.Entry<ContinuousEffect, Set<UUID>>> iterator = waitingEffects.entrySet().iterator(); iterator.hasNext(); ) {
|
||||
for (Iterator<Map.Entry<ContinuousEffect, Set<UUID>>> iterator = waitingEffects.entrySet().iterator(); iterator.hasNext();) {
|
||||
Map.Entry<ContinuousEffect, Set<UUID>> entry = iterator.next();
|
||||
if (appliedEffects.containsAll(entry.getValue())) { // all dependent to effects are applied now so apply the effect itself
|
||||
appliedAbilities = appliedEffectAbilities.get(entry.getKey());
|
||||
|
|
@ -1060,26 +1060,50 @@ public class ContinuousEffects implements Serializable {
|
|||
|
||||
private void applyLayer(List<ContinuousEffect> activeLayerEffects, Layer currentLayer, Game game) {
|
||||
List<ContinuousEffect> layer = filterLayeredEffects(activeLayerEffects, currentLayer);
|
||||
// layer is a list of all effects at the current layer
|
||||
if (!layer.isEmpty()) {
|
||||
int numberOfEffects = layer.size();
|
||||
// appliedEffects holds the list of effects currently applied to the layer
|
||||
Set<UUID> appliedEffects = new HashSet<>();
|
||||
// waitingEffects holds the list of dependent effects and their independent counterparts
|
||||
Map<ContinuousEffect, Set<UUID>> waitingEffects = new LinkedHashMap<>();
|
||||
for (ContinuousEffect effect : layer) {
|
||||
if (numberOfEffects > 1) { // If an effect is dependent to not applied effects yet of this layer, so wait to apply this effect
|
||||
if (numberOfEffects > 1) {
|
||||
// If an effect is dependent to not applied effects yet of this layer, so wait to apply this effect
|
||||
// check to see if any effect is dependent to other cards indirectly due to the independent card being dependent, etc.
|
||||
Set<UUID> dependentTo = effect.isDependentTo(layer);
|
||||
if (!appliedEffects.containsAll(dependentTo)) {
|
||||
waitingEffects.put(effect, dependentTo);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// apply the effect
|
||||
applyContinuousEffect(effect, currentLayer, game);
|
||||
// add it to the applied effects list
|
||||
appliedEffects.add(effect.getId());
|
||||
layer = getLayeredEffects(game);
|
||||
|
||||
// check waiting effects to see if it has anything to check
|
||||
if (!waitingEffects.isEmpty()) {
|
||||
// check if waiting effects can be applied now
|
||||
for (Entry<ContinuousEffect, Set<UUID>> entry : waitingEffects.entrySet()) {
|
||||
if (appliedEffects.containsAll(entry.getValue())) { // all dependent to effects are applied now so apply the effect itself
|
||||
// all dependent to effects are applied now so apply the effect itself
|
||||
if (appliedEffects.containsAll(entry.getValue())) {
|
||||
applyContinuousEffect(entry.getKey(), currentLayer, game);
|
||||
// add it to the applied effects list
|
||||
appliedEffects.add(entry.getKey().getId());
|
||||
layer = getLayeredEffects(game);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (numberOfEffects != appliedEffects.size()) {
|
||||
for (Entry<ContinuousEffect, Set<UUID>> entry : waitingEffects.entrySet()) {
|
||||
// all dependent to effects are applied now so apply the effect itself
|
||||
if (appliedEffects.containsAll(entry.getValue())) {
|
||||
applyContinuousEffect(entry.getKey(), currentLayer, game);
|
||||
// add it to the applied effects list
|
||||
appliedEffects.add(entry.getKey().getId());
|
||||
layer = getLayeredEffects(game);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,12 +43,15 @@ public class BecomesBasicLandEnchantedEffect extends ContinuousEffectImpl {
|
|||
Permanent permanent = game.getPermanent(enchantment.getAttachedTo());
|
||||
if (permanent != null) {
|
||||
switch (layer) {
|
||||
case AbilityAddingRemovingEffects_6:
|
||||
case TypeChangingEffects_4:
|
||||
// lands intrictically have the mana ability associated with their type, so added here in layer 4
|
||||
permanent.getSubtype(game).removeAll(SubType.getLandTypes());
|
||||
permanent.getSubtype(game).addAll(landTypes);
|
||||
permanent.removeAllAbilities(source.getSourceId(), game);
|
||||
for (SubType landType : landTypes) {
|
||||
switch (landType) {
|
||||
case SWAMP:
|
||||
if (permanent.hasSubtype(SubType.SWAMP, game)) { // type can be removed by other effect with newer timestamp, so no ability adding
|
||||
if (permanent.hasSubtype(SubType.SWAMP, game)) {
|
||||
permanent.addAbility(new BlackManaAbility(), source.getSourceId(), game);
|
||||
}
|
||||
break;
|
||||
|
|
@ -75,11 +78,6 @@ public class BecomesBasicLandEnchantedEffect extends ContinuousEffectImpl {
|
|||
}
|
||||
}
|
||||
break;
|
||||
case TypeChangingEffects_4:
|
||||
// subtypes are all removed by changing the subtype to a land type.
|
||||
permanent.getSubtype(game).removeAll(SubType.getLandTypes());
|
||||
permanent.getSubtype(game).addAll(landTypes);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -89,7 +87,7 @@ public class BecomesBasicLandEnchantedEffect extends ContinuousEffectImpl {
|
|||
|
||||
@Override
|
||||
public boolean hasLayer(Layer layer) {
|
||||
return layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.TypeChangingEffects_4;
|
||||
return layer == Layer.TypeChangingEffects_4;
|
||||
}
|
||||
|
||||
private String setText() {
|
||||
|
|
|
|||
|
|
@ -112,7 +112,8 @@ public class BecomesBasicLandTargetEffect extends ContinuousEffectImpl {
|
|||
land.addCardType(CardType.LAND);
|
||||
}
|
||||
if (loseOther) {
|
||||
// 305.7 Note that this doesn't remove any abilities that were granted to the land by other effects
|
||||
// 305.7 Note that this doesn't remove any abilities
|
||||
// that were granted to the land by other effects
|
||||
// So the ability removing has to be done before Layer 6
|
||||
land.removeAllAbilities(source.getSourceId(), game);
|
||||
// 305.7
|
||||
|
|
@ -127,8 +128,7 @@ public class BecomesBasicLandTargetEffect extends ContinuousEffectImpl {
|
|||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AbilityAddingRemovingEffects_6:
|
||||
// add intrinsic land abilities here not in layer 6
|
||||
for (SubType landType : landTypesToAdd) {
|
||||
switch (landType) {
|
||||
case SWAMP:
|
||||
|
|
@ -157,7 +157,7 @@ public class BecomesBasicLandTargetEffect extends ContinuousEffectImpl {
|
|||
|
||||
@Override
|
||||
public boolean hasLayer(Layer layer) {
|
||||
return layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.TypeChangingEffects_4;
|
||||
return layer == Layer.TypeChangingEffects_4;
|
||||
}
|
||||
|
||||
private String setText() {
|
||||
|
|
|
|||
|
|
@ -25,15 +25,18 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
|
|||
private boolean loseTypes = false;
|
||||
protected boolean loseName = false;
|
||||
|
||||
public BecomesCreatureAllEffect(Token token, String theyAreStillType, FilterPermanent filter, Duration duration, boolean loseColor) {
|
||||
public BecomesCreatureAllEffect(Token token, String theyAreStillType,
|
||||
FilterPermanent filter, Duration duration, boolean loseColor) {
|
||||
this(token, theyAreStillType, filter, duration, loseColor, false, false);
|
||||
}
|
||||
|
||||
public BecomesCreatureAllEffect(Token token, String theyAreStillType, FilterPermanent filter, Duration duration, boolean loseColor, boolean loseName) {
|
||||
public BecomesCreatureAllEffect(Token token, String theyAreStillType,
|
||||
FilterPermanent filter, Duration duration, boolean loseColor, boolean loseName) {
|
||||
this(token, theyAreStillType, filter, duration, loseColor, loseName, false);
|
||||
}
|
||||
|
||||
public BecomesCreatureAllEffect(Token token, String theyAreStillType, FilterPermanent filter, Duration duration, boolean loseColor, boolean loseName, boolean loseTypes) {
|
||||
public BecomesCreatureAllEffect(Token token, String theyAreStillType,
|
||||
FilterPermanent filter, Duration duration, boolean loseColor, boolean loseName, boolean loseTypes) {
|
||||
super(duration, Outcome.BecomeCreature);
|
||||
this.token = token;
|
||||
this.theyAreStillType = theyAreStillType;
|
||||
|
|
@ -57,7 +60,8 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
|
|||
public void init(Ability source, Game game) {
|
||||
super.init(source, game);
|
||||
if (this.affectedObjectsSet) {
|
||||
for (Permanent perm : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
|
||||
for (Permanent perm : game.getBattlefield().getActivePermanents(
|
||||
filter, source.getControllerId(), source.getSourceId(), game)) {
|
||||
affectedObjectList.add(new MageObjectReference(perm, game));
|
||||
}
|
||||
}
|
||||
|
|
@ -76,7 +80,8 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
|
|||
affectedPermanents.add(ref.getPermanent(game));
|
||||
}
|
||||
} else {
|
||||
affectedPermanents = new HashSet<>(game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game));
|
||||
affectedPermanents = new HashSet<>(game.getBattlefield()
|
||||
.getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game));
|
||||
}
|
||||
|
||||
for (Permanent permanent : affectedPermanents) {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,13 @@ public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl {
|
|||
this.loseType = loseType;
|
||||
staticText = text;
|
||||
}
|
||||
|
||||
public BecomesCreatureAttachedEffect(Token token, String text, Duration duration, LoseType loseType, Outcome outcome) {
|
||||
super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, outcome);
|
||||
this.token = token;
|
||||
this.loseType = loseType;
|
||||
staticText = text;
|
||||
}
|
||||
|
||||
public BecomesCreatureAttachedEffect(final BecomesCreatureAttachedEffect effect) {
|
||||
super(effect);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue