mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 02:30:08 -08:00
refactor: shared logic for diff implementation of isInUseableZone, improved docs and readability;
This commit is contained in:
parent
57ef74da90
commit
d49ff89a81
76 changed files with 285 additions and 273 deletions
|
|
@ -103,7 +103,7 @@ class AjanisLastStandTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ class AthreosDiesCreatureTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ class AvacynsCollarTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ class BereavementTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ class DeathTyrantTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ class DeathsPresenceTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ class DiregrafCaptainTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
@ -92,7 +92,7 @@ class FalkenrathNobleTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,8 +97,8 @@ class GraveBetrayalTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -77,8 +77,8 @@ class GravePactTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -86,8 +86,8 @@ class GutterGrimeTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ class HatefulEidolonTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ class InfestedThrinaxTriggeredAbility extends DelayedTriggeredAbility {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,8 +101,8 @@ class LuminousBroodmothTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -103,8 +103,8 @@ class LyndeCheerfulTormentorCurseDiesTriggeredAbility extends TriggeredAbilityIm
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -104,8 +104,8 @@ class MarchesaTheBlackRoseTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -206,8 +206,8 @@ class MariTheKillingQuillCreatureDiesAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -91,8 +91,8 @@ class MartyrsBondTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ class MassacreGirlDelayedTriggeredAbility extends DelayedTriggeredAbility {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
@ -85,7 +85,7 @@ class MassacreWurmTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,11 +125,11 @@ class MillicentRestlessRevenantTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
if (event.getType() == GameEvent.EventType.ZONE_CHANGE) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
} else {
|
||||
return super.isInUseableZone(game, source, event);
|
||||
return super.isInUseableZone(game, sourceObject, event);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -110,8 +110,8 @@ class MimicVatTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ class MolderBeastTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
@ -94,7 +94,7 @@ class MycoidShepherdTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
@ -96,7 +96,7 @@ class NecroskitterTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ class NetherTraitorTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,8 +112,8 @@ class NimDeathmantleTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ class OrahSkyclaveHierophantTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,8 +110,8 @@ class PatronOfTheVeinCreatureDiesTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ class PiasRevolutionTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ class ProperBurialTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,8 +106,8 @@ class PurgatoryTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ class RemembranceTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,11 +114,11 @@ class RhukHexgoldNabberTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
if (event.getType() == GameEvent.EventType.ZONE_CHANGE) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
} else {
|
||||
return super.isInUseableZone(game, source, event);
|
||||
return super.isInUseableZone(game, sourceObject, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,8 +113,8 @@ class RienneAngelOfRebirthTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ class SacredGroundTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,8 +80,8 @@ class SangromancerFirstTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ class ScrapTrawlerTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ class ScrapheapTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ class SeerOfStolenSightTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -189,8 +189,8 @@ class ShelobChildOfUngoliantTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ class SlagstoneRefineryTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ class SlayersPlateTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,8 +108,8 @@ class SporogenesisTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -96,8 +96,8 @@ class SyrKonradTheGrimTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -109,8 +109,8 @@ class TheScorpionGodTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -171,8 +171,8 @@ class TheSkullsporeNexusTrigger extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -102,8 +102,8 @@ class TianaShipsCaretakerTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -101,8 +101,8 @@ class VerdantSuccessionTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ class VillageCannibalsTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,8 +70,8 @@ class VindictiveVampireTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ class ViridianRevelTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
@ -105,7 +105,7 @@ class XiraTheGoldenStingTriggeredAbility extends WhenTargetDiesDelayedTriggeredA
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,9 +86,6 @@ public interface Ability extends Controllable, Serializable {
|
|||
* Gets the id of the object which put this ability in motion.
|
||||
* <p>
|
||||
* WARNING, MageSingleton abilities contains dirty data here, so you can't use sourceId with it
|
||||
*
|
||||
* @return The {@link java.util.UUID} of the object this ability is
|
||||
* associated with.
|
||||
*/
|
||||
UUID getSourceId();
|
||||
|
||||
|
|
@ -358,16 +355,17 @@ public interface Ability extends Controllable, Serializable {
|
|||
* - for leave battlefield triggers - keep default + set setLeavesTheBattlefieldTrigger(true)
|
||||
* - for dies triggers - override and use TriggeredAbilityImpl.isInUseableZoneDiesTrigger inside + set setLeavesTheBattlefieldTrigger(true)
|
||||
*
|
||||
* @param source can be null for static continues effects checking like rules modification (example: Yixlid Jailer)
|
||||
* @param sourceObject can be null for static continues effects checking like rules modification (example: Yixlid Jailer)
|
||||
* @param event can be null for state base effects checking like "when you control seven or more" (example: Endrek Sahr, Master Breeder)
|
||||
*/
|
||||
boolean isInUseableZone(Game game, MageObject source, GameEvent event);
|
||||
boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event);
|
||||
|
||||
/**
|
||||
* Returns true if the source object has currently the ability (e.g. The
|
||||
* object can have lost all or some abilities for some time (e.g. Turn to
|
||||
* Frog)
|
||||
*/
|
||||
boolean hasSourceObjectAbility(Game game, MageObject source, GameEvent event);
|
||||
boolean hasSourceObjectAbility(Game game, MageObject sourceObject, GameEvent event);
|
||||
|
||||
/**
|
||||
* Returns true if the ability has a tap itself in their costs
|
||||
|
|
@ -485,6 +483,7 @@ public interface Ability extends Controllable, Serializable {
|
|||
|
||||
/**
|
||||
* Finds the source object regardless of its zcc. Can be LKI from battlefield in some cases.
|
||||
* Warning, do not use with singleton abilities
|
||||
*/
|
||||
MageObject getSourceObject(Game game);
|
||||
|
||||
|
|
|
|||
|
|
@ -1175,35 +1175,31 @@ public abstract class AbilityImpl implements Ability {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
if (!this.hasSourceObjectAbility(game, source, event)) {
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
if (!this.hasSourceObjectAbility(game, sourceObject, event)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// workaround for singleton abilities like Flying
|
||||
UUID affectedSourceId = getRealSourceObjectId(this, sourceObject);
|
||||
|
||||
// in command zone
|
||||
if (zone == Zone.COMMAND) {
|
||||
if (this.getSourceId() == null) { // commander effects
|
||||
if (affectedSourceId == null) {
|
||||
// commander effects
|
||||
return true;
|
||||
} else {
|
||||
MageObject object = game.getObject(affectedSourceId);
|
||||
// emblem/planes are always actual
|
||||
if (object instanceof Emblem || object instanceof Dungeon || object instanceof Plane) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
MageObject object = game.getObject(this.getSourceId());
|
||||
// emblem/planes are always actual
|
||||
if (object instanceof Emblem || object instanceof Dungeon || object instanceof Plane) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
UUID parameterSourceId;
|
||||
// for singleton abilities like Flying we can't rely on abilities' source because it's only once in continuous effects
|
||||
// so will use the sourceId of the object itself that came as a parameter if it is not null
|
||||
if (this instanceof MageSingleton && source != null) {
|
||||
parameterSourceId = source.getId();
|
||||
} else {
|
||||
parameterSourceId = getSourceId();
|
||||
}
|
||||
|
||||
// on entering permanents - must use static abilities like it already on battlefield
|
||||
// example: Tatterkite enters without counters from Mikaeus, the Unhallowed
|
||||
if (game.getPermanentEntering(parameterSourceId) != null && zone == Zone.BATTLEFIELD) {
|
||||
if (game.getPermanentEntering(affectedSourceId) != null && zone == Zone.BATTLEFIELD) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1212,7 +1208,7 @@ public abstract class AbilityImpl implements Ability {
|
|||
// any trigger conditions, and continuous effects that exist at that time are used to determine what the
|
||||
// trigger conditions are and what the objects involved in the event look like.
|
||||
// ...
|
||||
Zone sourceObjectZone = game.getState().getZone(parameterSourceId);
|
||||
Zone sourceObjectZone = game.getState().getZone(affectedSourceId);
|
||||
|
||||
// 603.10.
|
||||
// ...
|
||||
|
|
@ -1228,12 +1224,12 @@ public abstract class AbilityImpl implements Ability {
|
|||
// TODO: research "put into a hand or library"
|
||||
if (isTriggerCanFireAfterLeaveBattlefield(event)) {
|
||||
// permanents with normal triggers
|
||||
if (source instanceof Permanent) {
|
||||
if (sourceObject instanceof Permanent) { // TODO: use affectedSourceObject here?
|
||||
// support leaves-the-battlefield abilities
|
||||
sourceObjectZone = Zone.BATTLEFIELD;
|
||||
}
|
||||
// permanents with continues effects like Yixlid Jailer, see related code "isInUseableZone(game, null"
|
||||
if (source == null && this instanceof StaticAbility) {
|
||||
if (sourceObject == null && this instanceof StaticAbility) {
|
||||
sourceObjectZone = Zone.BATTLEFIELD;
|
||||
}
|
||||
}
|
||||
|
|
@ -1267,6 +1263,7 @@ public abstract class AbilityImpl implements Ability {
|
|||
// need research: is it ability's or event's task?
|
||||
// - ability's task: code like ability.setLookBackInTime
|
||||
// - event's task: code like current switch
|
||||
// TODO: alternative solution: replace check by source.isLeavesTheBattlefieldTrigger?
|
||||
switch (e.getType()) {
|
||||
case DESTROYED_PERMANENT:
|
||||
case EXPLOITED_CREATURE:
|
||||
|
|
@ -1279,31 +1276,43 @@ public abstract class AbilityImpl implements Ability {
|
|||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSourceObjectAbility(Game game, MageObject source, GameEvent event) {
|
||||
// if source object have this ability
|
||||
// uses for ability.isInUseableZone
|
||||
// replacement and other continues effects can be without source, but active (must return true)
|
||||
|
||||
MageObject object = source;
|
||||
// for singleton abilities like Flying we can't rely on abilities' source because it's only once in continuous effects
|
||||
/**
|
||||
* Find real source object id from any ability (real and singleton)
|
||||
*/
|
||||
protected static UUID getRealSourceObjectId(Ability sourceAbility, MageObject sourceObject) {
|
||||
// In singleton abilities like Flying we can't rely on ability's source because it's init only once in continuous effects
|
||||
// so will use the sourceId of the object itself that came as a parameter if it is not null
|
||||
if (sourceAbility instanceof MageSingleton && sourceObject != null) {
|
||||
return sourceObject.getId();
|
||||
} else {
|
||||
return sourceAbility.getSourceId();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSourceObjectAbility(Game game, MageObject sourceObject, GameEvent event) {
|
||||
MageObject object = sourceObject;
|
||||
if (object == null) {
|
||||
object = game.getPermanentEntering(getSourceId());
|
||||
if (object == null) {
|
||||
object = game.getObject(getSourceId());
|
||||
}
|
||||
}
|
||||
if (object != null) {
|
||||
if (object instanceof Permanent) {
|
||||
return object.hasAbility(this, game) && (
|
||||
((Permanent) object).isPhasedIn() || this.getWorksPhasedOut()
|
||||
);
|
||||
} else {
|
||||
// cards and other objects
|
||||
return object.hasAbility(this, game);
|
||||
}
|
||||
|
||||
if (object == null) {
|
||||
// replacement and other continues effects can be without source, but active (must return true all time)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!object.hasAbility(this, game)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// phase in/out support
|
||||
if (object instanceof Permanent) {
|
||||
return ((Permanent) object).isPhasedIn() || this.getWorksPhasedOut();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ public class TriggeredAbilities extends LinkedHashMap<String, TriggeredAbility>
|
|||
if (ability.isInUseableZone(game, object, event)) {
|
||||
if (event == null || !game.getContinuousEffects().preventedByRuleModification(event, ability, game, false)) {
|
||||
if (object != null) {
|
||||
boolean controllerSet = false;
|
||||
boolean controllerSet = false; // TODO: wtf?!?!? Need rework whole "set" logic here
|
||||
Set<UUID> eventTargets = CardUtil.getEventTargets(event);
|
||||
if (ability.getZone() != Zone.COMMAND
|
||||
&& event != null
|
||||
|
|
|
|||
|
|
@ -72,6 +72,15 @@ public interface TriggeredAbility extends Ability {
|
|||
* If true the game “looks back in time” to determine if those abilities trigger
|
||||
* This has to be set, if the triggered ability has to check back in time if the permanent the ability is connected
|
||||
* to had the ability on the battlefield while the trigger is checked
|
||||
* <p>
|
||||
* 603.6c
|
||||
* Leaves-the-battlefield abilities trigger when a permanent moves from the battlefield to another zone,
|
||||
* or when a phased-in permanent leaves the game because its owner leaves the game. These are written as,
|
||||
* but aren’t limited to, “When [this object] leaves the battlefield, . . .” or “Whenever [something] is put
|
||||
* into a graveyard from the battlefield, . . . .” (See also rule 603.10.) An ability that attempts to do
|
||||
* something to the card that left the battlefield checks for it only in the first zone that it went to.
|
||||
* An ability that triggers when a card is put into a certain zone “from anywhere” is never treated as a
|
||||
* leaves-the-battlefield ability, even if an object is put into that zone from the battlefield.
|
||||
*/
|
||||
void setLeavesTheBattlefieldTrigger(boolean leavesTheBattlefieldTrigger);
|
||||
|
||||
|
|
|
|||
|
|
@ -348,73 +348,61 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
|
||||
/**
|
||||
* 603.6. Trigger events that involve objects changing zones are called
|
||||
* “zone-change triggers.” Many abilities with zone-change triggers
|
||||
* attempt to do something to that object after it changes zones. During
|
||||
* resolution, these abilities look for the object in the zone that it
|
||||
* moved to. If the object is unable to be found in the zone it went to,
|
||||
* the part of the ability attempting to do something to the object will
|
||||
* fail to do anything. The ability could be unable to find the object
|
||||
* because the object never entered the specified zone, because it left
|
||||
* the zone before the ability resolved, or because it is in a zone that
|
||||
* is hidden from a player, such as a library or an opponent's hand.
|
||||
* (This rule applies even if the object leaves the zone and returns
|
||||
* again before the ability resolves.) The most common zone-change
|
||||
* triggers are enters-the-battlefield triggers and
|
||||
* leaves-the-battlefield triggers.
|
||||
*
|
||||
* from:
|
||||
* http://www.mtgsalvation.com/forums/magic-fundamentals/magic-rulings/magic-rulings-archives/537065-ixidron-and-kozilek
|
||||
* There are two types of triggers that involve the graveyard: dies
|
||||
* triggers (which are a subset of leave-the-battlefield triggers) and
|
||||
* put into the graveyard from anywhere triggers.
|
||||
*
|
||||
* The former triggers trigger based on the game state prior to the move
|
||||
* where the Kozilek permanent is face down and has no abilities. The
|
||||
* latter triggers trigger from the game state after the move where the
|
||||
* Kozilek card is itself and has the ability.
|
||||
*/
|
||||
// workaround for singleton abilities like Flying
|
||||
UUID affectedSourceId = getRealSourceObjectId(this, sourceObject);
|
||||
|
||||
// process events from other objects
|
||||
Set<UUID> eventTargets = CardUtil.getEventTargets(event);
|
||||
if (!eventTargets.contains(getSourceId())) {
|
||||
return super.isInUseableZone(game, source, event);
|
||||
}
|
||||
// 603.6
|
||||
// Trigger events that involve objects changing zones are called "zone-change triggers." Many abilities with
|
||||
// zone-change triggers attempt to do something to that object after it changes zones. During resolution,
|
||||
// these abilities look for the object in the zone that it moved to. If the object is unable to be found
|
||||
// in the zone it went to, the part of the ability attempting to do something to the object will fail to
|
||||
// do anything. The ability could be unable to find the object because the object never entered the
|
||||
// specified zone, because it left the zone before the ability resolved, or because it is in a zone that
|
||||
// is hidden from a player, such as a library or an opponent’s hand. (This rule applies even if the
|
||||
// object leaves the zone and returns again before the ability resolves.) The most common zone-change
|
||||
// triggers are enters-the-battlefield triggers and leaves-the-battlefield triggers.
|
||||
|
||||
// process events from own object
|
||||
// There are possible two different use cases:
|
||||
// * look in current game state (normal events):
|
||||
// * look back in time (leaves battlefield, dies, etc);
|
||||
|
||||
// inject process of "look back in time" events
|
||||
// TODO: need sync code with AbilityImpl.isInUseableZone
|
||||
switch (event.getType()) {
|
||||
case ZONE_CHANGE:
|
||||
ZoneChangeEvent zce = (ZoneChangeEvent) event;
|
||||
if (eventTargets.contains(getSourceId()) && !zce.getToZone().isPublicZone()) {
|
||||
// If an ability triggers when the object that has it is put into a hidden zone from a graveyard,
|
||||
// that ability triggers from the graveyard, (such as Golgari Brownscale),
|
||||
// Yixlid Jailer will prevent that ability from triggering.
|
||||
if (zce.getFromZone().match(Zone.GRAVEYARD)) {
|
||||
if (!CardUtil.cardHadAbility(this, game.getLastKnownInformationCard(getSourceId(), zce.getFromZone()), getSourceId(), game)) {
|
||||
return false;
|
||||
// TODO: need sync or shared code with AbilityImpl.isInUseableZone
|
||||
MageObject affectedSourceObject = sourceObject;
|
||||
if (event == null) {
|
||||
// state base triggers - use only actual state
|
||||
} else {
|
||||
// event triggers - can look back in time for some use cases
|
||||
switch (event.getType()) {
|
||||
case ZONE_CHANGE:
|
||||
ZoneChangeEvent zce = (ZoneChangeEvent) event;
|
||||
Set<UUID> eventTargets = CardUtil.getEventTargets(event);
|
||||
if (eventTargets.contains(getSourceId()) && !zce.getToZone().isPublicZone()) {
|
||||
// TODO: need research and share with AbilityImpl
|
||||
// If an ability triggers when the object that has it is put into a hidden zone from a graveyard,
|
||||
// that ability triggers from the graveyard, (such as Golgari Brownscale),
|
||||
// Yixlid Jailer will prevent that ability from triggering.
|
||||
if (zce.getFromZone().match(Zone.GRAVEYARD)) {
|
||||
if (!CardUtil.cardHadAbility(this, game.getLastKnownInformationCard(getSourceId(), zce.getFromZone()), getSourceId(), game)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isLeavesTheBattlefieldTrigger()) {
|
||||
source = zce.getTarget();
|
||||
}
|
||||
break;
|
||||
case DESTROYED_PERMANENT:
|
||||
case EXPLOITED_CREATURE:
|
||||
if (isLeavesTheBattlefieldTrigger()) {
|
||||
source = game.getLastKnownInformation(getSourceId(), Zone.BATTLEFIELD);
|
||||
}
|
||||
break;
|
||||
if (isLeavesTheBattlefieldTrigger() && game.checkShortLivingLKI(affectedSourceId, Zone.BATTLEFIELD)) {
|
||||
affectedSourceObject = game.getLastKnownInformation(affectedSourceId, Zone.BATTLEFIELD);
|
||||
}
|
||||
break;
|
||||
case DESTROYED_PERMANENT:
|
||||
case EXPLOITED_CREATURE:
|
||||
if (isLeavesTheBattlefieldTrigger() && game.checkShortLivingLKI(affectedSourceId, Zone.BATTLEFIELD)) {
|
||||
affectedSourceObject = game.getPermanentOrLKIBattlefield(affectedSourceId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// all other events from own object
|
||||
return super.isInUseableZone(game, source, event);
|
||||
return super.isInUseableZone(game, affectedSourceObject, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -464,23 +452,26 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge
|
|||
* (Similar logic must be used for any leaves-the-battlefield, but this method assumes to graveyard only.)
|
||||
* NOTE: If your ability functions from another zone (not battlefield) then must use standard logic, not this.
|
||||
*/
|
||||
public static boolean isInUseableZoneDiesTrigger(TriggeredAbility source, GameEvent event, Game game) {
|
||||
public static boolean isInUseableZoneDiesTrigger(TriggeredAbility sourceAbility, MageObject sourceObject, GameEvent event, Game game) {
|
||||
// runtime check: wrong trigger settings
|
||||
if (!source.isLeavesTheBattlefieldTrigger()) {
|
||||
if (!sourceAbility.isLeavesTheBattlefieldTrigger()) {
|
||||
throw new IllegalArgumentException("Wrong code usage: all dies triggers must use setLeavesTheBattlefieldTrigger(true) and override isInUseableZone - "
|
||||
+ source.getSourceObject(game) + " - " + source);
|
||||
+ sourceAbility.getSourceObject(game) + " - " + sourceAbility);
|
||||
}
|
||||
|
||||
// runtime check: wrong isInUseableZone for batch related triggers
|
||||
if (event instanceof BatchEvent) {
|
||||
throw new IllegalArgumentException("Wrong code usage: batch events unsupported here, possible miss of override isInUseableZone - "
|
||||
+ source.getSourceObject(game) + " - " + source);
|
||||
+ sourceAbility.getSourceObject(game) + " - " + sourceAbility);
|
||||
}
|
||||
|
||||
// Get the source permanent of the ability
|
||||
MageObject sourceObject = null;
|
||||
if (game.getState().getZone(source.getSourceId()) == Zone.BATTLEFIELD) {
|
||||
sourceObject = game.getPermanent(source.getSourceId());
|
||||
// workaround for singleton abilities like Flying
|
||||
UUID affectedSourceId = getRealSourceObjectId(sourceAbility, sourceObject);
|
||||
|
||||
// on permanent - can use actual or look back in time
|
||||
MageObject affectedObject = null;
|
||||
if (game.getState().getZone(affectedSourceId) == Zone.BATTLEFIELD) {
|
||||
affectedObject = game.getPermanent(affectedSourceId);
|
||||
} else {
|
||||
// The idea: short living LKI must help to find a moment in the inner of resolve
|
||||
// -
|
||||
|
|
@ -498,26 +489,29 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge
|
|||
// - ! empty stack ! graveyard ! no ! no ! no more to resolve
|
||||
// --!---------------!-------------!-----!-----------!
|
||||
// -
|
||||
if (game.checkShortLivingLKI(source.getSourceId(), Zone.BATTLEFIELD)) {
|
||||
sourceObject = game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD);
|
||||
}
|
||||
}
|
||||
if (sourceObject == null) { // source is no permanent
|
||||
sourceObject = game.getObject(source);
|
||||
if (sourceObject == null || sourceObject.isPermanent(game)) {
|
||||
return false; // No source object found => ability is not valid
|
||||
if (game.checkShortLivingLKI(affectedSourceId, Zone.BATTLEFIELD)) {
|
||||
affectedObject = game.getLastKnownInformation(affectedSourceId, Zone.BATTLEFIELD);
|
||||
}
|
||||
}
|
||||
|
||||
if (!source.hasSourceObjectAbility(game, sourceObject, event)) {
|
||||
if (affectedObject == null) {
|
||||
affectedObject = game.getObject(sourceAbility);
|
||||
if (affectedObject == null || affectedObject.isPermanent(game)) {
|
||||
// if it was a permanent, but now removed then ignore
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sourceAbility.hasSourceObjectAbility(game, affectedObject, event)) {
|
||||
return false; // the permanent does currently not have or before it dies the ability so no trigger
|
||||
}
|
||||
|
||||
// check now it is in graveyard (only if it is no token and was the target itself)
|
||||
if (source.getSourceId().equals(event.getTargetId()) // source is also the target
|
||||
&& !(sourceObject instanceof PermanentToken) // it's no token
|
||||
&& sourceObject.getZoneChangeCounter(game) + 1 == game.getState().getZoneChangeCounter(source.getSourceId())) { // It's in the next zone
|
||||
Zone after = game.getState().getZone(source.getSourceId());
|
||||
// TODO: need research
|
||||
if (affectedSourceId.equals(event.getTargetId()) // source is also the target
|
||||
&& !(affectedObject instanceof PermanentToken) // it's no token
|
||||
&& affectedObject.getZoneChangeCounter(game) + 1 == game.getState().getZoneChangeCounter(affectedSourceId)) { // It's in the next zone
|
||||
Zone after = game.getState().getZone(affectedSourceId);
|
||||
if (!Zone.GRAVEYARD.match(after)) { // Zone is not the graveyard
|
||||
return false; // Moving to graveyard was replaced so no trigger
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ public class DealtDamageAndDiedTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ public class DealtDamageAttachedAndDiedTriggeredAbility extends TriggeredAbility
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ public class DiesAttachedTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,11 +82,11 @@ public class DiesCreatureTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
if (this.zone == Zone.BATTLEFIELD) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
} else {
|
||||
return super.isInUseableZone(game, source, event);
|
||||
return super.isInUseableZone(game, sourceObject, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,10 +56,10 @@ public class DiesOneOrMoreTriggeredAbility extends TriggeredAbilityImpl implemen
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return ((ZoneChangeBatchEvent) event)
|
||||
.getEvents()
|
||||
.stream()
|
||||
.anyMatch(e -> TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, e, game));
|
||||
.anyMatch(e -> TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, e, game));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ public class DiesSourceTriggeredAbility extends ZoneChangeTriggeredAbility {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ public class DiesThisOrAnotherTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ public class PutIntoGraveFromAnywhereSourceTriggeredAbility extends ZoneChangeTr
|
|||
// * @return
|
||||
// */
|
||||
// @Override
|
||||
// public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
// public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
// if (game.getState().getZone(source.getId()).equals(Zone.GRAVEYARD)) {
|
||||
// return this.hasSourceObjectAbility(game, source, event);
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ public class PutIntoGraveFromBattlefieldAllTriggeredAbility extends TriggeredAbi
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ public class PutIntoGraveFromBattlefieldSourceTriggeredAbility extends Triggered
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,12 +107,12 @@ public class UntilYourNextTurnDelayedTriggeredAbility extends DelayedTriggeredAb
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
if (isLeavesTheBattlefieldTrigger()) {
|
||||
// TODO: leaves battlefield and die are not same! Is it possible make a diff logic?
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
} else {
|
||||
return super.isInUseableZone(game, source, event);
|
||||
return super.isInUseableZone(game, sourceObject, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,12 +137,12 @@ public class ConditionalInterveningIfTriggeredAbility extends TriggeredAbilityIm
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
if (isLeavesTheBattlefieldTrigger()) {
|
||||
// TODO: leaves battlefield and die are not same! Is it possible make a diff logic?
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
} else {
|
||||
return super.isInUseableZone(game, source, event);
|
||||
return super.isInUseableZone(game, sourceObject, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,12 +123,12 @@ public class ConditionalTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
if (isLeavesTheBattlefieldTrigger()) {
|
||||
// TODO: leaves battlefield and die are not same! Is it possible make a diff logic?
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
} else {
|
||||
return super.isInUseableZone(game, source, event);
|
||||
return super.isInUseableZone(game, sourceObject, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ class HauntExileAbility extends ZoneChangeTriggeredAbility {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
boolean fromOK = true;
|
||||
Permanent sourcePermanent = (Permanent) game.getLastKnownInformation(sourceId, Zone.BATTLEFIELD);
|
||||
if (creatureHaunt
|
||||
|
|
|
|||
|
|
@ -127,15 +127,15 @@ public class OrTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
boolean res = false;
|
||||
for (TriggeredAbility ability : triggeredAbilities) {
|
||||
// TODO: call full inner trigger instead like ability.isInUseableZone()?! Need research why it fails
|
||||
if (ability.isLeavesTheBattlefieldTrigger()) {
|
||||
// TODO: leaves battlefield and die are not same! Is it possible make a diff logic?
|
||||
res |= TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
res |= TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
} else {
|
||||
res |= super.isInUseableZone(game, source, event);
|
||||
res |= super.isInUseableZone(game, sourceObject, event);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ class MonarchDrawTriggeredAbility extends BeginningOfEndStepTriggeredAbility {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -108,7 +108,7 @@ class MonarchDealsCombatDamageToAPlayerTriggeredAbility extends TriggeredAbility
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -96,8 +96,6 @@ public class ZoneChangeEvent extends GameEvent {
|
|||
|
||||
/**
|
||||
* Source ability of the event, can be null in rare cases
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Ability getSource() {
|
||||
return this.source;
|
||||
|
|
@ -105,6 +103,9 @@ public class ZoneChangeEvent extends GameEvent {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + ", from " + getFromZone() + " to " + getToZone();
|
||||
return super.toString()
|
||||
+ ", from " + getFromZone() + " to " + getToZone()
|
||||
+ ", " + (this.target == null ? "no target" : "target " + this.target)
|
||||
+ ", " + (this.source == null ? "no source" : "source " + this.source);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -517,12 +517,12 @@ public class StackAbility extends StackObjectImpl implements Ability {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSourceObjectAbility(Game game, MageObject source, GameEvent event) {
|
||||
public boolean hasSourceObjectAbility(Game game, MageObject sourceObject, GameEvent event) {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue