refactor: shared logic for diff implementation of isInUseableZone, improved docs and readability;

This commit is contained in:
Oleg Agafonov 2024-11-30 03:26:03 +04:00
parent 57ef74da90
commit d49ff89a81
76 changed files with 285 additions and 273 deletions

View file

@ -103,7 +103,7 @@ class AjanisLastStandTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -157,7 +157,7 @@ class AthreosDiesCreatureTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -95,7 +95,7 @@ class AvacynsCollarTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -78,7 +78,7 @@ class BereavementTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -95,7 +95,7 @@ class DeathTyrantTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -82,7 +82,7 @@ class DeathsPresenceTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -103,7 +103,7 @@ class DiregrafCaptainTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -92,7 +92,7 @@ class FalkenrathNobleTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -97,8 +97,8 @@ class GraveBetrayalTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -77,8 +77,8 @@ class GravePactTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -86,8 +86,8 @@ class GutterGrimeTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -109,7 +109,7 @@ class HatefulEidolonTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -94,7 +94,7 @@ class InfestedThrinaxTriggeredAbility extends DelayedTriggeredAbility {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -101,8 +101,8 @@ class LuminousBroodmothTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -103,8 +103,8 @@ class LyndeCheerfulTormentorCurseDiesTriggeredAbility extends TriggeredAbilityIm
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
@Override @Override

View file

@ -104,8 +104,8 @@ class MarchesaTheBlackRoseTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -206,8 +206,8 @@ class MariTheKillingQuillCreatureDiesAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -91,8 +91,8 @@ class MartyrsBondTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -108,7 +108,7 @@ class MassacreGirlDelayedTriggeredAbility extends DelayedTriggeredAbility {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -85,7 +85,7 @@ class MassacreWurmTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -125,11 +125,11 @@ class MillicentRestlessRevenantTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @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) { if (event.getType() == GameEvent.EventType.ZONE_CHANGE) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} else { } else {
return super.isInUseableZone(game, source, event); return super.isInUseableZone(game, sourceObject, event);
} }
} }

View file

@ -110,8 +110,8 @@ class MimicVatTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -78,7 +78,7 @@ class MolderBeastTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -94,7 +94,7 @@ class MycoidShepherdTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -96,7 +96,7 @@ class NecroskitterTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -98,7 +98,7 @@ class NetherTraitorTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -112,8 +112,8 @@ class NimDeathmantleTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -98,7 +98,7 @@ class OrahSkyclaveHierophantTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -110,8 +110,8 @@ class PatronOfTheVeinCreatureDiesTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -131,7 +131,7 @@ class PiasRevolutionTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -80,7 +80,7 @@ class ProperBurialTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -106,8 +106,8 @@ class PurgatoryTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -96,7 +96,7 @@ class RemembranceTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -114,11 +114,11 @@ class RhukHexgoldNabberTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @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) { if (event.getType() == GameEvent.EventType.ZONE_CHANGE) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} else { } else {
return super.isInUseableZone(game, source, event); return super.isInUseableZone(game, sourceObject, event);
} }
} }
} }

View file

@ -113,8 +113,8 @@ class RienneAngelOfRebirthTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -79,7 +79,7 @@ class SacredGroundTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -80,8 +80,8 @@ class SangromancerFirstTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -94,7 +94,7 @@ class ScrapTrawlerTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -80,7 +80,7 @@ class ScrapheapTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -89,7 +89,7 @@ class SeerOfStolenSightTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -189,8 +189,8 @@ class ShelobChildOfUngoliantTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -83,7 +83,7 @@ class SlagstoneRefineryTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -92,7 +92,7 @@ class SlayersPlateTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -108,8 +108,8 @@ class SporogenesisTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -96,8 +96,8 @@ class SyrKonradTheGrimTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
@Override @Override

View file

@ -109,8 +109,8 @@ class TheScorpionGodTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -171,8 +171,8 @@ class TheSkullsporeNexusTrigger extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -102,8 +102,8 @@ class TianaShipsCaretakerTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -101,8 +101,8 @@ class VerdantSuccessionTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -78,7 +78,7 @@ class VillageCannibalsTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -70,8 +70,8 @@ class VindictiveVampireTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
@Override @Override

View file

@ -81,7 +81,7 @@ class ViridianRevelTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -105,7 +105,7 @@ class XiraTheGoldenStingTriggeredAbility extends WhenTargetDiesDelayedTriggeredA
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -86,9 +86,6 @@ public interface Ability extends Controllable, Serializable {
* Gets the id of the object which put this ability in motion. * Gets the id of the object which put this ability in motion.
* <p> * <p>
* WARNING, MageSingleton abilities contains dirty data here, so you can't use sourceId with it * 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(); UUID getSourceId();
@ -358,16 +355,17 @@ public interface Ability extends Controllable, Serializable {
* - for leave battlefield triggers - keep default + set setLeavesTheBattlefieldTrigger(true) * - for leave battlefield triggers - keep default + set setLeavesTheBattlefieldTrigger(true)
* - for dies triggers - override and use TriggeredAbilityImpl.isInUseableZoneDiesTrigger inside + 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 * 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 * object can have lost all or some abilities for some time (e.g. Turn to
* Frog) * 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 * 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. * 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); MageObject getSourceObject(Game game);

View file

@ -1175,35 +1175,31 @@ public abstract class AbilityImpl implements Ability {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
if (!this.hasSourceObjectAbility(game, source, event)) { if (!this.hasSourceObjectAbility(game, sourceObject, event)) {
return false; return false;
} }
// workaround for singleton abilities like Flying
UUID affectedSourceId = getRealSourceObjectId(this, sourceObject);
// in command zone // in command zone
if (zone == Zone.COMMAND) { if (zone == Zone.COMMAND) {
if (this.getSourceId() == null) { // commander effects if (affectedSourceId == null) {
// commander effects
return true; 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 // on entering permanents - must use static abilities like it already on battlefield
// example: Tatterkite enters without counters from Mikaeus, the Unhallowed // 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; 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 // 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. // 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. // 603.10.
// ... // ...
@ -1228,12 +1224,12 @@ public abstract class AbilityImpl implements Ability {
// TODO: research "put into a hand or library" // TODO: research "put into a hand or library"
if (isTriggerCanFireAfterLeaveBattlefield(event)) { if (isTriggerCanFireAfterLeaveBattlefield(event)) {
// permanents with normal triggers // permanents with normal triggers
if (source instanceof Permanent) { if (sourceObject instanceof Permanent) { // TODO: use affectedSourceObject here?
// support leaves-the-battlefield abilities // support leaves-the-battlefield abilities
sourceObjectZone = Zone.BATTLEFIELD; sourceObjectZone = Zone.BATTLEFIELD;
} }
// permanents with continues effects like Yixlid Jailer, see related code "isInUseableZone(game, null" // 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; sourceObjectZone = Zone.BATTLEFIELD;
} }
} }
@ -1267,6 +1263,7 @@ public abstract class AbilityImpl implements Ability {
// need research: is it ability's or event's task? // need research: is it ability's or event's task?
// - ability's task: code like ability.setLookBackInTime // - ability's task: code like ability.setLookBackInTime
// - event's task: code like current switch // - event's task: code like current switch
// TODO: alternative solution: replace check by source.isLeavesTheBattlefieldTrigger?
switch (e.getType()) { switch (e.getType()) {
case DESTROYED_PERMANENT: case DESTROYED_PERMANENT:
case EXPLOITED_CREATURE: case EXPLOITED_CREATURE:
@ -1279,31 +1276,43 @@ public abstract class AbilityImpl implements Ability {
}); });
} }
@Override /**
public boolean hasSourceObjectAbility(Game game, MageObject source, GameEvent event) { * Find real source object id from any ability (real and singleton)
// if source object have this ability */
// uses for ability.isInUseableZone protected static UUID getRealSourceObjectId(Ability sourceAbility, MageObject sourceObject) {
// replacement and other continues effects can be without source, but active (must return true) // In singleton abilities like Flying we can't rely on ability's source because it's init only once in continuous effects
MageObject object = source;
// 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 // 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) { if (object == null) {
object = game.getPermanentEntering(getSourceId()); object = game.getPermanentEntering(getSourceId());
if (object == null) { if (object == null) {
object = game.getObject(getSourceId()); object = game.getObject(getSourceId());
} }
} }
if (object != null) {
if (object instanceof Permanent) { if (object == null) {
return object.hasAbility(this, game) && ( // replacement and other continues effects can be without source, but active (must return true all time)
((Permanent) object).isPhasedIn() || this.getWorksPhasedOut() return true;
);
} else {
// cards and other objects
return object.hasAbility(this, game);
}
} }
if (!object.hasAbility(this, game)) {
return false;
}
// phase in/out support
if (object instanceof Permanent) {
return ((Permanent) object).isPhasedIn() || this.getWorksPhasedOut();
}
return true; return true;
} }

View file

@ -209,7 +209,7 @@ public class TriggeredAbilities extends LinkedHashMap<String, TriggeredAbility>
if (ability.isInUseableZone(game, object, event)) { if (ability.isInUseableZone(game, object, event)) {
if (event == null || !game.getContinuousEffects().preventedByRuleModification(event, ability, game, false)) { if (event == null || !game.getContinuousEffects().preventedByRuleModification(event, ability, game, false)) {
if (object != null) { if (object != null) {
boolean controllerSet = false; boolean controllerSet = false; // TODO: wtf?!?!? Need rework whole "set" logic here
Set<UUID> eventTargets = CardUtil.getEventTargets(event); Set<UUID> eventTargets = CardUtil.getEventTargets(event);
if (ability.getZone() != Zone.COMMAND if (ability.getZone() != Zone.COMMAND
&& event != null && event != null

View file

@ -72,6 +72,15 @@ public interface TriggeredAbility extends Ability {
* If true the game looks back in time to determine if those abilities trigger * 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 * 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 * 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 arent 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); void setLeavesTheBattlefieldTrigger(boolean leavesTheBattlefieldTrigger);

View file

@ -348,73 +348,61 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
/** // workaround for singleton abilities like Flying
* 603.6. Trigger events that involve objects changing zones are called UUID affectedSourceId = getRealSourceObjectId(this, sourceObject);
* 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.
*/
// process events from other objects // 603.6
Set<UUID> eventTargets = CardUtil.getEventTargets(event); // Trigger events that involve objects changing zones are called "zone-change triggers." Many abilities with
if (!eventTargets.contains(getSourceId())) { // zone-change triggers attempt to do something to that object after it changes zones. During resolution,
return super.isInUseableZone(game, source, event); // 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 opponents 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 or shared code with AbilityImpl.isInUseableZone
// TODO: need sync code with AbilityImpl.isInUseableZone MageObject affectedSourceObject = sourceObject;
switch (event.getType()) { if (event == null) {
case ZONE_CHANGE: // state base triggers - use only actual state
ZoneChangeEvent zce = (ZoneChangeEvent) event; } else {
if (eventTargets.contains(getSourceId()) && !zce.getToZone().isPublicZone()) { // event triggers - can look back in time for some use cases
// If an ability triggers when the object that has it is put into a hidden zone from a graveyard, switch (event.getType()) {
// that ability triggers from the graveyard, (such as Golgari Brownscale), case ZONE_CHANGE:
// Yixlid Jailer will prevent that ability from triggering. ZoneChangeEvent zce = (ZoneChangeEvent) event;
if (zce.getFromZone().match(Zone.GRAVEYARD)) { Set<UUID> eventTargets = CardUtil.getEventTargets(event);
if (!CardUtil.cardHadAbility(this, game.getLastKnownInformationCard(getSourceId(), zce.getFromZone()), getSourceId(), game)) { if (eventTargets.contains(getSourceId()) && !zce.getToZone().isPublicZone()) {
return false; // 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() && game.checkShortLivingLKI(affectedSourceId, Zone.BATTLEFIELD)) {
if (isLeavesTheBattlefieldTrigger()) { affectedSourceObject = game.getLastKnownInformation(affectedSourceId, Zone.BATTLEFIELD);
source = zce.getTarget(); }
} break;
break; case DESTROYED_PERMANENT:
case DESTROYED_PERMANENT: case EXPLOITED_CREATURE:
case EXPLOITED_CREATURE: if (isLeavesTheBattlefieldTrigger() && game.checkShortLivingLKI(affectedSourceId, Zone.BATTLEFIELD)) {
if (isLeavesTheBattlefieldTrigger()) { affectedSourceObject = game.getPermanentOrLKIBattlefield(affectedSourceId);
source = game.getLastKnownInformation(getSourceId(), Zone.BATTLEFIELD); }
} break;
break; }
} }
// all other events from own object return super.isInUseableZone(game, affectedSourceObject, event);
return super.isInUseableZone(game, source, event);
} }
@Override @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.) * (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. * 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 // 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 - " 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 // runtime check: wrong isInUseableZone for batch related triggers
if (event instanceof BatchEvent) { if (event instanceof BatchEvent) {
throw new IllegalArgumentException("Wrong code usage: batch events unsupported here, possible miss of override isInUseableZone - " 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 // workaround for singleton abilities like Flying
MageObject sourceObject = null; UUID affectedSourceId = getRealSourceObjectId(sourceAbility, sourceObject);
if (game.getState().getZone(source.getSourceId()) == Zone.BATTLEFIELD) {
sourceObject = game.getPermanent(source.getSourceId()); // 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 { } else {
// The idea: short living LKI must help to find a moment in the inner of resolve // 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 // - ! empty stack ! graveyard ! no ! no ! no more to resolve
// --!---------------!-------------!-----!-----------! // --!---------------!-------------!-----!-----------!
// - // -
if (game.checkShortLivingLKI(source.getSourceId(), Zone.BATTLEFIELD)) { if (game.checkShortLivingLKI(affectedSourceId, Zone.BATTLEFIELD)) {
sourceObject = game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD); affectedObject = game.getLastKnownInformation(affectedSourceId, 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 (!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 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) // 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 // TODO: need research
&& !(sourceObject instanceof PermanentToken) // it's no token if (affectedSourceId.equals(event.getTargetId()) // source is also the target
&& sourceObject.getZoneChangeCounter(game) + 1 == game.getState().getZoneChangeCounter(source.getSourceId())) { // It's in the next zone && !(affectedObject instanceof PermanentToken) // it's no token
Zone after = game.getState().getZone(source.getSourceId()); && 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 if (!Zone.GRAVEYARD.match(after)) { // Zone is not the graveyard
return false; // Moving to graveyard was replaced so no trigger return false; // Moving to graveyard was replaced so no trigger
} }

View file

@ -85,7 +85,7 @@ public class DealtDamageAndDiedTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -79,7 +79,7 @@ public class DealtDamageAttachedAndDiedTriggeredAbility extends TriggeredAbility
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -161,7 +161,7 @@ public class DiesAttachedTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -82,11 +82,11 @@ public class DiesCreatureTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
if (this.zone == Zone.BATTLEFIELD) { if (this.zone == Zone.BATTLEFIELD) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} else { } else {
return super.isInUseableZone(game, source, event); return super.isInUseableZone(game, sourceObject, event);
} }
} }
} }

View file

@ -56,10 +56,10 @@ public class DiesOneOrMoreTriggeredAbility extends TriggeredAbilityImpl implemen
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return ((ZoneChangeBatchEvent) event) return ((ZoneChangeBatchEvent) event)
.getEvents() .getEvents()
.stream() .stream()
.anyMatch(e -> TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, e, game)); .anyMatch(e -> TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, e, game));
} }
} }

View file

@ -42,7 +42,7 @@ public class DiesSourceTriggeredAbility extends ZoneChangeTriggeredAbility {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -66,7 +66,7 @@ public class DiesThisOrAnotherTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -41,7 +41,7 @@ public class PutIntoGraveFromAnywhereSourceTriggeredAbility extends ZoneChangeTr
// * @return // * @return
// */ // */
// @Override // @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)) { // if (game.getState().getZone(source.getId()).equals(Zone.GRAVEYARD)) {
// return this.hasSourceObjectAbility(game, source, event); // return this.hasSourceObjectAbility(game, source, event);
// } // }

View file

@ -66,7 +66,7 @@ public class PutIntoGraveFromBattlefieldAllTriggeredAbility extends TriggeredAbi
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -58,7 +58,7 @@ public class PutIntoGraveFromBattlefieldSourceTriggeredAbility extends Triggered
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game); return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} }
} }

View file

@ -107,12 +107,12 @@ public class UntilYourNextTurnDelayedTriggeredAbility extends DelayedTriggeredAb
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
if (isLeavesTheBattlefieldTrigger()) { if (isLeavesTheBattlefieldTrigger()) {
// TODO: leaves battlefield and die are not same! Is it possible make a diff logic? // 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 { } else {
return super.isInUseableZone(game, source, event); return super.isInUseableZone(game, sourceObject, event);
} }
} }
} }

View file

@ -137,12 +137,12 @@ public class ConditionalInterveningIfTriggeredAbility extends TriggeredAbilityIm
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
if (isLeavesTheBattlefieldTrigger()) { if (isLeavesTheBattlefieldTrigger()) {
// TODO: leaves battlefield and die are not same! Is it possible make a diff logic? // 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 { } else {
return super.isInUseableZone(game, source, event); return super.isInUseableZone(game, sourceObject, event);
} }
} }
} }

View file

@ -123,12 +123,12 @@ public class ConditionalTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
if (isLeavesTheBattlefieldTrigger()) { if (isLeavesTheBattlefieldTrigger()) {
// TODO: leaves battlefield and die are not same! Is it possible make a diff logic? // 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 { } else {
return super.isInUseableZone(game, source, event); return super.isInUseableZone(game, sourceObject, event);
} }
} }
} }

View file

@ -128,7 +128,7 @@ class HauntExileAbility extends ZoneChangeTriggeredAbility {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
boolean fromOK = true; boolean fromOK = true;
Permanent sourcePermanent = (Permanent) game.getLastKnownInformation(sourceId, Zone.BATTLEFIELD); Permanent sourcePermanent = (Permanent) game.getLastKnownInformation(sourceId, Zone.BATTLEFIELD);
if (creatureHaunt if (creatureHaunt

View file

@ -127,15 +127,15 @@ public class OrTriggeredAbility extends TriggeredAbilityImpl {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
boolean res = false; boolean res = false;
for (TriggeredAbility ability : triggeredAbilities) { for (TriggeredAbility ability : triggeredAbilities) {
// TODO: call full inner trigger instead like ability.isInUseableZone()?! Need research why it fails // TODO: call full inner trigger instead like ability.isInUseableZone()?! Need research why it fails
if (ability.isLeavesTheBattlefieldTrigger()) { if (ability.isLeavesTheBattlefieldTrigger()) {
// TODO: leaves battlefield and die are not same! Is it possible make a diff logic? // 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 { } else {
res |= super.isInUseableZone(game, source, event); res |= super.isInUseableZone(game, sourceObject, event);
} }
} }
return res; return res;

View file

@ -61,7 +61,7 @@ class MonarchDrawTriggeredAbility extends BeginningOfEndStepTriggeredAbility {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return true; return true;
} }
@ -108,7 +108,7 @@ class MonarchDealsCombatDamageToAPlayerTriggeredAbility extends TriggeredAbility
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return true; return true;
} }

View file

@ -96,8 +96,6 @@ public class ZoneChangeEvent extends GameEvent {
/** /**
* Source ability of the event, can be null in rare cases * Source ability of the event, can be null in rare cases
*
* @return
*/ */
public Ability getSource() { public Ability getSource() {
return this.source; return this.source;
@ -105,6 +103,9 @@ public class ZoneChangeEvent extends GameEvent {
@Override @Override
public String toString() { 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);
} }
} }

View file

@ -517,12 +517,12 @@ public class StackAbility extends StackObjectImpl implements Ability {
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
throw new UnsupportedOperationException("Not supported."); throw new UnsupportedOperationException("Not supported.");
} }
@Override @Override
public boolean hasSourceObjectAbility(Game game, MageObject source, GameEvent event) { public boolean hasSourceObjectAbility(Game game, MageObject sourceObject, GameEvent event) {
throw new UnsupportedOperationException("Not supported."); throw new UnsupportedOperationException("Not supported.");
} }