mirror of
https://github.com/magefree/mage.git
synced 2025-12-26 13:32:06 -08:00
* No more continuous effects stay on battlefield after player leave the game;
Test framework: added real time check for player in game or not;
This commit is contained in:
parent
00633ce055
commit
9ef2e0bda7
5 changed files with 244 additions and 25 deletions
|
|
@ -1,10 +1,13 @@
|
|||
package mage.abilities.effects;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.MageSingleton;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.util.*;
|
||||
|
|
@ -93,6 +96,22 @@ public class ContinuousEffectsList<T extends ContinuousEffect> extends ArrayList
|
|||
}
|
||||
|
||||
private boolean isInactive(T effect, Game game) {
|
||||
// ends all inactive effects -- calls on player leave or apply new effect
|
||||
if (game.getState().isGameOver()) {
|
||||
// no need to remove effects after end -- users and tests must see last game state
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
800.4a When a player leaves the game, all objects (see rule 109) owned by that player leave the game and any effects
|
||||
which give that player control of any objects or players end. Then, if that player controlled any objects on the stack
|
||||
not represented by cards, those objects cease to exist. Then, if there are any objects still controlled by that player,
|
||||
those objects are exiled. This is not a state-based action. It happens as soon as the player leaves the game.
|
||||
If the player who left the game had priority at the time he or she left, priority passes to the next player in turn
|
||||
order who’s still in the game.
|
||||
*/
|
||||
// objects removes doing in player.leave() call... effects removes is here
|
||||
|
||||
Set<Ability> set = effectAbilityMap.get(effect.getId());
|
||||
if (set == null) {
|
||||
logger.debug("No abilities for effect found: " + effect.toString());
|
||||
|
|
@ -108,30 +127,62 @@ public class ContinuousEffectsList<T extends ContinuousEffect> extends ArrayList
|
|||
} else if (effect.isDiscarded()) {
|
||||
it.remove();
|
||||
} else {
|
||||
// 800.4k When a player leaves the game, any continuous effects with durations that last until that
|
||||
// player’s next turn or until a specific point in that turn will last until that turn would have begun.
|
||||
// They neither expire immediately nor last indefinitely.
|
||||
MageObject object = game.getObject(ability.getSourceId());
|
||||
boolean isObjectInGame = ability.getSourceId() == null || object != null; // Commander effects have no sourceId
|
||||
boolean isOwnerLeaveGame = false;
|
||||
if (object instanceof Card) {
|
||||
Player owner = game.getPlayer(((Card) object).getOwnerId());
|
||||
isOwnerLeaveGame = !owner.isInGame();
|
||||
}
|
||||
|
||||
switch (effect.getDuration()) {
|
||||
//
|
||||
case WhileOnBattlefield:
|
||||
case WhileInGraveyard:
|
||||
case WhileOnStack:
|
||||
if (ability.getSourceId() != null && game.getObject(ability.getSourceId()) == null) { // Commander effects have no sourceId
|
||||
it.remove(); // if the related source object does no longer exist in game - the effect has to be removed
|
||||
case EndOfStep:
|
||||
case EndOfCombat:
|
||||
case EndOfGame:
|
||||
// if the related source object does no longer exist in game - the effect has to be removed
|
||||
if (isOwnerLeaveGame || !isObjectInGame) {
|
||||
it.remove();
|
||||
}
|
||||
break;
|
||||
case OneUse:
|
||||
if (effect.isUsed()) {
|
||||
if (isOwnerLeaveGame || effect.isUsed()) {
|
||||
it.remove();
|
||||
}
|
||||
break;
|
||||
case Custom:
|
||||
// custom effects must process it's own inactive method (override), but can'be missied by devs
|
||||
if (isOwnerLeaveGame || effect.isInactive(ability, game)) {
|
||||
it.remove();
|
||||
}
|
||||
break;
|
||||
case EndOfTurn:
|
||||
// end of turn discards on cleanup steps
|
||||
// 514.2
|
||||
break;
|
||||
case UntilYourNextTurn:
|
||||
case UntilEndOfYourNextTurn:
|
||||
// until your turn effects continue until real turn reached, their used it's own inactive method
|
||||
// 514.2 Second, the following actions happen simultaneously: all damage marked on permanents
|
||||
// (including phased-out permanents) is removed and all "until end of turn" and "this turn" effects end.
|
||||
// This turn-based action doesn’t use the stack.
|
||||
if (effect.isInactive(ability, game)) {
|
||||
it.remove();
|
||||
}
|
||||
break;
|
||||
case UntilSourceLeavesBattlefield:
|
||||
if (Zone.BATTLEFIELD != game.getState().getZone(ability.getSourceId())) {
|
||||
if (isOwnerLeaveGame || Zone.BATTLEFIELD != game.getState().getZone(ability.getSourceId())) {
|
||||
it.remove();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Effects gets unknown duration " + effect.getDuration() + ", effect: " + effect.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue