From 30afb11cd2f85fcddab1d63cee173199b7a032b7 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Fri, 5 Nov 2021 15:11:23 -0400 Subject: [PATCH] Implementing Daybound/Nightbound mechanic (#8200) * adding initial day/night support in game state * remove card exclusion for testing * added functional implementation to abilities from main branch * functionally implemented NightCondition * updated DayNightHint * added support for nightbound entering transformed at night * [MID] Implemented Unnatural Moonrise * [MID] Implemented The Celestus * added some docs * changed access for state day/night methods * added transformation to day/night switch * re-added unfinished filter, removed day/night cards * fixed some errors with transforming * added hints to all day/night cards * added transformation prevention plus a test * added Immerwolf test * [MID] Implemented Tovolar, Dire Overlord / Tovolar, The Midnight Scourge * refactored some cards to not use isTransformable * removed transformable parameter * simplified some transform code * fixed null pointer exception * removed unnecessary canTransform method * fixed a small error * reworked implementation of rule 701.28f * small change in transform logic * fixed failiing test * fixed verify failure * small merge change * added support for day/night switching based on spells cast * [MID] Implemented Curse of Leeches / Leeching Lurkers * moved day/night handling to untap step * added tests for cards which set day and trigger from a change * [MID] Implemented Ludevic, Necrogenius / Olag, Ludevic's Hubris * added support for creatures transforming to match day/night when necessary * fixed verify failures * fixed another verify failure * remove temporary verify skip * added transform message * removed unnecessary transform message * [MID] Implemented Angelic Enforcer / Enduring Angel * updated DayNightHint with more information * fixed verify failure * merge fix * fixed Startled Awake / Persistent Nightmare / Moonmist interaction * added another test for Moonmist * merge fix * merge fix * [MID] Implemented Baneblade Scoundrel / Baneclaw Marauder * merge fix * [MID] various text fixes * [MID] a few more text fixes * Merge fix * Improved transform game logs (hints, source), fixed day/night logs, fixed miss game param (due code style); * fixed a test failure * Merge fix Co-authored-by: Oleg Agafonov --- .../src/mage/cards/a/AberrantResearcher.java | 3 +- Mage.Sets/src/mage/cards/a/AccursedWitch.java | 1 - .../src/mage/cards/a/AfflictedDeserter.java | 1 - .../src/mage/cards/a/AmbitiousFarmhand.java | 3 +- .../src/mage/cards/a/AnakinSkywalker.java | 3 +- .../src/mage/cards/a/AngelicEnforcer.java | 60 +++ .../src/mage/cards/a/ArchangelAvacyn.java | 70 +--- .../src/mage/cards/a/ArchdemonOfGreed.java | 1 - Mage.Sets/src/mage/cards/a/ArchiveHaunt.java | 1 - .../src/mage/cards/a/ArguelsBloodFast.java | 3 +- .../mage/cards/a/ArlinnEmbracedByTheMoon.java | 3 +- Mage.Sets/src/mage/cards/a/ArlinnKord.java | 3 +- .../src/mage/cards/a/ArlinnTheMoonsFury.java | 1 - .../src/mage/cards/a/ArlinnThePacksHope.java | 1 - .../src/mage/cards/a/AshmouthDragon.java | 1 - Mage.Sets/src/mage/cards/a/AutumnalGloom.java | 3 +- .../mage/cards/a/AvacynianMissionaries.java | 3 +- Mage.Sets/src/mage/cards/a/AwokenDemon.java | 1 - .../mage/cards/a/AzcantaTheSunkenRuin.java | 1 - Mage.Sets/src/mage/cards/a/AzorsGateway.java | 3 +- .../src/mage/cards/b/BaithookAngler.java | 1 - Mage.Sets/src/mage/cards/b/BaneOfHanweir.java | 1 - .../src/mage/cards/b/BanebladeScoundrel.java | 57 +++ .../src/mage/cards/b/BaneclawMarauder.java | 126 +++++++ .../src/mage/cards/b/BenevolentGeist.java | 1 - .../src/mage/cards/b/BereavedSurvivor.java | 3 +- Mage.Sets/src/mage/cards/b/BirdAdmirer.java | 1 - .../src/mage/cards/b/BloodlineKeeper.java | 3 +- .../src/mage/cards/b/BloodswornSquire.java | 4 +- Mage.Sets/src/mage/cards/b/BrandedHowler.java | 8 - .../src/mage/cards/b/BreakneckRider.java | 1 - Mage.Sets/src/mage/cards/b/BrutalCathar.java | 1 - Mage.Sets/src/mage/cards/b/BurlyBreaker.java | 1 - .../src/mage/cards/c/CatapultFodder.java | 4 +- Mage.Sets/src/mage/cards/c/ChaliceOfLife.java | 4 +- .../mage/cards/c/ChandraFireOfKaladesh.java | 1 - .../src/mage/cards/c/ChandraRoaringFlame.java | 1 - .../src/mage/cards/c/ChapelShieldgeist.java | 1 - .../src/mage/cards/c/ChaplainOfAlms.java | 1 - .../src/mage/cards/c/ChillingChronicle.java | 3 +- .../src/mage/cards/c/ChosenOfMarkov.java | 3 +- .../src/mage/cards/c/CivilizedScholar.java | 7 +- .../src/mage/cards/c/CloisteredYouth.java | 3 +- .../src/mage/cards/c/ConduitOfStorms.java | 3 +- .../src/mage/cards/c/ConquerorsGalleon.java | 1 - .../src/mage/cards/c/ConvictedKiller.java | 7 - .../src/mage/cards/c/CovertCutpurse.java | 1 - .../src/mage/cards/c/CovetousCastaway.java | 1 - Mage.Sets/src/mage/cards/c/CovetousGeist.java | 1 - Mage.Sets/src/mage/cards/c/CreepingInn.java | 3 +- .../src/mage/cards/c/CryptolithFragment.java | 3 +- .../src/mage/cards/c/CuriousHomunculus.java | 3 +- .../src/mage/cards/c/CurseOfLeeches.java | 111 ++++++ Mage.Sets/src/mage/cards/d/DaringSleuth.java | 4 +- .../src/mage/cards/d/DauntlessAvenger.java | 1 - .../src/mage/cards/d/DaybreakRanger.java | 1 - .../src/mage/cards/d/DeathbonnetHulk.java | 1 - .../src/mage/cards/d/DeathbonnetSprout.java | 3 +- .../src/mage/cards/d/DelverOfSecrets.java | 39 +- Mage.Sets/src/mage/cards/d/Demilich.java | 2 +- .../mage/cards/d/DennickPiousApprentice.java | 1 - .../src/mage/cards/d/DepartedSoulkeeper.java | 1 - .../src/mage/cards/d/DevotedGrafkeeper.java | 1 - .../src/mage/cards/d/DireStrainBrawler.java | 1 - .../mage/cards/d/DireStrainDemolisher.java | 1 - .../src/mage/cards/d/DocentOfPerfection.java | 3 +- Mage.Sets/src/mage/cards/d/DormantGrove.java | 3 +- Mage.Sets/src/mage/cards/d/DowsingDagger.java | 3 +- .../src/mage/cards/d/DuskwatchRecruiter.java | 7 - .../src/mage/cards/e/EcstaticAwakener.java | 3 +- .../mage/cards/e/ElbrusTheBindingBlade.java | 6 +- .../src/mage/cards/e/ElusiveTormentor.java | 3 +- .../src/mage/cards/e/EmbodimentOfFlame.java | 1 - Mage.Sets/src/mage/cards/e/EnduringAngel.java | 110 ++++++ .../src/mage/cards/e/ExtricatorOfSin.java | 3 +- .../src/mage/cards/f/FangbladeBrigand.java | 1 - .../mage/cards/f/FangbladeEviscerator.java | 1 - .../src/mage/cards/f/FlameChanneler.java | 4 +- .../src/mage/cards/f/FlameheartWerewolf.java | 1 - .../src/mage/cards/f/FrenziedTrapbreaker.java | 1 - Mage.Sets/src/mage/cards/g/Galedrifter.java | 1 - .../src/mage/cards/g/GarrukRelentless.java | 3 +- .../src/mage/cards/g/GarrukTheVeilCursed.java | 1 - .../src/mage/cards/g/GatstafArsonists.java | 7 - Mage.Sets/src/mage/cards/g/GatstafHowler.java | 1 - .../src/mage/cards/g/GatstafRavagers.java | 1 - .../src/mage/cards/g/GatstafShepherd.java | 1 - .../src/mage/cards/g/GeierReachBandit.java | 1 - .../src/mage/cards/g/GhastlyHaunting.java | 1 - .../src/mage/cards/g/GhostlyCastigator.java | 1 - .../src/mage/cards/g/GideonBattleForged.java | 1 - .../src/mage/cards/g/GoldenGuardian.java | 1 - .../src/mage/cards/g/GraveyardGlutton.java | 1 - .../src/mage/cards/g/GraveyardTrespasser.java | 1 - .../mage/cards/g/GrimlockDinobotLeader.java | 5 +- .../mage/cards/g/GrimlockFerociousKing.java | 5 +- .../src/mage/cards/g/GrizzledAngler.java | 3 +- .../src/mage/cards/g/GrizzledOutcasts.java | 1 - .../mage/cards/g/GrowingRitesOfItlimoc.java | 3 +- Mage.Sets/src/mage/cards/h/HadanasClimb.java | 3 +- .../mage/cards/h/HanweirMilitiaCaptain.java | 3 +- .../src/mage/cards/h/HanweirWatchkeep.java | 1 - Mage.Sets/src/mage/cards/h/HarvestHand.java | 1 - .../mage/cards/h/HarvesttideAssailant.java | 1 - .../mage/cards/h/HarvesttideInfiltrator.java | 1 - .../cards/h/HawkinsNationalLaboratory.java | 5 +- .../src/mage/cards/h/HeirOfFalkenrath.java | 3 +- .../src/mage/cards/h/HeirloomMirror.java | 3 +- .../mage/cards/h/HermitOfTheNatterknolls.java | 2 - .../src/mage/cards/h/HinterlandHermit.java | 1 - .../src/mage/cards/h/HinterlandLogger.java | 1 - .../src/mage/cards/h/HinterlandScourge.java | 1 - .../src/mage/cards/h/HomicidalBrute.java | 21 +- .../mage/cards/h/HomicidalBruteWatcher.java | 23 -- .../src/mage/cards/h/HookHauntDrifter.java | 1 - Mage.Sets/src/mage/cards/h/HostileHostel.java | 7 +- Mage.Sets/src/mage/cards/h/HoundTamer.java | 1 - Mage.Sets/src/mage/cards/h/HowlpackAlpha.java | 1 - .../src/mage/cards/h/HowlpackOfEstwald.java | 1 - .../mage/cards/h/HuntmasterOfTheFells.java | 1 - .../src/mage/cards/i/InfectiousCurse.java | 1 - .../src/mage/cards/i/InheritedFiend.java | 1 - Mage.Sets/src/mage/cards/i/InsidiousMist.java | 3 +- .../src/mage/cards/i/InstigatorGang.java | 1 - Mage.Sets/src/mage/cards/i/Ironfang.java | 1 - .../src/mage/cards/j/JaceTelepathUnbound.java | 1 - .../src/mage/cards/j/JaceVrynsProdigy.java | 1 - .../mage/cards/j/JerrenCorruptedBishop.java | 3 +- .../src/mage/cards/j/JourneyToEternity.java | 1 - .../src/mage/cards/k/KessigForgemaster.java | 1 - .../src/mage/cards/k/KessigNaturalist.java | 1 - Mage.Sets/src/mage/cards/k/KessigProwler.java | 3 +- .../src/mage/cards/k/KindlyStranger.java | 3 +- .../src/mage/cards/k/KrallenhordeHowler.java | 1 - .../src/mage/cards/k/KrallenhordeKiller.java | 1 - .../src/mage/cards/k/KrallenhordeWantons.java | 1 - Mage.Sets/src/mage/cards/k/KruinOutlaw.java | 1 - .../src/mage/cards/k/KytheonHeroOfAkros.java | 1 - .../src/mage/cards/l/LambholtButcher.java | 8 - Mage.Sets/src/mage/cards/l/LambholtElder.java | 1 - .../src/mage/cards/l/LambholtPacifist.java | 1 - .../src/mage/cards/l/LeechingLurker.java | 43 +++ .../src/mage/cards/l/LegionsLanding.java | 3 +- .../mage/cards/l/LilianaHereticalHealer.java | 1 - Mage.Sets/src/mage/cards/l/LoneRider.java | 3 +- .../cards/l/LoneWolfOfTheNatterknolls.java | 2 - Mage.Sets/src/mage/cards/l/LordOfLineage.java | 1 - .../src/mage/cards/l/LordOfTheUlvenwald.java | 1 - Mage.Sets/src/mage/cards/l/LoyalCathar.java | 1 - .../src/mage/cards/l/LudevicNecrogenius.java | 61 +++ .../src/mage/cards/l/LudevicsAbomination.java | 1 - .../src/mage/cards/l/LudevicsTestSubject.java | 3 +- .../src/mage/cards/l/LuminousPhantom.java | 1 - .../src/mage/cards/l/LunarchVeteran.java | 1 - .../src/mage/cards/m/MalevolentHermit.java | 1 - .../src/mage/cards/m/MarkovsServant.java | 1 - .../src/mage/cards/m/MayorOfAvabruck.java | 1 - .../src/mage/cards/m/MercilessPredator.java | 1 - .../src/mage/cards/m/MondronenShaman.java | 1 - Mage.Sets/src/mage/cards/m/Moonmist.java | 19 +- Mage.Sets/src/mage/cards/m/MoonrageBrute.java | 1 - .../src/mage/cards/m/MoonragersSlash.java | 4 +- .../src/mage/cards/m/MoonriseIntruder.java | 1 - .../src/mage/cards/m/MoonscarredWerewolf.java | 1 - .../src/mage/cards/m/MorningApparition.java | 1 - .../src/mage/cards/m/MourningPatrol.java | 1 - .../src/mage/cards/m/MysteriousTome.java | 3 +- .../src/mage/cards/m/MysticMonstrosity.java | 1 - Mage.Sets/src/mage/cards/m/MysticSkull.java | 3 +- Mage.Sets/src/mage/cards/n/NeckBreaker.java | 1 - .../src/mage/cards/n/NeglectedHeirloom.java | 3 +- .../src/mage/cards/n/NicolBolasTheArisen.java | 1 - .../mage/cards/n/NicolBolasTheRavager.java | 1 - .../src/mage/cards/n/NightfallPredator.java | 1 - .../src/mage/cards/n/NissaVastwoodSeer.java | 3 +- .../src/mage/cards/o/OlagLudevicsHubris.java | 135 +++++++ .../mage/cards/o/OliviasMidnightAmbush.java | 4 +- Mage.Sets/src/mage/cards/o/OneOfThePack.java | 1 - .../mage/cards/o/OrmendahlTheCorrupter.java | 1 - .../src/mage/cards/o/OutlandLiberator.java | 4 +- .../mage/cards/o/OverwhelmedArchivist.java | 1 - Mage.Sets/src/mage/cards/p/PathOfMettle.java | 3 +- .../src/mage/cards/p/PersistentNightmare.java | 11 +- Mage.Sets/src/mage/cards/p/PiousEvangel.java | 3 +- Mage.Sets/src/mage/cards/p/PoppetFactory.java | 3 +- .../src/mage/cards/p/PoppetStitcher.java | 3 +- Mage.Sets/src/mage/cards/p/PrimalAmulet.java | 3 +- .../src/mage/cards/p/ProfaneProcession.java | 3 +- .../src/mage/cards/r/RampagingWerewolf.java | 1 - .../src/mage/cards/r/RavagerOfTheFells.java | 1 - Mage.Sets/src/mage/cards/r/RavenousDemon.java | 3 +- .../src/mage/cards/r/RecklessStormseeker.java | 1 - Mage.Sets/src/mage/cards/r/RecklessWaif.java | 1 - .../src/mage/cards/s/SageOfAncientLore.java | 1 - .../src/mage/cards/s/ScornedVillager.java | 1 - Mage.Sets/src/mage/cards/s/ScreechingBat.java | 83 +---- .../src/mage/cards/s/SeafaringWerewolf.java | 1 - .../src/mage/cards/s/SearchForAzcanta.java | 3 +- .../src/mage/cards/s/SeasonedCathar.java | 1 - Mage.Sets/src/mage/cards/s/ShadyTraveler.java | 1 - Mage.Sets/src/mage/cards/s/ShrillHowler.java | 3 +- .../src/mage/cards/s/SilverpeltWerewolf.java | 1 - Mage.Sets/src/mage/cards/s/SkinInvasion.java | 1 - Mage.Sets/src/mage/cards/s/SmolderingEgg.java | 3 +- .../src/mage/cards/s/SmolderingWerewolf.java | 3 +- .../src/mage/cards/s/SolitaryHunter.java | 1 - Mage.Sets/src/mage/cards/s/SoulSeizer.java | 22 +- .../src/mage/cards/s/SpellruneHowler.java | 1 - .../src/mage/cards/s/SpellrunePainter.java | 1 - .../src/mage/cards/s/StalkingPredator.java | 1 - .../src/mage/cards/s/StalkingVampire.java | 84 +---- Mage.Sets/src/mage/cards/s/StartledAwake.java | 33 +- .../src/mage/cards/s/StormChargedSlasher.java | 1 - Mage.Sets/src/mage/cards/s/StormTheVault.java | 3 +- .../src/mage/cards/s/StranglingGrasp.java | 1 - .../src/mage/cards/s/SuspiciousStowaway.java | 1 - .../src/mage/cards/t/TangleclawWerewolf.java | 3 +- Mage.Sets/src/mage/cards/t/TavernRuffian.java | 1 - Mage.Sets/src/mage/cards/t/TavernSmasher.java | 1 - .../src/mage/cards/t/TerrorOfKruinPass.java | 1 - .../src/mage/cards/t/ThaumaticCompass.java | 3 +- Mage.Sets/src/mage/cards/t/TheCelestus.java | 114 ++++++ Mage.Sets/src/mage/cards/t/TheUpsideDown.java | 5 +- Mage.Sets/src/mage/cards/t/ThingInTheIce.java | 3 +- .../src/mage/cards/t/ThrabenGargoyle.java | 3 +- .../src/mage/cards/t/ThrabenMilitia.java | 1 - Mage.Sets/src/mage/cards/t/ThrabenSentry.java | 3 +- .../src/mage/cards/t/TimberShredder.java | 1 - .../src/mage/cards/t/TirelessHauler.java | 1 - .../src/mage/cards/t/TormentedPariah.java | 1 - .../src/mage/cards/t/TovolarDireOverlord.java | 125 +++++++ .../cards/t/TovolarTheMidnightScourge.java | 78 ++++ .../src/mage/cards/t/TovolarsHuntmaster.java | 1 - .../src/mage/cards/t/TovolarsMagehunter.java | 1 - .../src/mage/cards/t/TovolarsPackleader.java | 1 - .../src/mage/cards/t/TownGossipmonger.java | 3 +- Mage.Sets/src/mage/cards/t/TreasureMap.java | 3 +- .../mage/cards/u/UlrichOfTheKrallenhorde.java | 1 - .../mage/cards/u/UlrichUncontestedAlpha.java | 1 - .../src/mage/cards/u/UlvenwaldCaptive.java | 3 +- .../src/mage/cards/u/UlvenwaldMystics.java | 1 - .../src/mage/cards/u/UlvenwaldOddity.java | 3 +- .../mage/cards/u/UlvenwaldPrimordials.java | 1 - .../src/mage/cards/u/UnhallowedCathar.java | 1 - .../src/mage/cards/u/UninvitedGeist.java | 3 +- .../src/mage/cards/u/UnnaturalMoonrise.java | 81 ++++ Mage.Sets/src/mage/cards/u/UntamedPup.java | 3 +- .../mage/cards/v/VancesBlastingCannons.java | 3 +- .../src/mage/cards/v/VengefulStrangler.java | 1 - .../src/mage/cards/v/VildinPackAlpha.java | 23 +- .../src/mage/cards/v/VildinPackOutcast.java | 3 +- .../src/mage/cards/v/VillageIronsmith.java | 1 - .../src/mage/cards/v/VillageMessenger.java | 1 - .../src/mage/cards/v/VillageReavers.java | 1 - Mage.Sets/src/mage/cards/v/VillageWatch.java | 1 - .../src/mage/cards/v/VillagersOfEstwald.java | 1 - .../src/mage/cards/v/VodalianWarMachine.java | 53 +-- .../src/mage/cards/v/VoldarenPariah.java | 3 +- Mage.Sets/src/mage/cards/w/Waildrifter.java | 1 - Mage.Sets/src/mage/cards/w/WaxingMoon.java | 65 ++-- Mage.Sets/src/mage/cards/w/WearyPrisoner.java | 1 + .../src/mage/cards/w/WeddingAnnouncement.java | 3 +- .../mage/cards/w/WerewolfOfAncientHunger.java | 1 - .../src/mage/cards/w/WerewolfRansacker.java | 1 - Mage.Sets/src/mage/cards/w/WestvaleAbbey.java | 3 +- Mage.Sets/src/mage/cards/w/WildbloodPack.java | 1 - Mage.Sets/src/mage/cards/w/WingShredder.java | 2 - .../src/mage/cards/w/WithengarUnbound.java | 2 - .../src/mage/cards/w/WolfbittenCaptive.java | 1 - .../src/mage/cards/w/WrathfulJailbreaker.java | 1 + .../src/mage/sets/InnistradMidnightHunt.java | 14 +- .../abilities/keywords/DayNightTest.java | 349 ++++++++++++++++++ .../abilities/keywords/TransformTest.java | 93 ++++- .../src/main/java/mage/abilities/Ability.java | 4 + .../main/java/mage/abilities/AbilityImpl.java | 21 ++ .../common/BecomeDayAsEntersAbility.java | 11 +- .../BecomesDayOrNightTriggeredAbility.java | 3 +- .../common/WerewolfBackTriggeredAbility.java | 2 +- .../common/WerewolfFrontTriggeredAbility.java | 2 +- .../condition/common/NightCondition.java | 3 +- .../effects/common/TransformSourceEffect.java | 57 +-- .../effects/common/TransformTargetEffect.java | 88 ----- .../abilities/hint/common/DayNightHint.java | 40 ++ .../mage/abilities/hint/common/NightHint.java | 27 -- .../abilities/keyword/DayboundAbility.java | 34 +- .../abilities/keyword/NightboundAbility.java | 41 +- .../abilities/keyword/TransformAbility.java | 1 - Mage/src/main/java/mage/cards/Card.java | 2 - Mage/src/main/java/mage/cards/CardImpl.java | 9 +- .../main/java/mage/cards/mock/MockCard.java | 1 - .../java/mage/cards/mock/MockSplitCard.java | 1 - Mage/src/main/java/mage/game/Game.java | 20 + Mage/src/main/java/mage/game/GameImpl.java | 51 ++- Mage/src/main/java/mage/game/GameState.java | 31 +- .../main/java/mage/game/events/GameEvent.java | 3 +- .../java/mage/game/permanent/Permanent.java | 16 +- .../mage/game/permanent/PermanentCard.java | 14 +- .../mage/game/permanent/PermanentImpl.java | 66 ++-- Mage/src/main/java/mage/game/stack/Spell.java | 5 - .../java/mage/game/stack/StackAbility.java | 10 + Mage/src/main/java/mage/game/turn/Turn.java | 48 +-- .../main/java/mage/game/turn/UntapStep.java | 20 +- .../main/java/mage/players/PlayerImpl.java | 6 +- Mage/src/main/java/mage/util/CardUtil.java | 1 - .../common/CastSpellLastTurnWatcher.java | 16 +- 305 files changed, 2174 insertions(+), 1064 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/a/AngelicEnforcer.java create mode 100644 Mage.Sets/src/mage/cards/b/BanebladeScoundrel.java create mode 100644 Mage.Sets/src/mage/cards/b/BaneclawMarauder.java create mode 100644 Mage.Sets/src/mage/cards/c/CurseOfLeeches.java create mode 100644 Mage.Sets/src/mage/cards/e/EnduringAngel.java delete mode 100644 Mage.Sets/src/mage/cards/h/HomicidalBruteWatcher.java create mode 100644 Mage.Sets/src/mage/cards/l/LeechingLurker.java create mode 100644 Mage.Sets/src/mage/cards/l/LudevicNecrogenius.java create mode 100644 Mage.Sets/src/mage/cards/o/OlagLudevicsHubris.java create mode 100644 Mage.Sets/src/mage/cards/t/TheCelestus.java create mode 100644 Mage.Sets/src/mage/cards/t/TovolarDireOverlord.java create mode 100644 Mage.Sets/src/mage/cards/t/TovolarTheMidnightScourge.java create mode 100644 Mage.Sets/src/mage/cards/u/UnnaturalMoonrise.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DayNightTest.java delete mode 100644 Mage/src/main/java/mage/abilities/effects/common/TransformTargetEffect.java create mode 100644 Mage/src/main/java/mage/abilities/hint/common/DayNightHint.java delete mode 100644 Mage/src/main/java/mage/abilities/hint/common/NightHint.java diff --git a/Mage.Sets/src/mage/cards/a/AberrantResearcher.java b/Mage.Sets/src/mage/cards/a/AberrantResearcher.java index 04fb935339..154fbf7901 100644 --- a/Mage.Sets/src/mage/cards/a/AberrantResearcher.java +++ b/Mage.Sets/src/mage/cards/a/AberrantResearcher.java @@ -28,7 +28,6 @@ public final class AberrantResearcher extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.p.PerfectedForm.class; // Flying @@ -71,7 +70,7 @@ class AberrantResearcherEffect extends OneShotEffect { .noneMatch(card -> card.isInstantOrSorcery(game))) { return false; } - new TransformSourceEffect(true).apply(game, source); + new TransformSourceEffect().apply(game, source); return true; } diff --git a/Mage.Sets/src/mage/cards/a/AccursedWitch.java b/Mage.Sets/src/mage/cards/a/AccursedWitch.java index d157b752a2..bf88d81b5e 100644 --- a/Mage.Sets/src/mage/cards/a/AccursedWitch.java +++ b/Mage.Sets/src/mage/cards/a/AccursedWitch.java @@ -30,7 +30,6 @@ public final class AccursedWitch extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.i.InfectiousCurse.class; // Spells your opponents cast that target Accursed Witch cost {1} less to cast. diff --git a/Mage.Sets/src/mage/cards/a/AfflictedDeserter.java b/Mage.Sets/src/mage/cards/a/AfflictedDeserter.java index d340c1ace3..b5dc48b063 100644 --- a/Mage.Sets/src/mage/cards/a/AfflictedDeserter.java +++ b/Mage.Sets/src/mage/cards/a/AfflictedDeserter.java @@ -20,7 +20,6 @@ public final class AfflictedDeserter extends CardImpl { this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = mage.cards.w.WerewolfRansacker.class; this.power = new MageInt(3); diff --git a/Mage.Sets/src/mage/cards/a/AmbitiousFarmhand.java b/Mage.Sets/src/mage/cards/a/AmbitiousFarmhand.java index b292ac13b4..63256a3483 100644 --- a/Mage.Sets/src/mage/cards/a/AmbitiousFarmhand.java +++ b/Mage.Sets/src/mage/cards/a/AmbitiousFarmhand.java @@ -36,7 +36,6 @@ public final class AmbitiousFarmhand extends CardImpl { this.subtype.add(SubType.PEASANT); this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.s.SeasonedCathar.class; // When Ambitious Farmhand enters the battlefield, you may search your library for a basic Plains card, reveal it, put it into your hand, then shuffle. @@ -47,7 +46,7 @@ public final class AmbitiousFarmhand extends CardImpl { // Coven—{1}{W}{W}: Transform Ambitious Farmhand. Activate only if you control three or more creatures with different powers. this.addAbility(new TransformAbility()); this.addAbility(new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new TransformSourceEffect(true), + Zone.BATTLEFIELD, new TransformSourceEffect(), new ManaCostsImpl<>("{1}{W}{W}"), CovenCondition.instance ).setAbilityWord(AbilityWord.COVEN).addHint(CovenHint.instance)); } diff --git a/Mage.Sets/src/mage/cards/a/AnakinSkywalker.java b/Mage.Sets/src/mage/cards/a/AnakinSkywalker.java index e8a3e9c205..ad03a0f3c9 100644 --- a/Mage.Sets/src/mage/cards/a/AnakinSkywalker.java +++ b/Mage.Sets/src/mage/cards/a/AnakinSkywalker.java @@ -38,7 +38,6 @@ public final class AnakinSkywalker extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = mage.cards.d.DarthVader.class; // Whenever another creature dies, put a +1/+1 counter on Anakin Skywalker. @@ -82,7 +81,7 @@ class AnakinSkywalkerEffect extends ReplacementEffectImpl { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null) { permanent.regenerate(source, game); - return new TransformSourceEffect(true).apply(game, source); + return new TransformSourceEffect().apply(game, source); } return false; } diff --git a/Mage.Sets/src/mage/cards/a/AngelicEnforcer.java b/Mage.Sets/src/mage/cards/a/AngelicEnforcer.java new file mode 100644 index 0000000000..a1b545ee4c --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AngelicEnforcer.java @@ -0,0 +1,60 @@ +package mage.cards.a; + +import mage.MageInt; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.common.ControllerLifeCount; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.continuous.GainAbilityControllerEffect; +import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.HexproofAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AngelicEnforcer extends CardImpl { + + public AngelicEnforcer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); + + this.subtype.add(SubType.ANGEL); + this.power = new MageInt(0); + this.toughness = new MageInt(0); + this.color.setWhite(true); + this.nightCard = true; + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // You have hexproof. + this.addAbility(new SimpleStaticAbility(new GainAbilityControllerEffect(HexproofAbility.getInstance()))); + + // Angelic Enforcer's power and toughness are each equal to your life total. + this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect( + ControllerLifeCount.instance, Duration.EndOfGame + ).setText("{this}'s power and toughness are each equal to your life total"))); + + // Whenever Angelic Enforcer attacks, double your life total. + this.addAbility(new AttacksTriggeredAbility(new GainLifeEffect( + ControllerLifeCount.instance + ).setText("double your life total"))); + } + + private AngelicEnforcer(final AngelicEnforcer card) { + super(card); + } + + @Override + public AngelicEnforcer copy() { + return new AngelicEnforcer(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/ArchangelAvacyn.java b/Mage.Sets/src/mage/cards/a/ArchangelAvacyn.java index 3156f5621e..605363d487 100644 --- a/Mage.Sets/src/mage/cards/a/ArchangelAvacyn.java +++ b/Mage.Sets/src/mage/cards/a/ArchangelAvacyn.java @@ -1,30 +1,23 @@ - package mage.cards.a; -import java.util.UUID; import mage.MageInt; -import mage.MageObject; -import mage.abilities.Ability; import mage.abilities.common.DiesCreatureTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.delayed.AtTheBeginOfNextUpkeepDelayedTriggeredAbility; -import mage.abilities.effects.Effect; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.TransformTargetEffect; -import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.keyword.*; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; -import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; /** - * * @author fireshoes */ public final class ArchangelAvacyn extends CardImpl { @@ -37,14 +30,13 @@ public final class ArchangelAvacyn extends CardImpl { } public ArchangelAvacyn(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}"); addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.ANGEL); this.power = new MageInt(4); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = AvacynThePurifier.class; // Flash @@ -57,15 +49,18 @@ public final class ArchangelAvacyn extends CardImpl { this.addAbility(VigilanceAbility.getInstance()); // When Archangel Avacyn enters the battlefield, creatures you control gain indestructible until end of turn. - Ability ability = new EntersBattlefieldTriggeredAbility( - new GainAbilityAllEffect(IndestructibleAbility.getInstance(), Duration.EndOfTurn, - new FilterControlledCreaturePermanent("creatures you control")), false); - this.addAbility(ability); + this.addAbility(new EntersBattlefieldTriggeredAbility(new GainAbilityControlledEffect( + IndestructibleAbility.getInstance(), Duration.EndOfTurn, + StaticFilters.FILTER_PERMANENT_CREATURES + ), false)); // When a non-Angel creature you control dies, transform Archangel Avacyn at the beginning of the next upkeep. this.addAbility(new TransformAbility()); - this.addAbility(new DiesCreatureTriggeredAbility(new ArchangelAvacynEffect(), false, filter)); - + this.addAbility(new DiesCreatureTriggeredAbility( + new CreateDelayedTriggeredAbilityEffect( + new AtTheBeginOfNextUpkeepDelayedTriggeredAbility(new TransformSourceEffect()) + ).setText("transform {this} at the beginning of the next upkeep"), false, filter + ).setTriggerPhrase("When a non-Angel creature you control dies, ")); } private ArchangelAvacyn(final ArchangelAvacyn card) { @@ -77,36 +72,3 @@ public final class ArchangelAvacyn extends CardImpl { return new ArchangelAvacyn(this); } } - -class ArchangelAvacynEffect extends OneShotEffect { - - private static final String effectText = "transform {this} at the beginning of the next upkeep"; - - ArchangelAvacynEffect() { - super(Outcome.Benefit); - staticText = effectText; - } - - ArchangelAvacynEffect(ArchangelAvacynEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - MageObject sourceObject = source.getSourceObjectIfItStillExists(game); - if (sourceObject instanceof Permanent) { - //create delayed triggered ability - Effect effect = new TransformTargetEffect(false); - effect.setTargetPointer(new FixedTarget((Permanent) sourceObject, game)); - AtTheBeginOfNextUpkeepDelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextUpkeepDelayedTriggeredAbility(effect); - game.addDelayedTriggeredAbility(delayedAbility, source); - } - return true; - - } - - @Override - public ArchangelAvacynEffect copy() { - return new ArchangelAvacynEffect(this); - } -} diff --git a/Mage.Sets/src/mage/cards/a/ArchdemonOfGreed.java b/Mage.Sets/src/mage/cards/a/ArchdemonOfGreed.java index 24536e649a..b8127b2763 100644 --- a/Mage.Sets/src/mage/cards/a/ArchdemonOfGreed.java +++ b/Mage.Sets/src/mage/cards/a/ArchdemonOfGreed.java @@ -39,7 +39,6 @@ public final class ArchdemonOfGreed extends CardImpl { this.color.setBlack(true); this.nightCard = true; - this.transformable = true; this.power = new MageInt(9); this.toughness = new MageInt(9); diff --git a/Mage.Sets/src/mage/cards/a/ArchiveHaunt.java b/Mage.Sets/src/mage/cards/a/ArchiveHaunt.java index c026815658..7516cde5dc 100644 --- a/Mage.Sets/src/mage/cards/a/ArchiveHaunt.java +++ b/Mage.Sets/src/mage/cards/a/ArchiveHaunt.java @@ -26,7 +26,6 @@ public final class ArchiveHaunt extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); this.color.setBlue(true); - this.transformable = true; this.nightCard = true; // Flying diff --git a/Mage.Sets/src/mage/cards/a/ArguelsBloodFast.java b/Mage.Sets/src/mage/cards/a/ArguelsBloodFast.java index a590432997..7e6f55b301 100644 --- a/Mage.Sets/src/mage/cards/a/ArguelsBloodFast.java +++ b/Mage.Sets/src/mage/cards/a/ArguelsBloodFast.java @@ -29,7 +29,6 @@ public final class ArguelsBloodFast extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}"); addSuperType(SuperType.LEGENDARY); - this.transformable = true; this.secondSideCardClazz = mage.cards.t.TempleOfAclazotz.class; // {1}{B}, Pay 2 life: Draw a card. @@ -40,7 +39,7 @@ public final class ArguelsBloodFast extends CardImpl { // At the beginning of your upkeep, if you have 5 or less life, you may transform Arguel's Blood Fast. this.addAbility(new TransformAbility()); this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.YOU, true), + new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(), TargetController.YOU, true), FatefulHourCondition.instance, "At the beginning of your upkeep, if you have 5 or less life, you may transform {this}" )); diff --git a/Mage.Sets/src/mage/cards/a/ArlinnEmbracedByTheMoon.java b/Mage.Sets/src/mage/cards/a/ArlinnEmbracedByTheMoon.java index 1a2d5b1ae4..786926b468 100644 --- a/Mage.Sets/src/mage/cards/a/ArlinnEmbracedByTheMoon.java +++ b/Mage.Sets/src/mage/cards/a/ArlinnEmbracedByTheMoon.java @@ -35,7 +35,6 @@ public final class ArlinnEmbracedByTheMoon extends CardImpl { this.color.setGreen(true); this.nightCard = true; - this.transformable = true; // +1: Creatures you control get +1/+1 and gain trample until end of turn. Effect effect = new BoostControlledEffect(1, 1, Duration.EndOfTurn, StaticFilters.FILTER_PERMANENT_CREATURE); @@ -50,7 +49,7 @@ public final class ArlinnEmbracedByTheMoon extends CardImpl { this.addAbility(new TransformAbility()); ability = new LoyaltyAbility(new DamageTargetEffect(3), -1); ability.addTarget(new TargetAnyTarget()); - ability.addEffect(new TransformSourceEffect(false)); + ability.addEffect(new TransformSourceEffect()); this.addAbility(ability); // -6: You get an emblem with "Creatures you control have haste and '{T}: This creature deals damage equal to its power to any target.'" diff --git a/Mage.Sets/src/mage/cards/a/ArlinnKord.java b/Mage.Sets/src/mage/cards/a/ArlinnKord.java index 80b3c240fb..96f3e33cc2 100644 --- a/Mage.Sets/src/mage/cards/a/ArlinnKord.java +++ b/Mage.Sets/src/mage/cards/a/ArlinnKord.java @@ -32,7 +32,6 @@ public final class ArlinnKord extends CardImpl { this.addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.ARLINN); - this.transformable = true; this.secondSideCardClazz = ArlinnEmbracedByTheMoon.class; this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(3)); @@ -53,7 +52,7 @@ public final class ArlinnKord extends CardImpl { // 0: Create a 2/2 green Wolf creature token. Transform Arlinn Kord. this.addAbility(new TransformAbility()); ability = new LoyaltyAbility(new CreateTokenEffect(new WolfToken()), 0); - ability.addEffect(new TransformSourceEffect(true)); + ability.addEffect(new TransformSourceEffect()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/ArlinnTheMoonsFury.java b/Mage.Sets/src/mage/cards/a/ArlinnTheMoonsFury.java index 98e064a041..f6ce1f507a 100644 --- a/Mage.Sets/src/mage/cards/a/ArlinnTheMoonsFury.java +++ b/Mage.Sets/src/mage/cards/a/ArlinnTheMoonsFury.java @@ -31,7 +31,6 @@ public final class ArlinnTheMoonsFury extends CardImpl { this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4)); this.color.setRed(true); this.color.setGreen(true); - this.transformable = true; this.nightCard = true; // Nightbound diff --git a/Mage.Sets/src/mage/cards/a/ArlinnThePacksHope.java b/Mage.Sets/src/mage/cards/a/ArlinnThePacksHope.java index ee4f826916..36d2f2f472 100644 --- a/Mage.Sets/src/mage/cards/a/ArlinnThePacksHope.java +++ b/Mage.Sets/src/mage/cards/a/ArlinnThePacksHope.java @@ -35,7 +35,6 @@ public final class ArlinnThePacksHope extends CardImpl { this.addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.ARLINN); this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4)); - this.transformable = true; this.secondSideCardClazz = mage.cards.a.ArlinnTheMoonsFury.class; // Daybound diff --git a/Mage.Sets/src/mage/cards/a/AshmouthDragon.java b/Mage.Sets/src/mage/cards/a/AshmouthDragon.java index aa7fae2f96..f4c11eb6b5 100644 --- a/Mage.Sets/src/mage/cards/a/AshmouthDragon.java +++ b/Mage.Sets/src/mage/cards/a/AshmouthDragon.java @@ -26,7 +26,6 @@ public final class AshmouthDragon extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); this.color.setRed(true); - this.transformable = true; this.nightCard = true; // Flying diff --git a/Mage.Sets/src/mage/cards/a/AutumnalGloom.java b/Mage.Sets/src/mage/cards/a/AutumnalGloom.java index 41d6cb6a28..fbf7ac4320 100644 --- a/Mage.Sets/src/mage/cards/a/AutumnalGloom.java +++ b/Mage.Sets/src/mage/cards/a/AutumnalGloom.java @@ -25,7 +25,6 @@ public final class AutumnalGloom extends CardImpl { public AutumnalGloom(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}"); - this.transformable = true; this.secondSideCardClazz = AncientOfTheEquinox.class; // {B}: Put the top card of your library into your graveyard. @@ -33,7 +32,7 @@ public final class AutumnalGloom extends CardImpl { // Delirium — At the beginning of your end step, if there are four or more card types among cards in your graveyard, transform Autumnal Gloom. this.addAbility(new TransformAbility()); - Ability ability = new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), TargetController.YOU, DeliriumCondition.instance, false); + Ability ability = new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), TargetController.YOU, DeliriumCondition.instance, false); ability.setAbilityWord(AbilityWord.DELIRIUM); ability.addHint(CardTypesInGraveyardHint.YOU); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/a/AvacynianMissionaries.java b/Mage.Sets/src/mage/cards/a/AvacynianMissionaries.java index 4430839660..a9469350d3 100644 --- a/Mage.Sets/src/mage/cards/a/AvacynianMissionaries.java +++ b/Mage.Sets/src/mage/cards/a/AvacynianMissionaries.java @@ -27,12 +27,11 @@ public final class AvacynianMissionaries extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.l.LunarchInquisitors.class; // At the beginning of your end step, if Avacynian Missionaries is equipped, transform it. this.addAbility(new TransformAbility()); - this.addAbility(new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), TargetController.YOU, EquippedSourceCondition.instance, false)); + this.addAbility(new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), TargetController.YOU, EquippedSourceCondition.instance, false)); } diff --git a/Mage.Sets/src/mage/cards/a/AwokenDemon.java b/Mage.Sets/src/mage/cards/a/AwokenDemon.java index d7b9e1c6ed..dabf328e6c 100644 --- a/Mage.Sets/src/mage/cards/a/AwokenDemon.java +++ b/Mage.Sets/src/mage/cards/a/AwokenDemon.java @@ -20,7 +20,6 @@ public final class AwokenDemon extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); this.color.setBlack(true); - this.transformable = true; this.nightCard = true; } diff --git a/Mage.Sets/src/mage/cards/a/AzcantaTheSunkenRuin.java b/Mage.Sets/src/mage/cards/a/AzcantaTheSunkenRuin.java index 32fa65cc5f..4352f6c781 100644 --- a/Mage.Sets/src/mage/cards/a/AzcantaTheSunkenRuin.java +++ b/Mage.Sets/src/mage/cards/a/AzcantaTheSunkenRuin.java @@ -37,7 +37,6 @@ public final class AzcantaTheSunkenRuin extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; // (Transforms from Search for Azcanta)/ // {T} : Add {U}. diff --git a/Mage.Sets/src/mage/cards/a/AzorsGateway.java b/Mage.Sets/src/mage/cards/a/AzorsGateway.java index a8d4649e8b..9e97185af0 100644 --- a/Mage.Sets/src/mage/cards/a/AzorsGateway.java +++ b/Mage.Sets/src/mage/cards/a/AzorsGateway.java @@ -36,7 +36,6 @@ public final class AzorsGateway extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); this.addSuperType(SuperType.LEGENDARY); - this.transformable = true; this.secondSideCardClazz = mage.cards.s.SanctumOfTheSun.class; // {1}, {T}: Draw a card, then exile a card from your hand. If cards with five or more different converted mana costs are exiled with Azor's Gateway, you gain 5 life, untap Azor's Gateway, and transform it. @@ -94,7 +93,7 @@ class AzorsGatewayEffect extends OneShotEffect { if (usedCMC.size() > 4) { controller.gainLife(4, game, source); new UntapSourceEffect().apply(game, source); - new TransformSourceEffect(true).apply(game, source); + new TransformSourceEffect().apply(game, source); } } return true; diff --git a/Mage.Sets/src/mage/cards/b/BaithookAngler.java b/Mage.Sets/src/mage/cards/b/BaithookAngler.java index 200ccb38c7..123f91a139 100644 --- a/Mage.Sets/src/mage/cards/b/BaithookAngler.java +++ b/Mage.Sets/src/mage/cards/b/BaithookAngler.java @@ -23,7 +23,6 @@ public final class BaithookAngler extends CardImpl { this.subtype.add(SubType.PEASANT); this.power = new MageInt(2); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.h.HookHauntDrifter.class; // Disturb {1}{U} diff --git a/Mage.Sets/src/mage/cards/b/BaneOfHanweir.java b/Mage.Sets/src/mage/cards/b/BaneOfHanweir.java index a787fbe86e..db8f96ac32 100644 --- a/Mage.Sets/src/mage/cards/b/BaneOfHanweir.java +++ b/Mage.Sets/src/mage/cards/b/BaneOfHanweir.java @@ -22,7 +22,6 @@ public final class BaneOfHanweir extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(5); this.toughness = new MageInt(5); diff --git a/Mage.Sets/src/mage/cards/b/BanebladeScoundrel.java b/Mage.Sets/src/mage/cards/b/BanebladeScoundrel.java new file mode 100644 index 0000000000..fa410c3874 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BanebladeScoundrel.java @@ -0,0 +1,57 @@ +package mage.cards.b; + +import mage.MageInt; +import mage.abilities.common.BecomesBlockedSourceTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.abilities.keyword.DayboundAbility; +import mage.abilities.keyword.TransformAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.BlockingOrBlockedBySourcePredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BanebladeScoundrel extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + + static { + filter.add(BlockingOrBlockedBySourcePredicate.BLOCKING); + } + + public BanebladeScoundrel(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ROGUE); + this.subtype.add(SubType.WEREWOLF); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + this.secondSideCardClazz = mage.cards.b.BaneclawMarauder.class; + + // Whenever Baneblade Scoundrel becomes blocked, each creature blocking it gets -1/-1 until end of turn. + this.addAbility(new BecomesBlockedSourceTriggeredAbility(new BoostAllEffect( + -1, -1, Duration.EndOfTurn, filter, false + ).setText("each creature blocking it gets -1/-1 until end of turn"), false)); + + // Daybound + this.addAbility(new TransformAbility()); + this.addAbility(new DayboundAbility()); + } + + private BanebladeScoundrel(final BanebladeScoundrel card) { + super(card); + } + + @Override + public BanebladeScoundrel copy() { + return new BanebladeScoundrel(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/BaneclawMarauder.java b/Mage.Sets/src/mage/cards/b/BaneclawMarauder.java new file mode 100644 index 0000000000..2a2394c962 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BaneclawMarauder.java @@ -0,0 +1,126 @@ +package mage.cards.b; + +import mage.MageInt; +import mage.MageObjectReference; +import mage.abilities.common.BecomesBlockedSourceTriggeredAbility; +import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.effects.common.LoseLifeTargetControllerEffect; +import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.abilities.keyword.NightboundAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.WatcherScope; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.filter.predicate.permanent.BlockingOrBlockedBySourcePredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.watchers.Watcher; + +import java.util.*; + +/** + * @author TheElk801 + */ +public final class BaneclawMarauder extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + private static final FilterPermanent filter2 = new FilterCreaturePermanent("a creature blocking {this}"); + + static { + filter.add(BlockingOrBlockedBySourcePredicate.BLOCKING); + filter2.add(BaneclawMarauderPredicate.instance); + } + + public BaneclawMarauder(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); + + this.subtype.add(SubType.WEREWOLF); + this.power = new MageInt(5); + this.toughness = new MageInt(4); + this.color.setBlack(true); + this.nightCard = true; + + // Whenever Baneclaw Marauder becomes blocked, each creature blocking it gets -1/-1 until end of turn. + this.addAbility(new BecomesBlockedSourceTriggeredAbility(new BoostAllEffect( + -1, -1, Duration.EndOfTurn, filter, false + ).setText("each creature blocking it gets -1/-1 until end of turn"), false)); + + // Whenever a creature blocking Baneclaw Marauder dies, its controller loses 1 life. + this.addAbility(new DiesCreatureTriggeredAbility( + new LoseLifeTargetControllerEffect(1) + .setText("that creature's controller loses 1 life"), + false, filter2, true + ), new BaneclawMarauderWatcher()); + + // Nightbound + this.addAbility(new NightboundAbility()); + } + + private BaneclawMarauder(final BaneclawMarauder card) { + super(card); + } + + @Override + public BaneclawMarauder copy() { + return new BaneclawMarauder(this); + } +} + +enum BaneclawMarauderPredicate implements ObjectSourcePlayerPredicate { + instance; + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + return BaneclawMarauderWatcher.check(input.getSourceId(), input.getObject(), game); + } +} + +class BaneclawMarauderWatcher extends Watcher { + + private final Map> blockerMap = new HashMap<>(); + + BaneclawMarauderWatcher() { + super(WatcherScope.GAME); + } + + @Override + public void watch(GameEvent event, Game game) { + switch (event.getType()) { + case BLOCKER_DECLARED: + blockerMap + .computeIfAbsent(new MageObjectReference(event.getTargetId(), game), x -> new HashSet<>()) + .add(new MageObjectReference(event.getSourceId(), game)); + return; + case END_COMBAT_STEP_POST: + blockerMap.clear(); + return; + case REMOVED_FROM_COMBAT: + blockerMap + .values() + .stream() + .forEach(set -> set.removeIf(mor -> mor.refersTo(event.getTargetId(), game))); + } + } + + @Override + public void reset() { + super.reset(); + blockerMap.clear(); + } + + static boolean check(UUID sourceId, Permanent blocker, Game game) { + return game.getState() + .getWatcher(BaneclawMarauderWatcher.class) + .blockerMap + .getOrDefault(new MageObjectReference(sourceId, game), Collections.emptySet()) + .stream() + .anyMatch(mor -> mor.refersTo(blocker, game)); + } +} diff --git a/Mage.Sets/src/mage/cards/b/BenevolentGeist.java b/Mage.Sets/src/mage/cards/b/BenevolentGeist.java index f54295208e..814302e507 100644 --- a/Mage.Sets/src/mage/cards/b/BenevolentGeist.java +++ b/Mage.Sets/src/mage/cards/b/BenevolentGeist.java @@ -28,7 +28,6 @@ public final class BenevolentGeist extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); this.color.setBlue(true); - this.transformable = true; this.nightCard = true; // Flying diff --git a/Mage.Sets/src/mage/cards/b/BereavedSurvivor.java b/Mage.Sets/src/mage/cards/b/BereavedSurvivor.java index 69b57d3eda..463b071648 100644 --- a/Mage.Sets/src/mage/cards/b/BereavedSurvivor.java +++ b/Mage.Sets/src/mage/cards/b/BereavedSurvivor.java @@ -24,13 +24,12 @@ public final class BereavedSurvivor extends CardImpl { this.subtype.add(SubType.PEASANT); this.power = new MageInt(2); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.d.DauntlessAvenger.class; // When another creature you control dies, transform Bereaved Survivor. this.addAbility(new TransformAbility()); this.addAbility(new DiesCreatureTriggeredAbility( - new TransformSourceEffect(true), false, + new TransformSourceEffect(), false, StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE ).setTriggerPhrase("When another creature you control dies, ")); } diff --git a/Mage.Sets/src/mage/cards/b/BirdAdmirer.java b/Mage.Sets/src/mage/cards/b/BirdAdmirer.java index 3ee4bc0bd7..c6e18af59b 100644 --- a/Mage.Sets/src/mage/cards/b/BirdAdmirer.java +++ b/Mage.Sets/src/mage/cards/b/BirdAdmirer.java @@ -24,7 +24,6 @@ public final class BirdAdmirer extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(1); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = mage.cards.w.WingShredder.class; // Reach diff --git a/Mage.Sets/src/mage/cards/b/BloodlineKeeper.java b/Mage.Sets/src/mage/cards/b/BloodlineKeeper.java index 9091884499..f651d1a1ec 100644 --- a/Mage.Sets/src/mage/cards/b/BloodlineKeeper.java +++ b/Mage.Sets/src/mage/cards/b/BloodlineKeeper.java @@ -41,7 +41,6 @@ public final class BloodlineKeeper extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.l.LordOfLineage.class; this.addAbility(FlyingAbility.getInstance()); @@ -50,7 +49,7 @@ public final class BloodlineKeeper extends CardImpl { // {B}: Transform Bloodline Keeper. Activate this ability only if you control five or more Vampires. this.addAbility(new TransformAbility()); Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new TransformSourceEffect(true), + new TransformSourceEffect(), new ManaCostsImpl("{B}"), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 4)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/b/BloodswornSquire.java b/Mage.Sets/src/mage/cards/b/BloodswornSquire.java index baf0f7716b..a13ac16a0a 100644 --- a/Mage.Sets/src/mage/cards/b/BloodswornSquire.java +++ b/Mage.Sets/src/mage/cards/b/BloodswornSquire.java @@ -33,8 +33,6 @@ public final class BloodswornSquire extends CardImpl { this.subtype.add(SubType.SOLDIER); this.power = new MageInt(3); this.toughness = new MageInt(3); - - this.transformable = true; this.secondSideCardClazz = mage.cards.b.BloodswornKnight.class; this.addAbility(new TransformAbility()); @@ -47,7 +45,7 @@ public final class BloodswornSquire extends CardImpl { ability.addCost(new DiscardCardCost()); ability.addEffect(new TapSourceEffect().setText("tap it")); ability.addEffect(new ConditionalOneShotEffect( - new TransformSourceEffect(true, true), + new TransformSourceEffect(), new CardsInControllerGraveyardCondition(4, StaticFilters.FILTER_CARD_CREATURES), "Then if there are four or more creature cards in your graveyard, transform {this}" )); diff --git a/Mage.Sets/src/mage/cards/b/BrandedHowler.java b/Mage.Sets/src/mage/cards/b/BrandedHowler.java index 3b5fb571a4..4aac461937 100644 --- a/Mage.Sets/src/mage/cards/b/BrandedHowler.java +++ b/Mage.Sets/src/mage/cards/b/BrandedHowler.java @@ -2,18 +2,11 @@ package mage.cards.b; import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; -import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.WerewolfBackTriggeredAbility; -import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.common.TransformSourceEffect; -import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.TargetController; /** * @@ -30,7 +23,6 @@ public final class BrandedHowler extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Branded Howler. this.addAbility(new WerewolfBackTriggeredAbility()); diff --git a/Mage.Sets/src/mage/cards/b/BreakneckRider.java b/Mage.Sets/src/mage/cards/b/BreakneckRider.java index f0936aedf8..fbc0c3322e 100644 --- a/Mage.Sets/src/mage/cards/b/BreakneckRider.java +++ b/Mage.Sets/src/mage/cards/b/BreakneckRider.java @@ -21,7 +21,6 @@ public final class BreakneckRider extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.n.NeckBreaker.class; // At the beginning of each upkeep, if no spells were cast last turn, transform Breakneck Rider. diff --git a/Mage.Sets/src/mage/cards/b/BrutalCathar.java b/Mage.Sets/src/mage/cards/b/BrutalCathar.java index 902e0277d0..4b5037da2f 100644 --- a/Mage.Sets/src/mage/cards/b/BrutalCathar.java +++ b/Mage.Sets/src/mage/cards/b/BrutalCathar.java @@ -32,7 +32,6 @@ public final class BrutalCathar extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(2); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.m.MoonrageBrute.class; // When this creature enters the battlefield or transforms into Brutal Cathar, exile target creature an opponent controls until this creature leaves the battlefield. diff --git a/Mage.Sets/src/mage/cards/b/BurlyBreaker.java b/Mage.Sets/src/mage/cards/b/BurlyBreaker.java index 4f32772824..36fd55168c 100644 --- a/Mage.Sets/src/mage/cards/b/BurlyBreaker.java +++ b/Mage.Sets/src/mage/cards/b/BurlyBreaker.java @@ -24,7 +24,6 @@ public final class BurlyBreaker extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(6); this.toughness = new MageInt(5); - this.transformable = true; this.secondSideCardClazz = mage.cards.d.DireStrainDemolisher.class; // Ward {1} diff --git a/Mage.Sets/src/mage/cards/c/CatapultFodder.java b/Mage.Sets/src/mage/cards/c/CatapultFodder.java index 6c227759f6..3e5a9c90a6 100644 --- a/Mage.Sets/src/mage/cards/c/CatapultFodder.java +++ b/Mage.Sets/src/mage/cards/c/CatapultFodder.java @@ -28,14 +28,12 @@ public final class CatapultFodder extends CardImpl { this.subtype.add(SubType.ZOMBIE); this.power = new MageInt(1); this.toughness = new MageInt(5); - - this.transformable = true; this.secondSideCardClazz = mage.cards.c.CatapultCaptain.class; // At the beginning of combat on your turn, if you control three or more creatures that each have toughness greater than their power, transform Catapult Fodder. this.addAbility(new TransformAbility()); this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfCombatTriggeredAbility(new TransformSourceEffect(true, true), TargetController.YOU, false), + new BeginningOfCombatTriggeredAbility(new TransformSourceEffect(), TargetController.YOU, false), CatapultFodderCondition.instance, "At the beginning of combat on your turn, if you control three or more creatures that each have toughness greater than their power, transform {this}" )); diff --git a/Mage.Sets/src/mage/cards/c/ChaliceOfLife.java b/Mage.Sets/src/mage/cards/c/ChaliceOfLife.java index 50e1662643..b9a4a4768a 100644 --- a/Mage.Sets/src/mage/cards/c/ChaliceOfLife.java +++ b/Mage.Sets/src/mage/cards/c/ChaliceOfLife.java @@ -25,7 +25,6 @@ public final class ChaliceOfLife extends CardImpl { public ChaliceOfLife(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}"); - this.transformable = true; this.secondSideCardClazz = ChaliceOfDeath.class; this.addAbility(new TransformAbility()); @@ -66,8 +65,7 @@ class ChaliceOfLifeEffect extends OneShotEffect { // if you have at least 10 life more than your starting life total, transform Chalice of Life. if (player.getLife() >= game.getStartingLife() + 10) { - permanent.transform(game); - game.informPlayers(permanent.getName() + " transforms into " + permanent.getSecondCardFace().getName()); + permanent.transform(source, game); } } } diff --git a/Mage.Sets/src/mage/cards/c/ChandraFireOfKaladesh.java b/Mage.Sets/src/mage/cards/c/ChandraFireOfKaladesh.java index 217cd782ff..4a13c2dcbc 100644 --- a/Mage.Sets/src/mage/cards/c/ChandraFireOfKaladesh.java +++ b/Mage.Sets/src/mage/cards/c/ChandraFireOfKaladesh.java @@ -45,7 +45,6 @@ public final class ChandraFireOfKaladesh extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = ChandraRoaringFlame.class; // Whenever you cast a red spell, untap Chandra, Fire of Kaladesh. diff --git a/Mage.Sets/src/mage/cards/c/ChandraRoaringFlame.java b/Mage.Sets/src/mage/cards/c/ChandraRoaringFlame.java index 09ebc62e4d..0308ad1de7 100644 --- a/Mage.Sets/src/mage/cards/c/ChandraRoaringFlame.java +++ b/Mage.Sets/src/mage/cards/c/ChandraRoaringFlame.java @@ -33,7 +33,6 @@ public final class ChandraRoaringFlame extends CardImpl { this.color.setRed(true); this.nightCard = true; - this.transformable = true; this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4)); diff --git a/Mage.Sets/src/mage/cards/c/ChapelShieldgeist.java b/Mage.Sets/src/mage/cards/c/ChapelShieldgeist.java index 397c975f90..d5ac684e10 100644 --- a/Mage.Sets/src/mage/cards/c/ChapelShieldgeist.java +++ b/Mage.Sets/src/mage/cards/c/ChapelShieldgeist.java @@ -31,7 +31,6 @@ public final class ChapelShieldgeist extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); this.color.setWhite(true); - this.transformable = true; this.nightCard = true; // Flying diff --git a/Mage.Sets/src/mage/cards/c/ChaplainOfAlms.java b/Mage.Sets/src/mage/cards/c/ChaplainOfAlms.java index 73105c7bf2..68e2524ff5 100644 --- a/Mage.Sets/src/mage/cards/c/ChaplainOfAlms.java +++ b/Mage.Sets/src/mage/cards/c/ChaplainOfAlms.java @@ -25,7 +25,6 @@ public final class ChaplainOfAlms extends CardImpl { this.subtype.add(SubType.CLERIC); this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.c.ChapelShieldgeist.class; // First strike diff --git a/Mage.Sets/src/mage/cards/c/ChillingChronicle.java b/Mage.Sets/src/mage/cards/c/ChillingChronicle.java index 27b55de43e..12036ef274 100644 --- a/Mage.Sets/src/mage/cards/c/ChillingChronicle.java +++ b/Mage.Sets/src/mage/cards/c/ChillingChronicle.java @@ -22,13 +22,12 @@ public final class ChillingChronicle extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, ""); this.color.setBlue(true); - this.transformable = true; this.nightCard = true; // {1}, {T}: Tap target nonland permanent. Transform Chilling Chronicle. Ability ability = new SimpleActivatedAbility(new TapTargetEffect(), new GenericManaCost(1)); ability.addCost(new TapSourceCost()); - ability.addEffect(new TransformSourceEffect(false)); + ability.addEffect(new TransformSourceEffect()); ability.addTarget(new TargetNonlandPermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/ChosenOfMarkov.java b/Mage.Sets/src/mage/cards/c/ChosenOfMarkov.java index 43a0143df8..b52ded12bb 100644 --- a/Mage.Sets/src/mage/cards/c/ChosenOfMarkov.java +++ b/Mage.Sets/src/mage/cards/c/ChosenOfMarkov.java @@ -37,12 +37,11 @@ public final class ChosenOfMarkov extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.m.MarkovsServant.class; // {tap}, Tap an untapped Vampire you control: Transform Chosen of Markov. this.addAbility(new TransformAbility()); - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new TapSourceCost()); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new TapSourceCost()); ability.addCost(new TapTargetCost(new TargetControlledPermanent(filter))); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/CivilizedScholar.java b/Mage.Sets/src/mage/cards/c/CivilizedScholar.java index 2810cb556d..be6d388e56 100644 --- a/Mage.Sets/src/mage/cards/c/CivilizedScholar.java +++ b/Mage.Sets/src/mage/cards/c/CivilizedScholar.java @@ -1,4 +1,3 @@ - package mage.cards.c; import java.util.UUID; @@ -12,7 +11,6 @@ import mage.abilities.keyword.TransformAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.cards.h.HomicidalBruteWatcher; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Outcome; @@ -31,7 +29,6 @@ public final class CivilizedScholar extends CardImpl { this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.ADVISOR); - this.transformable = true; this.secondSideCardClazz = mage.cards.h.HomicidalBrute.class; this.power = new MageInt(0); @@ -39,7 +36,7 @@ public final class CivilizedScholar extends CardImpl { // {tap}: Draw a card, then discard a card. If a creature card is discarded this way, untap Civilized Scholar, then transform it. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CivilizedScholarEffect(), new TapSourceCost())); - this.addAbility(new TransformAbility(), new HomicidalBruteWatcher()); + this.addAbility(new TransformAbility()); } private CivilizedScholar(final CivilizedScholar card) { @@ -80,7 +77,7 @@ class CivilizedScholarEffect extends OneShotEffect { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { permanent.untap(game); - permanent.transform(game); + permanent.transform(source, game); } } return true; diff --git a/Mage.Sets/src/mage/cards/c/CloisteredYouth.java b/Mage.Sets/src/mage/cards/c/CloisteredYouth.java index 09cecfb911..d98ba02068 100644 --- a/Mage.Sets/src/mage/cards/c/CloisteredYouth.java +++ b/Mage.Sets/src/mage/cards/c/CloisteredYouth.java @@ -25,12 +25,11 @@ public final class CloisteredYouth extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.u.UnholyFiend.class; // At the beginning of your upkeep, you may transform Cloistered Youth. this.addAbility(new TransformAbility()); - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.YOU, true)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(), TargetController.YOU, true)); } private CloisteredYouth(final CloisteredYouth card) { diff --git a/Mage.Sets/src/mage/cards/c/ConduitOfStorms.java b/Mage.Sets/src/mage/cards/c/ConduitOfStorms.java index 80233f34d5..caa5492203 100644 --- a/Mage.Sets/src/mage/cards/c/ConduitOfStorms.java +++ b/Mage.Sets/src/mage/cards/c/ConduitOfStorms.java @@ -33,7 +33,6 @@ public final class ConduitOfStorms extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = ConduitOfEmrakul.class; // Whenever Conduit of Storms attacks, add {R} at the beginning of your next main phase this turn. @@ -44,7 +43,7 @@ public final class ConduitOfStorms extends CardImpl { this.addAbility(new AttacksTriggeredAbility(effect, false)); // {3}{R}{R}: Transform Conduit of Storms. this.addAbility(new TransformAbility()); - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new ManaCostsImpl("{3}{R}{R}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new ManaCostsImpl("{3}{R}{R}"))); } private ConduitOfStorms(final ConduitOfStorms card) { diff --git a/Mage.Sets/src/mage/cards/c/ConquerorsGalleon.java b/Mage.Sets/src/mage/cards/c/ConquerorsGalleon.java index bc45f90e58..854a195f39 100644 --- a/Mage.Sets/src/mage/cards/c/ConquerorsGalleon.java +++ b/Mage.Sets/src/mage/cards/c/ConquerorsGalleon.java @@ -27,7 +27,6 @@ public final class ConquerorsGalleon extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(10); - this.transformable = true; this.secondSideCardClazz = ConquerorsFoothold.class; // When Conqueror's Galleon attacks, exile it at the end of combat, then return it to the battlefield transformed under your control. diff --git a/Mage.Sets/src/mage/cards/c/ConvictedKiller.java b/Mage.Sets/src/mage/cards/c/ConvictedKiller.java index b81f22ce7e..ed0602e002 100644 --- a/Mage.Sets/src/mage/cards/c/ConvictedKiller.java +++ b/Mage.Sets/src/mage/cards/c/ConvictedKiller.java @@ -3,18 +3,12 @@ package mage.cards.c; import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; -import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.WerewolfFrontTriggeredAbility; -import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.TargetController; /** * @author fireshoes @@ -28,7 +22,6 @@ public final class ConvictedKiller extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.b.BrandedHowler.class; // At the beginning of each upkeep, if no spells were cast last turn, transform Convicted Killer. diff --git a/Mage.Sets/src/mage/cards/c/CovertCutpurse.java b/Mage.Sets/src/mage/cards/c/CovertCutpurse.java index 4659de478d..2065b9ee04 100644 --- a/Mage.Sets/src/mage/cards/c/CovertCutpurse.java +++ b/Mage.Sets/src/mage/cards/c/CovertCutpurse.java @@ -39,7 +39,6 @@ public final class CovertCutpurse extends CardImpl { this.subtype.add(SubType.ROGUE); this.power = new MageInt(2); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.c.CovetousGeist.class; // When Covert Cutpurse enters the battlefield, destroy target creature you don't control that was dealt damage this turn. diff --git a/Mage.Sets/src/mage/cards/c/CovetousCastaway.java b/Mage.Sets/src/mage/cards/c/CovetousCastaway.java index 9f1a218060..a92f0b9f97 100644 --- a/Mage.Sets/src/mage/cards/c/CovetousCastaway.java +++ b/Mage.Sets/src/mage/cards/c/CovetousCastaway.java @@ -24,7 +24,6 @@ public final class CovetousCastaway extends CardImpl { this.subtype.add(SubType.HUMAN); this.power = new MageInt(1); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.g.GhostlyCastigator.class; // When Covetous Castaway dies, mill three cards. diff --git a/Mage.Sets/src/mage/cards/c/CovetousGeist.java b/Mage.Sets/src/mage/cards/c/CovetousGeist.java index 7f1be06882..fbc4f1faec 100644 --- a/Mage.Sets/src/mage/cards/c/CovetousGeist.java +++ b/Mage.Sets/src/mage/cards/c/CovetousGeist.java @@ -25,7 +25,6 @@ public final class CovetousGeist extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); this.color.setBlack(true); - this.transformable = true; this.nightCard = true; // Flying diff --git a/Mage.Sets/src/mage/cards/c/CreepingInn.java b/Mage.Sets/src/mage/cards/c/CreepingInn.java index 791bfedba2..5ba7b0aa98 100644 --- a/Mage.Sets/src/mage/cards/c/CreepingInn.java +++ b/Mage.Sets/src/mage/cards/c/CreepingInn.java @@ -37,7 +37,6 @@ public final class CreepingInn extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(7); this.color.setBlack(true); - this.transformable = true; this.nightCard = true; // Whenever Creeping Inn attacks, you may exile a creature card from your graveyard. @@ -46,7 +45,7 @@ public final class CreepingInn extends CardImpl { this.addAbility(new AttacksTriggeredAbility(new CreepingInnEffect())); // {4}: Creeping Inn phases out. - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new PhaseOutSourceEffect(), new ManaCostsImpl("{4}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new PhaseOutSourceEffect(), new ManaCostsImpl<>("{4}"))); } private CreepingInn(final CreepingInn card) { diff --git a/Mage.Sets/src/mage/cards/c/CryptolithFragment.java b/Mage.Sets/src/mage/cards/c/CryptolithFragment.java index 8730d91c2e..8d7683d41b 100644 --- a/Mage.Sets/src/mage/cards/c/CryptolithFragment.java +++ b/Mage.Sets/src/mage/cards/c/CryptolithFragment.java @@ -25,7 +25,6 @@ public final class CryptolithFragment extends CardImpl { public CryptolithFragment(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); - this.transformable = true; this.secondSideCardClazz = mage.cards.a.AuroraOfEmrakul.class; // Cryptolith Fragment enters the battlefield tapped. @@ -39,7 +38,7 @@ public final class CryptolithFragment extends CardImpl { // At the beginning of your upkeep, if each player has 10 or less life, transform Cryptolith Fragment. this.addAbility(new TransformAbility()); this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.YOU, false), + new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(), TargetController.YOU, false), new XorLessLifeCondition(XorLessLifeCondition.CheckType.EACH_PLAYER, 10), "At the beginning of your upkeep, if each player has 10 or less life, transform Cryptolith Fragment.")); } diff --git a/Mage.Sets/src/mage/cards/c/CuriousHomunculus.java b/Mage.Sets/src/mage/cards/c/CuriousHomunculus.java index ad14b25935..3c67f2eb17 100644 --- a/Mage.Sets/src/mage/cards/c/CuriousHomunculus.java +++ b/Mage.Sets/src/mage/cards/c/CuriousHomunculus.java @@ -33,7 +33,6 @@ public final class CuriousHomunculus extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.v.VoraciousReader.class; // {T}: Add {C}. Spend this mana only to cast an instant or sorcery spell. @@ -42,7 +41,7 @@ public final class CuriousHomunculus extends CardImpl { // At the beginning of your upkeep, if there are three or more instant and/or sorcery cards in your graveyard, transform Curious Homunculus. this.addAbility(new TransformAbility()); this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.YOU, false), + new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(), TargetController.YOU, false), new InstantOrSorceryCardsInControllerGraveyardCondition(3), "At the beginning of your upkeep, if there are three or more instant and/or sorcery cards in your graveyard, transform {this}")); } diff --git a/Mage.Sets/src/mage/cards/c/CurseOfLeeches.java b/Mage.Sets/src/mage/cards/c/CurseOfLeeches.java new file mode 100644 index 0000000000..75555e0aaa --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CurseOfLeeches.java @@ -0,0 +1,111 @@ +package mage.cards.c; + +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.LoseLifeTargetEffect; +import mage.abilities.keyword.DayboundAbility; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.TransformAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPlayer; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class CurseOfLeeches extends CardImpl { + + public CurseOfLeeches(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}"); + + this.subtype.add(SubType.AURA); + this.subtype.add(SubType.CURSE); + this.secondSideCardClazz = mage.cards.l.LeechingLurker.class; + + // Enchant player + TargetPlayer auraTarget = new TargetPlayer(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // As this permanent transforms into Curse of Leeches, attach it to a player. + this.addAbility(new SimpleStaticAbility(new CurseOfLeechesEffect())); + + // At the beginning of enchanted player's upkeep, they lose 1 life and you gain 1 life. + ability = new BeginningOfUpkeepTriggeredAbility( + Zone.BATTLEFIELD, new LoseLifeTargetEffect(1).setText("they lose 1 life"), + TargetController.ENCHANTED, false, true + ); + ability.addEffect(new GainLifeEffect(1).concatBy("and")); + this.addAbility(ability); + + // Daybound + this.addAbility(new TransformAbility()); + this.addAbility(new DayboundAbility()); + } + + private CurseOfLeeches(final CurseOfLeeches card) { + super(card); + } + + @Override + public CurseOfLeeches copy() { + return new CurseOfLeeches(this); + } +} + +class CurseOfLeechesEffect extends ReplacementEffectImpl { + + CurseOfLeechesEffect() { + super(Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = "as this permanent transforms into {this}, attach it to a player"; + } + + private CurseOfLeechesEffect(final CurseOfLeechesEffect effect) { + super(effect); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + TargetPlayer target = new TargetPlayer(); + target.withChooseHint("Player to attach to").setNotTarget(true); + controller.choose(Outcome.Detriment, target, source.getSourceId(), game); + Permanent permanent = source.getSourcePermanentIfItStillExists(game); + if (permanent == null) { + return false; + } + permanent.addAttachment(target.getFirstTarget(), source, game); + return false; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.TRANSFORMING; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + return source.getSourceId().equals(event.getTargetId()); + } + + @Override + public CurseOfLeechesEffect copy() { + return new CurseOfLeechesEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DaringSleuth.java b/Mage.Sets/src/mage/cards/d/DaringSleuth.java index de0ba14e6c..01499f1e4c 100644 --- a/Mage.Sets/src/mage/cards/d/DaringSleuth.java +++ b/Mage.Sets/src/mage/cards/d/DaringSleuth.java @@ -12,7 +12,6 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; import java.util.UUID; @@ -28,7 +27,6 @@ public final class DaringSleuth extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.b.BearerOfOverwhelmingTruths.class; // When you sacrifice a Clue, transform Daring Sleuth. @@ -49,7 +47,7 @@ public final class DaringSleuth extends CardImpl { class DaringSleuthTriggeredAbility extends TriggeredAbilityImpl { public DaringSleuthTriggeredAbility() { - super(Zone.BATTLEFIELD, new TransformSourceEffect(true)); + super(Zone.BATTLEFIELD, new TransformSourceEffect()); } public DaringSleuthTriggeredAbility(final DaringSleuthTriggeredAbility ability) { diff --git a/Mage.Sets/src/mage/cards/d/DauntlessAvenger.java b/Mage.Sets/src/mage/cards/d/DauntlessAvenger.java index d7004ce349..8659565dac 100644 --- a/Mage.Sets/src/mage/cards/d/DauntlessAvenger.java +++ b/Mage.Sets/src/mage/cards/d/DauntlessAvenger.java @@ -36,7 +36,6 @@ public final class DauntlessAvenger extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(2); this.color.setWhite(true); - this.transformable = true; this.nightCard = true; // Whenever Dauntless Avenger attacks, return target creature card with mana value 2 or less from your graveyard to the battlefield tapped and attacking. diff --git a/Mage.Sets/src/mage/cards/d/DaybreakRanger.java b/Mage.Sets/src/mage/cards/d/DaybreakRanger.java index a5bf78e375..6048aa3396 100644 --- a/Mage.Sets/src/mage/cards/d/DaybreakRanger.java +++ b/Mage.Sets/src/mage/cards/d/DaybreakRanger.java @@ -37,7 +37,6 @@ public final class DaybreakRanger extends CardImpl { this.subtype.add(SubType.RANGER); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = mage.cards.n.NightfallPredator.class; this.power = new MageInt(2); diff --git a/Mage.Sets/src/mage/cards/d/DeathbonnetHulk.java b/Mage.Sets/src/mage/cards/d/DeathbonnetHulk.java index 99b151931c..7d39869b0f 100644 --- a/Mage.Sets/src/mage/cards/d/DeathbonnetHulk.java +++ b/Mage.Sets/src/mage/cards/d/DeathbonnetHulk.java @@ -30,7 +30,6 @@ public final class DeathbonnetHulk extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(3); this.color.setGreen(true); - this.transformable = true; this.nightCard = true; // At the beginning of your upkeep, you may exile a card from a graveyard. If a creature card was exiled this way, put a +1/+1 counter on Deathbonnet Hulk. diff --git a/Mage.Sets/src/mage/cards/d/DeathbonnetSprout.java b/Mage.Sets/src/mage/cards/d/DeathbonnetSprout.java index 051e7980c9..9089004165 100644 --- a/Mage.Sets/src/mage/cards/d/DeathbonnetSprout.java +++ b/Mage.Sets/src/mage/cards/d/DeathbonnetSprout.java @@ -39,7 +39,6 @@ public final class DeathbonnetSprout extends CardImpl { this.subtype.add(SubType.FUNGUS); this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.d.DeathbonnetHulk.class; // At the beginning of your upkeep, mill a card. Then if there are three or more creature cards in your graveyard, transform Deathbonnet Sprout. @@ -48,7 +47,7 @@ public final class DeathbonnetSprout extends CardImpl { new MillCardsControllerEffect(1), TargetController.YOU, false ); ability.addEffect(new ConditionalOneShotEffect( - new TransformSourceEffect(true), condition, + new TransformSourceEffect(), condition, "Then if there are three or more creature cards in your graveyard, transform {this}" )); this.addAbility(ability.addHint(hint)); diff --git a/Mage.Sets/src/mage/cards/d/DelverOfSecrets.java b/Mage.Sets/src/mage/cards/d/DelverOfSecrets.java index b0c282c70d..a02bc453ea 100644 --- a/Mage.Sets/src/mage/cards/d/DelverOfSecrets.java +++ b/Mage.Sets/src/mage/cards/d/DelverOfSecrets.java @@ -33,7 +33,6 @@ public final class DelverOfSecrets extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.i.InsectileAberration.class; // At the beginning of your upkeep, look at the top card of your library. You may reveal that card. If an instant or sorcery card is revealed this way, transform Delver of Secrets. @@ -73,25 +72,25 @@ class DelverOfSecretsEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); - if (player != null && sourcePermanent != null) { - if (player.getLibrary().hasCards()) { - Card card = player.getLibrary().getFromTop(game); - if(card == null){ - return false; - } - Cards cards = new CardsImpl(); - cards.add(card); - player.lookAtCards(sourcePermanent.getName(), cards, game); - if (player.chooseUse(Outcome.DrawCard, "Reveal the top card of your library?", source, game)) { - player.revealCards(sourcePermanent.getName(), cards, game); - if (filter.match(card, game)) { - return new TransformSourceEffect(true, true).apply(game, source); - } - } - - } - return true; + if (player == null || sourcePermanent == null) { + return false; } - return false; + if (player.getLibrary().hasCards()) { + Card card = player.getLibrary().getFromTop(game); + if(card == null){ + return false; + } + Cards cards = new CardsImpl(); + cards.add(card); + player.lookAtCards(sourcePermanent.getName(), cards, game); + if (player.chooseUse(Outcome.DrawCard, "Reveal the top card of your library?", source, game)) { + player.revealCards(sourcePermanent.getName(), cards, game); + if (filter.match(card, game)) { + return new TransformSourceEffect().apply(game, source); + } + } + + } + return true; } } diff --git a/Mage.Sets/src/mage/cards/d/Demilich.java b/Mage.Sets/src/mage/cards/d/Demilich.java index da6ff4323e..1a0aa25a23 100644 --- a/Mage.Sets/src/mage/cards/d/Demilich.java +++ b/Mage.Sets/src/mage/cards/d/Demilich.java @@ -76,7 +76,7 @@ enum DemilichValue implements DynamicValue { SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class); if (watcher != null) { for (Spell spell : watcher.getSpellsCastThisTurn(sourceAbility.getControllerId())) { - if (spell.isInstantOrSorcery()) { + if (spell.isInstantOrSorcery(game)) { spells++; } } diff --git a/Mage.Sets/src/mage/cards/d/DennickPiousApprentice.java b/Mage.Sets/src/mage/cards/d/DennickPiousApprentice.java index 20107974ca..862393b75a 100644 --- a/Mage.Sets/src/mage/cards/d/DennickPiousApprentice.java +++ b/Mage.Sets/src/mage/cards/d/DennickPiousApprentice.java @@ -29,7 +29,6 @@ public final class DennickPiousApprentice extends CardImpl { this.subtype.add(SubType.SOLDIER); this.power = new MageInt(2); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.d.DennickPiousApparition.class; // Lifelink diff --git a/Mage.Sets/src/mage/cards/d/DepartedSoulkeeper.java b/Mage.Sets/src/mage/cards/d/DepartedSoulkeeper.java index 91e19c92f0..c937f9d299 100644 --- a/Mage.Sets/src/mage/cards/d/DepartedSoulkeeper.java +++ b/Mage.Sets/src/mage/cards/d/DepartedSoulkeeper.java @@ -25,7 +25,6 @@ public final class DepartedSoulkeeper extends CardImpl { this.toughness = new MageInt(1); this.color.setWhite(true); this.color.setBlue(true); - this.transformable = true; this.nightCard = true; // Flying diff --git a/Mage.Sets/src/mage/cards/d/DevotedGrafkeeper.java b/Mage.Sets/src/mage/cards/d/DevotedGrafkeeper.java index 667d86340c..83b9adc4a0 100644 --- a/Mage.Sets/src/mage/cards/d/DevotedGrafkeeper.java +++ b/Mage.Sets/src/mage/cards/d/DevotedGrafkeeper.java @@ -32,7 +32,6 @@ public final class DevotedGrafkeeper extends CardImpl { this.subtype.add(SubType.PEASANT); this.power = new MageInt(2); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.d.DepartedSoulkeeper.class; // When Devoted Grafkeeper enters the battlefield, mill two cards. diff --git a/Mage.Sets/src/mage/cards/d/DireStrainBrawler.java b/Mage.Sets/src/mage/cards/d/DireStrainBrawler.java index c7116d20e7..b1ee9f5296 100644 --- a/Mage.Sets/src/mage/cards/d/DireStrainBrawler.java +++ b/Mage.Sets/src/mage/cards/d/DireStrainBrawler.java @@ -22,7 +22,6 @@ public final class DireStrainBrawler extends CardImpl { this.power = new MageInt(6); this.toughness = new MageInt(6); this.color.setGreen(true); - this.transformable = true; this.nightCard = true; // Vigilance diff --git a/Mage.Sets/src/mage/cards/d/DireStrainDemolisher.java b/Mage.Sets/src/mage/cards/d/DireStrainDemolisher.java index 51fcdcc707..abb57f2351 100644 --- a/Mage.Sets/src/mage/cards/d/DireStrainDemolisher.java +++ b/Mage.Sets/src/mage/cards/d/DireStrainDemolisher.java @@ -23,7 +23,6 @@ public final class DireStrainDemolisher extends CardImpl { this.power = new MageInt(8); this.toughness = new MageInt(7); this.color.setGreen(true); - this.transformable = true; this.nightCard = true; // Ward {3} diff --git a/Mage.Sets/src/mage/cards/d/DocentOfPerfection.java b/Mage.Sets/src/mage/cards/d/DocentOfPerfection.java index 1848042ea0..eff5ca4030 100644 --- a/Mage.Sets/src/mage/cards/d/DocentOfPerfection.java +++ b/Mage.Sets/src/mage/cards/d/DocentOfPerfection.java @@ -45,7 +45,6 @@ public final class DocentOfPerfection extends CardImpl { this.power = new MageInt(5); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = mage.cards.f.FinalIteration.class; // Flying @@ -98,7 +97,7 @@ class DocentOfPerfectionEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { if (game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game) >= 3) { - return new TransformSourceEffect(true).apply(game, source); + return new TransformSourceEffect().apply(game, source); } } return false; diff --git a/Mage.Sets/src/mage/cards/d/DormantGrove.java b/Mage.Sets/src/mage/cards/d/DormantGrove.java index 1bb4d62b25..e2cf7d115e 100644 --- a/Mage.Sets/src/mage/cards/d/DormantGrove.java +++ b/Mage.Sets/src/mage/cards/d/DormantGrove.java @@ -27,7 +27,6 @@ public final class DormantGrove extends CardImpl { public DormantGrove(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}"); - this.transformable = true; this.secondSideCardClazz = mage.cards.g.GnarledGrovestrider.class; // At the beginning of combat on your turn, put a +1/+1 counter on target creature you control. @@ -39,7 +38,7 @@ public final class DormantGrove extends CardImpl { TargetController.YOU, false ); ability.addEffect(new ConditionalOneShotEffect( - new TransformSourceEffect(true, true), + new TransformSourceEffect(), DormatGroveCondition.instance, "Then if that creature has toughness 6 or greater, transform {this}" )); diff --git a/Mage.Sets/src/mage/cards/d/DowsingDagger.java b/Mage.Sets/src/mage/cards/d/DowsingDagger.java index bbd5575d4d..eb4887c349 100644 --- a/Mage.Sets/src/mage/cards/d/DowsingDagger.java +++ b/Mage.Sets/src/mage/cards/d/DowsingDagger.java @@ -33,7 +33,6 @@ public final class DowsingDagger extends CardImpl { this.subtype.add(SubType.EQUIPMENT); - this.transformable = true; this.secondSideCardClazz = mage.cards.l.LostVale.class; // When Dowsing Dagger enters the battlefield, target opponent creates two 0/2 green Plant creature tokens with defender. @@ -47,7 +46,7 @@ public final class DowsingDagger extends CardImpl { // Whenever equipped creature deals combat damage to a player, you may transform Dowsing Dagger. this.addAbility(new TransformAbility()); - this.addAbility(new DealsDamageToAPlayerAttachedTriggeredAbility(new TransformSourceEffect(true), "equipped", true)); + this.addAbility(new DealsDamageToAPlayerAttachedTriggeredAbility(new TransformSourceEffect(), "equipped", true)); // Equip 2 this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2))); diff --git a/Mage.Sets/src/mage/cards/d/DuskwatchRecruiter.java b/Mage.Sets/src/mage/cards/d/DuskwatchRecruiter.java index ec4aa4d065..b7ea9403b6 100644 --- a/Mage.Sets/src/mage/cards/d/DuskwatchRecruiter.java +++ b/Mage.Sets/src/mage/cards/d/DuskwatchRecruiter.java @@ -3,21 +3,15 @@ package mage.cards.d; import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; -import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.WerewolfFrontTriggeredAbility; -import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; -import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.TargetController; import mage.constants.Zone; import mage.filter.common.FilterCreatureCard; @@ -34,7 +28,6 @@ public final class DuskwatchRecruiter extends CardImpl { this.subtype.add(SubType.WARRIOR); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = mage.cards.k.KrallenhordeHowler.class; this.power = new MageInt(2); diff --git a/Mage.Sets/src/mage/cards/e/EcstaticAwakener.java b/Mage.Sets/src/mage/cards/e/EcstaticAwakener.java index 50f4541680..200f79689a 100644 --- a/Mage.Sets/src/mage/cards/e/EcstaticAwakener.java +++ b/Mage.Sets/src/mage/cards/e/EcstaticAwakener.java @@ -30,7 +30,6 @@ public final class EcstaticAwakener extends CardImpl { this.subtype.add(SubType.WIZARD); this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.a.AwokenDemon.class; // {2}{B}, Sacrifice another creature: Draw a card, then transform Ecstatic Awakener. Activate only once each turn. @@ -38,7 +37,7 @@ public final class EcstaticAwakener extends CardImpl { Ability ability = new LimitedTimesPerTurnActivatedAbility( Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), new ManaCostsImpl<>("{2}{B}") ); - ability.addEffect(new TransformSourceEffect(true).concatBy(", then")); + ability.addEffect(new TransformSourceEffect().concatBy(", then")); ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE))); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/ElbrusTheBindingBlade.java b/Mage.Sets/src/mage/cards/e/ElbrusTheBindingBlade.java index 591d5dddfe..ee01415f79 100644 --- a/Mage.Sets/src/mage/cards/e/ElbrusTheBindingBlade.java +++ b/Mage.Sets/src/mage/cards/e/ElbrusTheBindingBlade.java @@ -1,4 +1,3 @@ - package mage.cards.e; import java.util.UUID; @@ -31,7 +30,6 @@ public final class ElbrusTheBindingBlade extends CardImpl { addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.EQUIPMENT); - this.transformable = true; this.secondSideCardClazz = mage.cards.w.WithengarUnbound.class; this.addAbility(new TransformAbility()); @@ -70,9 +68,7 @@ class ElbrusTheBindingBladeEffect extends OneShotEffect { Permanent attachedTo = game.getPermanent(equipment.getAttachedTo()); if (attachedTo != null) { attachedTo.removeAttachment(equipment.getId(), source, game); - equipment.transform(game); - game.informPlayers(equipment.getName() + " transforms into " + equipment.getSecondCardFace().getName()); - + equipment.transform(source, game); } } return false; diff --git a/Mage.Sets/src/mage/cards/e/ElusiveTormentor.java b/Mage.Sets/src/mage/cards/e/ElusiveTormentor.java index 592a56393b..8e60ab8019 100644 --- a/Mage.Sets/src/mage/cards/e/ElusiveTormentor.java +++ b/Mage.Sets/src/mage/cards/e/ElusiveTormentor.java @@ -28,12 +28,11 @@ public final class ElusiveTormentor extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = mage.cards.i.InsidiousMist.class; // {1}, Discard a card: Transform Elusive Tormentor. this.addAbility(new TransformAbility()); - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new GenericManaCost(1)); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new GenericManaCost(1)); ability.addCost(new DiscardCardCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/EmbodimentOfFlame.java b/Mage.Sets/src/mage/cards/e/EmbodimentOfFlame.java index f6159aff10..7b06303bf6 100644 --- a/Mage.Sets/src/mage/cards/e/EmbodimentOfFlame.java +++ b/Mage.Sets/src/mage/cards/e/EmbodimentOfFlame.java @@ -34,7 +34,6 @@ public final class EmbodimentOfFlame extends CardImpl { this.toughness = new MageInt(3); this.color.setRed(true); this.nightCard = true; - this.transformable = true; // Whenever a spell you control deals damage, put a flame counter on Embodiment of Flame. this.addAbility(new EmbodimentOfFlameTriggeredAbility()); diff --git a/Mage.Sets/src/mage/cards/e/EnduringAngel.java b/Mage.Sets/src/mage/cards/e/EnduringAngel.java new file mode 100644 index 0000000000..cb4b85471a --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EnduringAngel.java @@ -0,0 +1,110 @@ +package mage.cards.e; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.continuous.GainAbilityControllerEffect; +import mage.abilities.keyword.DoubleStrikeAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.HexproofAbility; +import mage.abilities.keyword.TransformAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class EnduringAngel extends CardImpl { + + public EnduringAngel(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{W}{W}"); + + this.subtype.add(SubType.ANGEL); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + this.secondSideCardClazz = mage.cards.a.AngelicEnforcer.class; + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Double strike + this.addAbility(DoubleStrikeAbility.getInstance()); + + // You have hexproof. + this.addAbility(new SimpleStaticAbility(new GainAbilityControllerEffect(HexproofAbility.getInstance()))); + + // If your life total would be reduced to 0 or less, instead transform Enduring Angel and your life total becomes 3. Then if Enduring Angel didn't transform this way, you lose the game. + this.addAbility(new TransformAbility()); + this.addAbility(new SimpleStaticAbility(new EnduringAngelEffect())); + } + + private EnduringAngel(final EnduringAngel card) { + super(card); + } + + @Override + public EnduringAngel copy() { + return new EnduringAngel(this); + } +} + +class EnduringAngelEffect extends ReplacementEffectImpl { + + EnduringAngelEffect() { + super(Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = "if your life total would be reduced to 0 or less, instead transform {this} " + + "and your life total becomes 3. Then if {this} didn't transform this way, you lose the game"; + } + + private EnduringAngelEffect(final EnduringAngelEffect effect) { + super(effect); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Player player = game.getPlayer(source.getControllerId()); + Permanent permanent = source.getSourcePermanentIfItStillExists(game); + if (player == null || permanent == null || player.getLife() - event.getAmount() > 0) { + return false; + } + boolean transformed = permanent.transform(source, game); + if (player.getLife() > 3) { + event.setAmount(player.getLife() - 3); + } else if (player.getLife() < 3) { + event.setAmount(0); + player.setLife(3, game, source); + } else { + event.setAmount(0); + } + if (!transformed) { + player.lost(game); + } + return false; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.LOSE_LIFE; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + return source.isControlledBy(event.getPlayerId()); + } + + @Override + public EnduringAngelEffect copy() { + return new EnduringAngelEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/e/ExtricatorOfSin.java b/Mage.Sets/src/mage/cards/e/ExtricatorOfSin.java index 37699775eb..191b698e82 100644 --- a/Mage.Sets/src/mage/cards/e/ExtricatorOfSin.java +++ b/Mage.Sets/src/mage/cards/e/ExtricatorOfSin.java @@ -42,7 +42,6 @@ public final class ExtricatorOfSin extends CardImpl { this.power = new MageInt(0); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = ExtricatorOfFlesh.class; // When Extricator of Sin enters the battlefield, you may sacrifice another permanent. If you do, create a 3/2 colorless Eldrazi Horror creature token. @@ -52,7 +51,7 @@ public final class ExtricatorOfSin extends CardImpl { // Delirium — At the beginning of your upkeep, if there are four or more card types among cards in your graveyard, transform Extricator of Sin. this.addAbility(new TransformAbility()); this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), TargetController.YOU, false), + new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), TargetController.YOU, false), DeliriumCondition.instance, "Delirium — At the beginning of your upkeep, if there are four or more card types among cards in your graveyard, " + " transform {this}.") diff --git a/Mage.Sets/src/mage/cards/f/FangbladeBrigand.java b/Mage.Sets/src/mage/cards/f/FangbladeBrigand.java index c8bab4a331..ab8610811c 100644 --- a/Mage.Sets/src/mage/cards/f/FangbladeBrigand.java +++ b/Mage.Sets/src/mage/cards/f/FangbladeBrigand.java @@ -29,7 +29,6 @@ public final class FangbladeBrigand extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(3); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = mage.cards.f.FangbladeEviscerator.class; // {1}{R}: Fangblade Brigand gets +1/+0 and gains first strike until end of turn. diff --git a/Mage.Sets/src/mage/cards/f/FangbladeEviscerator.java b/Mage.Sets/src/mage/cards/f/FangbladeEviscerator.java index f3a9ba0926..b9c7a4dabe 100644 --- a/Mage.Sets/src/mage/cards/f/FangbladeEviscerator.java +++ b/Mage.Sets/src/mage/cards/f/FangbladeEviscerator.java @@ -29,7 +29,6 @@ public final class FangbladeEviscerator extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(5); this.color.setRed(true); - this.transformable = true; this.nightCard = true; // {1}{R}: Fangblade Eviscerator gets +1/+0 and gains first strike until end of turn. diff --git a/Mage.Sets/src/mage/cards/f/FlameChanneler.java b/Mage.Sets/src/mage/cards/f/FlameChanneler.java index ee029cffe2..8bce9da31b 100644 --- a/Mage.Sets/src/mage/cards/f/FlameChanneler.java +++ b/Mage.Sets/src/mage/cards/f/FlameChanneler.java @@ -27,7 +27,7 @@ public final class FlameChanneler extends CardImpl { this.subtype.add(SubType.WIZARD); this.power = new MageInt(2); this.toughness = new MageInt(2); - this.transformable=true;this.secondSideCardClazz=mage.cards.e.EmbodimentOfFlame.class; + this.secondSideCardClazz = mage.cards.e.EmbodimentOfFlame.class; // When a spell you control deals damage, transform Flame Channeler. this.addAbility(new TransformAbility()); @@ -47,7 +47,7 @@ public final class FlameChanneler extends CardImpl { class FlameChannelerTriggeredAbility extends TriggeredAbilityImpl { FlameChannelerTriggeredAbility() { - super(Zone.BATTLEFIELD, new TransformSourceEffect(true)); + super(Zone.BATTLEFIELD, new TransformSourceEffect()); } private FlameChannelerTriggeredAbility(final FlameChannelerTriggeredAbility ability) { diff --git a/Mage.Sets/src/mage/cards/f/FlameheartWerewolf.java b/Mage.Sets/src/mage/cards/f/FlameheartWerewolf.java index 84bf2aba13..b73d8bc11e 100644 --- a/Mage.Sets/src/mage/cards/f/FlameheartWerewolf.java +++ b/Mage.Sets/src/mage/cards/f/FlameheartWerewolf.java @@ -26,7 +26,6 @@ public final class FlameheartWerewolf extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; // Whenever Flameheart Werewolf blocks or becomes blocked by a creature, Flameheart Werewolf deals 2 damage to that creature. this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(new DamageTargetEffect(2, true, "that creature"), diff --git a/Mage.Sets/src/mage/cards/f/FrenziedTrapbreaker.java b/Mage.Sets/src/mage/cards/f/FrenziedTrapbreaker.java index 40af95b9df..771d12a628 100644 --- a/Mage.Sets/src/mage/cards/f/FrenziedTrapbreaker.java +++ b/Mage.Sets/src/mage/cards/f/FrenziedTrapbreaker.java @@ -39,7 +39,6 @@ public final class FrenziedTrapbreaker extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(3); this.color.setGreen(true); - this.transformable = true; this.nightCard = true; // {1}, Sacrifice Frenzied Trapbreaker: Destroy target artifact or enchantment. diff --git a/Mage.Sets/src/mage/cards/g/Galedrifter.java b/Mage.Sets/src/mage/cards/g/Galedrifter.java index 1ef6a7f13d..aff87e6ee3 100644 --- a/Mage.Sets/src/mage/cards/g/Galedrifter.java +++ b/Mage.Sets/src/mage/cards/g/Galedrifter.java @@ -23,7 +23,6 @@ public final class Galedrifter extends CardImpl { this.subtype.add(SubType.HIPPOGRIFF); this.power = new MageInt(3); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.w.Waildrifter.class; // Flying diff --git a/Mage.Sets/src/mage/cards/g/GarrukRelentless.java b/Mage.Sets/src/mage/cards/g/GarrukRelentless.java index a6a35b5244..1ac3ece0df 100644 --- a/Mage.Sets/src/mage/cards/g/GarrukRelentless.java +++ b/Mage.Sets/src/mage/cards/g/GarrukRelentless.java @@ -31,7 +31,6 @@ public final class GarrukRelentless extends CardImpl { this.addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.GARRUK); - this.transformable = true; this.secondSideCardClazz = GarrukTheVeilCursed.class; this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(3)); @@ -63,7 +62,7 @@ public final class GarrukRelentless extends CardImpl { class GarrukRelentlessStateTrigger extends StateTriggeredAbility { public GarrukRelentlessStateTrigger() { - super(Zone.BATTLEFIELD, new TransformSourceEffect(true)); + super(Zone.BATTLEFIELD, new TransformSourceEffect()); } public GarrukRelentlessStateTrigger(final GarrukRelentlessStateTrigger ability) { diff --git a/Mage.Sets/src/mage/cards/g/GarrukTheVeilCursed.java b/Mage.Sets/src/mage/cards/g/GarrukTheVeilCursed.java index 65231c23e6..065638a1a8 100644 --- a/Mage.Sets/src/mage/cards/g/GarrukTheVeilCursed.java +++ b/Mage.Sets/src/mage/cards/g/GarrukTheVeilCursed.java @@ -38,7 +38,6 @@ public final class GarrukTheVeilCursed extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.color.setGreen(true); this.color.setBlack(true); diff --git a/Mage.Sets/src/mage/cards/g/GatstafArsonists.java b/Mage.Sets/src/mage/cards/g/GatstafArsonists.java index d71ff6bac9..198d47e1d7 100644 --- a/Mage.Sets/src/mage/cards/g/GatstafArsonists.java +++ b/Mage.Sets/src/mage/cards/g/GatstafArsonists.java @@ -2,18 +2,12 @@ package mage.cards.g; import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; -import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.WerewolfFrontTriggeredAbility; -import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.TargetController; /** * @@ -28,7 +22,6 @@ public final class GatstafArsonists extends CardImpl { this.power = new MageInt(5); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = GatstafRavagers.class; // At the beginning of each upkeep, if no spells were cast last turn, transform Gatstaf Arsonists. diff --git a/Mage.Sets/src/mage/cards/g/GatstafHowler.java b/Mage.Sets/src/mage/cards/g/GatstafHowler.java index df0faacf87..3d98791e21 100644 --- a/Mage.Sets/src/mage/cards/g/GatstafHowler.java +++ b/Mage.Sets/src/mage/cards/g/GatstafHowler.java @@ -22,7 +22,6 @@ public final class GatstafHowler extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(3); this.toughness = new MageInt(3); diff --git a/Mage.Sets/src/mage/cards/g/GatstafRavagers.java b/Mage.Sets/src/mage/cards/g/GatstafRavagers.java index ce353bf647..fd2463f180 100644 --- a/Mage.Sets/src/mage/cards/g/GatstafRavagers.java +++ b/Mage.Sets/src/mage/cards/g/GatstafRavagers.java @@ -23,7 +23,6 @@ public final class GatstafRavagers extends CardImpl { this.color.setRed(true); - this.transformable = true; this.nightCard = true; // Menace diff --git a/Mage.Sets/src/mage/cards/g/GatstafShepherd.java b/Mage.Sets/src/mage/cards/g/GatstafShepherd.java index 1e49e181c0..47d1bb9d28 100644 --- a/Mage.Sets/src/mage/cards/g/GatstafShepherd.java +++ b/Mage.Sets/src/mage/cards/g/GatstafShepherd.java @@ -20,7 +20,6 @@ public final class GatstafShepherd extends CardImpl { this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = GatstafHowler.class; this.power = new MageInt(2); diff --git a/Mage.Sets/src/mage/cards/g/GeierReachBandit.java b/Mage.Sets/src/mage/cards/g/GeierReachBandit.java index 9fde0db14a..004e24bd54 100644 --- a/Mage.Sets/src/mage/cards/g/GeierReachBandit.java +++ b/Mage.Sets/src/mage/cards/g/GeierReachBandit.java @@ -24,7 +24,6 @@ public final class GeierReachBandit extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.v.VildinPackAlpha.class; // Haste diff --git a/Mage.Sets/src/mage/cards/g/GhastlyHaunting.java b/Mage.Sets/src/mage/cards/g/GhastlyHaunting.java index 1dd17b3910..b388bb7654 100644 --- a/Mage.Sets/src/mage/cards/g/GhastlyHaunting.java +++ b/Mage.Sets/src/mage/cards/g/GhastlyHaunting.java @@ -25,7 +25,6 @@ public final class GhastlyHaunting extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; // Enchant creature TargetPermanent auraTarget = new TargetCreaturePermanent(); diff --git a/Mage.Sets/src/mage/cards/g/GhostlyCastigator.java b/Mage.Sets/src/mage/cards/g/GhostlyCastigator.java index 35833d5214..f18d529962 100644 --- a/Mage.Sets/src/mage/cards/g/GhostlyCastigator.java +++ b/Mage.Sets/src/mage/cards/g/GhostlyCastigator.java @@ -27,7 +27,6 @@ public final class GhostlyCastigator extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(4); this.color.setBlue(true); - this.transformable = true; this.nightCard = true; // Flying diff --git a/Mage.Sets/src/mage/cards/g/GideonBattleForged.java b/Mage.Sets/src/mage/cards/g/GideonBattleForged.java index 740e82a5b4..740ad27a0b 100644 --- a/Mage.Sets/src/mage/cards/g/GideonBattleForged.java +++ b/Mage.Sets/src/mage/cards/g/GideonBattleForged.java @@ -42,7 +42,6 @@ public final class GideonBattleForged extends CardImpl { this.color.setWhite(true); this.nightCard = true; - this.transformable = true; this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(3)); diff --git a/Mage.Sets/src/mage/cards/g/GoldenGuardian.java b/Mage.Sets/src/mage/cards/g/GoldenGuardian.java index 1cfe74e73d..6e575c7c14 100644 --- a/Mage.Sets/src/mage/cards/g/GoldenGuardian.java +++ b/Mage.Sets/src/mage/cards/g/GoldenGuardian.java @@ -47,7 +47,6 @@ public final class GoldenGuardian extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = GoldForgeGarrison.class; // Defender diff --git a/Mage.Sets/src/mage/cards/g/GraveyardGlutton.java b/Mage.Sets/src/mage/cards/g/GraveyardGlutton.java index 8cd92dd191..2fd570828e 100644 --- a/Mage.Sets/src/mage/cards/g/GraveyardGlutton.java +++ b/Mage.Sets/src/mage/cards/g/GraveyardGlutton.java @@ -35,7 +35,6 @@ public final class GraveyardGlutton extends CardImpl { this.toughness = new MageInt(4); this.color.setBlack(true); this.nightCard = true; - this.transformable = true; // Ward—Discard a card. this.addAbility(new WardAbility(new DiscardCardCost())); diff --git a/Mage.Sets/src/mage/cards/g/GraveyardTrespasser.java b/Mage.Sets/src/mage/cards/g/GraveyardTrespasser.java index 4b505e9d41..100d764de4 100644 --- a/Mage.Sets/src/mage/cards/g/GraveyardTrespasser.java +++ b/Mage.Sets/src/mage/cards/g/GraveyardTrespasser.java @@ -35,7 +35,6 @@ public final class GraveyardTrespasser extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(3); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.g.GraveyardGlutton.class; // Ward—Discard a card. diff --git a/Mage.Sets/src/mage/cards/g/GrimlockDinobotLeader.java b/Mage.Sets/src/mage/cards/g/GrimlockDinobotLeader.java index d569fee265..94c472489d 100644 --- a/Mage.Sets/src/mage/cards/g/GrimlockDinobotLeader.java +++ b/Mage.Sets/src/mage/cards/g/GrimlockDinobotLeader.java @@ -46,8 +46,7 @@ public final class GrimlockDinobotLeader extends CardImpl{ this.subtype.add(SubType.AUTOBOT); this.power = new MageInt(4); this.toughness = new MageInt(4); - - this.transformable = true; + this.secondSideCardClazz = GrimlockFerociousKing.class; // Dinosaurs, Vehicles and other Transformers creatures you control get +2/+0. @@ -56,7 +55,7 @@ public final class GrimlockDinobotLeader extends CardImpl{ // {2}: Grimlock, Dinobot Leader becomes Grimlock, Ferocious King. this.addAbility(new TransformAbility()); - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new ManaCostsImpl("{2}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new ManaCostsImpl("{2}"))); } private GrimlockDinobotLeader(final GrimlockDinobotLeader card) { diff --git a/Mage.Sets/src/mage/cards/g/GrimlockFerociousKing.java b/Mage.Sets/src/mage/cards/g/GrimlockFerociousKing.java index ca8ba185e9..5b16978b08 100644 --- a/Mage.Sets/src/mage/cards/g/GrimlockFerociousKing.java +++ b/Mage.Sets/src/mage/cards/g/GrimlockFerociousKing.java @@ -31,15 +31,14 @@ public final class GrimlockFerociousKing extends CardImpl{ this.color.setGreen(true); this.color.setWhite(true); - this.transformable = true; - this.nightCard = true; + this.nightCard = true; // Trample this.addAbility(TrampleAbility.getInstance()); // {2}: Grimlock, Ferocious King becomes Grimlock, Dinobot Leader. this.addAbility(new TransformAbility()); - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(false), new ManaCostsImpl("{2}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new ManaCostsImpl("{2}"))); } private GrimlockFerociousKing(final GrimlockFerociousKing card) { diff --git a/Mage.Sets/src/mage/cards/g/GrizzledAngler.java b/Mage.Sets/src/mage/cards/g/GrizzledAngler.java index 20b7016afb..3726aae9f9 100644 --- a/Mage.Sets/src/mage/cards/g/GrizzledAngler.java +++ b/Mage.Sets/src/mage/cards/g/GrizzledAngler.java @@ -32,7 +32,6 @@ public final class GrizzledAngler extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = GrislyAnglerfish.class; // {T}: Put the top two cards of your library into your graveyard. Then if there is a colorless creature card in your graveyard, transform Grizzled Angler. @@ -78,7 +77,7 @@ class GrizzledAnglerEffect extends OneShotEffect { if (controller != null) { controller.millCards(2, source, game); if (controller.getGraveyard().count(filter, source.getSourceId(), source.getControllerId(), game) >= 1) { - return new TransformSourceEffect(true).apply(game, source); + return new TransformSourceEffect().apply(game, source); } } return false; diff --git a/Mage.Sets/src/mage/cards/g/GrizzledOutcasts.java b/Mage.Sets/src/mage/cards/g/GrizzledOutcasts.java index 947f486a36..ab0bcf6566 100644 --- a/Mage.Sets/src/mage/cards/g/GrizzledOutcasts.java +++ b/Mage.Sets/src/mage/cards/g/GrizzledOutcasts.java @@ -20,7 +20,6 @@ public final class GrizzledOutcasts extends CardImpl { this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = mage.cards.k.KrallenhordeWantons.class; this.power = new MageInt(4); diff --git a/Mage.Sets/src/mage/cards/g/GrowingRitesOfItlimoc.java b/Mage.Sets/src/mage/cards/g/GrowingRitesOfItlimoc.java index 6f32b3a86f..a4216f7cb5 100644 --- a/Mage.Sets/src/mage/cards/g/GrowingRitesOfItlimoc.java +++ b/Mage.Sets/src/mage/cards/g/GrowingRitesOfItlimoc.java @@ -36,7 +36,6 @@ public final class GrowingRitesOfItlimoc extends CardImpl { this.addSuperType(SuperType.LEGENDARY); - this.transformable = true; this.secondSideCardClazz = mage.cards.i.ItlimocCradleOfTheSun.class; // When Growing Rites of Itlimoc enters the battlefield, look at the top four cards of your library. @@ -47,7 +46,7 @@ public final class GrowingRitesOfItlimoc extends CardImpl { // At the beginning of your end step, if you control four or more creatures, transform Growing Rites of Itlimoc. this.addAbility(new TransformAbility()); this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility(new TransformSourceEffect(true), TargetController.YOU, false), + new BeginningOfEndStepTriggeredAbility(new TransformSourceEffect(), TargetController.YOU, false), new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_CONTROLLED_A_CREATURE, ComparisonType.MORE_THAN, 3), "At the beginning of your end step, if you control four or more creatures, transform {this}")); } diff --git a/Mage.Sets/src/mage/cards/h/HadanasClimb.java b/Mage.Sets/src/mage/cards/h/HadanasClimb.java index 633a238a48..223b770c7c 100644 --- a/Mage.Sets/src/mage/cards/h/HadanasClimb.java +++ b/Mage.Sets/src/mage/cards/h/HadanasClimb.java @@ -27,14 +27,13 @@ public final class HadanasClimb extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}{U}"); this.addSuperType(SuperType.LEGENDARY); - this.transformable = true; this.secondSideCardClazz = mage.cards.w.WingedTempleOfOrazca.class; // At the beginning of combat on your turn, put a +1/+1 counter on target creature you control. Then if that creature has three or more +1/+1 counters on it, transform Hadana's Climb. this.addAbility(new TransformAbility()); Ability ability = new BeginningOfCombatTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()), TargetController.YOU, false); - ability.addEffect(new ConditionalOneShotEffect(new TransformSourceEffect(true), new TargetHasCounterCondition(CounterType.P1P1, 3, Integer.MAX_VALUE), + ability.addEffect(new ConditionalOneShotEffect(new TransformSourceEffect(), new TargetHasCounterCondition(CounterType.P1P1, 3, Integer.MAX_VALUE), "Then if that creature has three or more +1/+1 counters on it, transform {this}")); ability.addTarget(new TargetControlledCreaturePermanent()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/h/HanweirMilitiaCaptain.java b/Mage.Sets/src/mage/cards/h/HanweirMilitiaCaptain.java index dceb0b20ec..2e1a11f192 100644 --- a/Mage.Sets/src/mage/cards/h/HanweirMilitiaCaptain.java +++ b/Mage.Sets/src/mage/cards/h/HanweirMilitiaCaptain.java @@ -31,13 +31,12 @@ public final class HanweirMilitiaCaptain extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.w.WestvaleCultLeader.class; // At the beginning of your upkeep, if you control four or more creatures, transform Hanweir Militia Captain. this.addAbility(new TransformAbility()); this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.YOU, false), + new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(), TargetController.YOU, false), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 3), "At the beginning of your upkeep, if you control four or more creatures, transform {this}")); } diff --git a/Mage.Sets/src/mage/cards/h/HanweirWatchkeep.java b/Mage.Sets/src/mage/cards/h/HanweirWatchkeep.java index cd550520cc..85997f17d3 100644 --- a/Mage.Sets/src/mage/cards/h/HanweirWatchkeep.java +++ b/Mage.Sets/src/mage/cards/h/HanweirWatchkeep.java @@ -22,7 +22,6 @@ public final class HanweirWatchkeep extends CardImpl { this.subtype.add(SubType.WARRIOR); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = mage.cards.b.BaneOfHanweir.class; this.power = new MageInt(1); diff --git a/Mage.Sets/src/mage/cards/h/HarvestHand.java b/Mage.Sets/src/mage/cards/h/HarvestHand.java index a5af36de70..29fb77f3e5 100644 --- a/Mage.Sets/src/mage/cards/h/HarvestHand.java +++ b/Mage.Sets/src/mage/cards/h/HarvestHand.java @@ -29,7 +29,6 @@ public final class HarvestHand extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.s.ScroungedScythe.class; // When Harvest Hand dies, return it to the battlefield transformed under your control. diff --git a/Mage.Sets/src/mage/cards/h/HarvesttideAssailant.java b/Mage.Sets/src/mage/cards/h/HarvesttideAssailant.java index 55c37c19d4..c1d10320d8 100644 --- a/Mage.Sets/src/mage/cards/h/HarvesttideAssailant.java +++ b/Mage.Sets/src/mage/cards/h/HarvesttideAssailant.java @@ -22,7 +22,6 @@ public final class HarvesttideAssailant extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); this.color.setRed(true); - this.transformable = true; this.nightCard = true; // Trample diff --git a/Mage.Sets/src/mage/cards/h/HarvesttideInfiltrator.java b/Mage.Sets/src/mage/cards/h/HarvesttideInfiltrator.java index 66e8715dc5..4695e36a65 100644 --- a/Mage.Sets/src/mage/cards/h/HarvesttideInfiltrator.java +++ b/Mage.Sets/src/mage/cards/h/HarvesttideInfiltrator.java @@ -23,7 +23,6 @@ public final class HarvesttideInfiltrator extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(3); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.h.HarvesttideAssailant.class; // Trample diff --git a/Mage.Sets/src/mage/cards/h/HawkinsNationalLaboratory.java b/Mage.Sets/src/mage/cards/h/HawkinsNationalLaboratory.java index 236fed263c..614a9b2263 100644 --- a/Mage.Sets/src/mage/cards/h/HawkinsNationalLaboratory.java +++ b/Mage.Sets/src/mage/cards/h/HawkinsNationalLaboratory.java @@ -29,9 +29,8 @@ public final class HawkinsNationalLaboratory extends CardImpl { public HawkinsNationalLaboratory(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); - this.addSuperType(SuperType.LEGENDARY); - this.transformable = true; + this.secondSideCardClazz = mage.cards.t.TheUpsideDown.class; // {T}: Add {C}. @@ -45,7 +44,7 @@ public final class HawkinsNationalLaboratory extends CardImpl { // At the beginning of your end step, if you sacrificed three or more Clues this turn, transform Hawkins National Laboratory. this.addAbility(new TransformAbility()); this.addAbility(new BeginningOfEndStepTriggeredAbility( - Zone.BATTLEFIELD, new TransformSourceEffect(true), + Zone.BATTLEFIELD, new TransformSourceEffect(), TargetController.YOU, HawkinsNationalLaboratoryCondition.instance, false ), new HawkinsNationalLaboratoryWatcher()); } diff --git a/Mage.Sets/src/mage/cards/h/HeirOfFalkenrath.java b/Mage.Sets/src/mage/cards/h/HeirOfFalkenrath.java index e3a8262c09..f86c9772c4 100644 --- a/Mage.Sets/src/mage/cards/h/HeirOfFalkenrath.java +++ b/Mage.Sets/src/mage/cards/h/HeirOfFalkenrath.java @@ -25,12 +25,11 @@ public final class HeirOfFalkenrath extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = HeirToTheNight.class; // Discard a card: Transform Heir of Falkenrath. Activate this ability only once each turn. this.addAbility(new TransformAbility()); - this.addAbility(new LimitedTimesPerTurnActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new DiscardCardCost())); + this.addAbility(new LimitedTimesPerTurnActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new DiscardCardCost())); } private HeirOfFalkenrath(final HeirOfFalkenrath card) { diff --git a/Mage.Sets/src/mage/cards/h/HeirloomMirror.java b/Mage.Sets/src/mage/cards/h/HeirloomMirror.java index 43f576e01c..4d71dcec83 100644 --- a/Mage.Sets/src/mage/cards/h/HeirloomMirror.java +++ b/Mage.Sets/src/mage/cards/h/HeirloomMirror.java @@ -28,7 +28,6 @@ public final class HeirloomMirror extends CardImpl { public HeirloomMirror(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}{B}"); - this.transformable = true; this.secondSideCardClazz = mage.cards.i.InheritedFiend.class; // {1}, {T}, Pay 1 life, Discard a card: Draw a card, mill a card, then put a ritual counter on Heirloom Mirror. Then if it has 3 or more ritual counters on it, remove them and transform it. Activate only as a sorcery. @@ -82,7 +81,7 @@ class HeirloomMirrorEffect extends OneShotEffect { return true; } permanent.removeCounters(CounterType.RITUAL.createInstance(counters), source, game); - new TransformSourceEffect(true).apply(game, source); + new TransformSourceEffect().apply(game, source); return true; } } diff --git a/Mage.Sets/src/mage/cards/h/HermitOfTheNatterknolls.java b/Mage.Sets/src/mage/cards/h/HermitOfTheNatterknolls.java index 5b2becc29b..e14800c329 100644 --- a/Mage.Sets/src/mage/cards/h/HermitOfTheNatterknolls.java +++ b/Mage.Sets/src/mage/cards/h/HermitOfTheNatterknolls.java @@ -12,7 +12,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.filter.FilterSpell; import mage.filter.StaticFilters; import java.util.UUID; @@ -29,7 +28,6 @@ public final class HermitOfTheNatterknolls extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.l.LoneWolfOfTheNatterknolls.class; // Whenever an opponent casts a spell during your turn, draw a card. diff --git a/Mage.Sets/src/mage/cards/h/HinterlandHermit.java b/Mage.Sets/src/mage/cards/h/HinterlandHermit.java index f1d4288776..549ec1ed1b 100644 --- a/Mage.Sets/src/mage/cards/h/HinterlandHermit.java +++ b/Mage.Sets/src/mage/cards/h/HinterlandHermit.java @@ -20,7 +20,6 @@ public final class HinterlandHermit extends CardImpl { this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = HinterlandScourge.class; this.power = new MageInt(2); diff --git a/Mage.Sets/src/mage/cards/h/HinterlandLogger.java b/Mage.Sets/src/mage/cards/h/HinterlandLogger.java index a8e6295322..51df4a0963 100644 --- a/Mage.Sets/src/mage/cards/h/HinterlandLogger.java +++ b/Mage.Sets/src/mage/cards/h/HinterlandLogger.java @@ -22,7 +22,6 @@ public final class HinterlandLogger extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.t.TimberShredder.class; // At the beginning of each upkeep, if no spells were cast last turn, transform Hinterland Logger. diff --git a/Mage.Sets/src/mage/cards/h/HinterlandScourge.java b/Mage.Sets/src/mage/cards/h/HinterlandScourge.java index 155deff810..942dfb7e1e 100644 --- a/Mage.Sets/src/mage/cards/h/HinterlandScourge.java +++ b/Mage.Sets/src/mage/cards/h/HinterlandScourge.java @@ -25,7 +25,6 @@ public final class HinterlandScourge extends CardImpl { // this card is the second face of double-faced card of Hinterland Hermit this.nightCard = true; - this.transformable = true; this.power = new MageInt(3); this.toughness = new MageInt(2); diff --git a/Mage.Sets/src/mage/cards/h/HomicidalBrute.java b/Mage.Sets/src/mage/cards/h/HomicidalBrute.java index b4ec7d0412..7e0ebe1baf 100644 --- a/Mage.Sets/src/mage/cards/h/HomicidalBrute.java +++ b/Mage.Sets/src/mage/cards/h/HomicidalBrute.java @@ -10,10 +10,10 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import mage.constants.WatcherScope; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; import mage.watchers.Watcher; /** @@ -28,14 +28,13 @@ public final class HomicidalBrute extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.color.setRed(true); this.power = new MageInt(5); this.toughness = new MageInt(1); // At the beginning of your end step, if Homicidal Brute didn't attack this turn, tap Homicidal Brute, then transform it. - this.addAbility(new HomicidalBruteTriggeredAbility()); + this.addAbility(new HomicidalBruteTriggeredAbility(), new HomicidalBruteWatcher()); } private HomicidalBrute(final HomicidalBrute card) { @@ -53,7 +52,7 @@ class HomicidalBruteTriggeredAbility extends TriggeredAbilityImpl { public HomicidalBruteTriggeredAbility() { super(Zone.BATTLEFIELD, new TapSourceEffect(), false); - addEffect(new TransformSourceEffect(false)); + addEffect(new TransformSourceEffect()); } public HomicidalBruteTriggeredAbility(HomicidalBruteTriggeredAbility ability) { @@ -87,5 +86,19 @@ class HomicidalBruteTriggeredAbility extends TriggeredAbilityImpl { } } +class HomicidalBruteWatcher extends Watcher { + public HomicidalBruteWatcher() { + super(WatcherScope.CARD); + } + @Override + public void watch(GameEvent event, Game game) { + if (condition) { + return; + } + if (event.getType() == GameEvent.EventType.ATTACKER_DECLARED && event.getSourceId().equals(sourceId)) { + condition = true; + } + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/h/HomicidalBruteWatcher.java b/Mage.Sets/src/mage/cards/h/HomicidalBruteWatcher.java deleted file mode 100644 index 4425e8cba3..0000000000 --- a/Mage.Sets/src/mage/cards/h/HomicidalBruteWatcher.java +++ /dev/null @@ -1,23 +0,0 @@ -package mage.cards.h; - -import mage.constants.WatcherScope; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.watchers.Watcher; - -public class HomicidalBruteWatcher extends Watcher { - - public HomicidalBruteWatcher() { - super(WatcherScope.CARD); - } - - @Override - public void watch(GameEvent event, Game game) { - if (condition) { - return; - } - if (event.getType() == GameEvent.EventType.ATTACKER_DECLARED && event.getSourceId().equals(sourceId)) { - condition = true; - } - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/h/HookHauntDrifter.java b/Mage.Sets/src/mage/cards/h/HookHauntDrifter.java index bd3eaf73dd..20484b801d 100644 --- a/Mage.Sets/src/mage/cards/h/HookHauntDrifter.java +++ b/Mage.Sets/src/mage/cards/h/HookHauntDrifter.java @@ -23,7 +23,6 @@ public final class HookHauntDrifter extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(2); this.color.setBlue(true); - this.transformable = true; this.nightCard = true; // Flying diff --git a/Mage.Sets/src/mage/cards/h/HostileHostel.java b/Mage.Sets/src/mage/cards/h/HostileHostel.java index 9156b6faeb..b0ceff1be5 100644 --- a/Mage.Sets/src/mage/cards/h/HostileHostel.java +++ b/Mage.Sets/src/mage/cards/h/HostileHostel.java @@ -6,7 +6,6 @@ import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.abilities.mana.ColorlessManaAbility; import mage.cards.CardImpl; @@ -31,7 +30,6 @@ public final class HostileHostel extends CardImpl { public HostileHostel(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); - this.transformable = true; this.secondSideCardClazz = mage.cards.c.CreepingInn.class; // {T}: Add {C}. @@ -39,11 +37,10 @@ public final class HostileHostel extends CardImpl { // {1}, {T}, Sacrifice a creature: Put a soul counter on Hostile Hostel. Then if there are three or more soul counters on it, remove those counters, transform it, then untap it. Activate only as a sorcery. this.addAbility(new TransformAbility()); - Ability ability = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new HostileHostelEffect(), new ManaCostsImpl("{1}")); + Ability ability = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new HostileHostelEffect(), new ManaCostsImpl<>("{1}")); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT))); this.addAbility(ability); - } private HostileHostel(final HostileHostel card) { @@ -82,7 +79,7 @@ class HostileHostelEffect extends OneShotEffect { int counters = permanent.getCounters(game).getCount(CounterType.SOUL); if (counters > 2) { permanent.removeCounters(CounterType.SOUL.getName(), counters, source, game); - new TransformSourceEffect(true).apply(game, source); + permanent.transform(source, game); permanent.untap(game); } return true; diff --git a/Mage.Sets/src/mage/cards/h/HoundTamer.java b/Mage.Sets/src/mage/cards/h/HoundTamer.java index d45833ecbd..f7cd37cdef 100644 --- a/Mage.Sets/src/mage/cards/h/HoundTamer.java +++ b/Mage.Sets/src/mage/cards/h/HoundTamer.java @@ -29,7 +29,6 @@ public final class HoundTamer extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(3); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.u.UntamedPup.class; // Trample diff --git a/Mage.Sets/src/mage/cards/h/HowlpackAlpha.java b/Mage.Sets/src/mage/cards/h/HowlpackAlpha.java index b877500f25..8ac3ceb528 100644 --- a/Mage.Sets/src/mage/cards/h/HowlpackAlpha.java +++ b/Mage.Sets/src/mage/cards/h/HowlpackAlpha.java @@ -40,7 +40,6 @@ public final class HowlpackAlpha extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.color.setGreen(true); this.power = new MageInt(3); diff --git a/Mage.Sets/src/mage/cards/h/HowlpackOfEstwald.java b/Mage.Sets/src/mage/cards/h/HowlpackOfEstwald.java index ded182d316..42f6134245 100644 --- a/Mage.Sets/src/mage/cards/h/HowlpackOfEstwald.java +++ b/Mage.Sets/src/mage/cards/h/HowlpackOfEstwald.java @@ -21,7 +21,6 @@ public final class HowlpackOfEstwald extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(4); this.toughness = new MageInt(6); diff --git a/Mage.Sets/src/mage/cards/h/HuntmasterOfTheFells.java b/Mage.Sets/src/mage/cards/h/HuntmasterOfTheFells.java index a79558e8ae..b2ab1b638e 100644 --- a/Mage.Sets/src/mage/cards/h/HuntmasterOfTheFells.java +++ b/Mage.Sets/src/mage/cards/h/HuntmasterOfTheFells.java @@ -28,7 +28,6 @@ public final class HuntmasterOfTheFells extends CardImpl { this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = mage.cards.r.RavagerOfTheFells.class; this.power = new MageInt(2); diff --git a/Mage.Sets/src/mage/cards/i/InfectiousCurse.java b/Mage.Sets/src/mage/cards/i/InfectiousCurse.java index 4d5aec7542..1ed1ff50d5 100644 --- a/Mage.Sets/src/mage/cards/i/InfectiousCurse.java +++ b/Mage.Sets/src/mage/cards/i/InfectiousCurse.java @@ -33,7 +33,6 @@ public final class InfectiousCurse extends CardImpl { this.color.setBlack(true); this.nightCard = true; - this.transformable = true; // Enchant player TargetPlayer auraTarget = new TargetPlayer(); diff --git a/Mage.Sets/src/mage/cards/i/InheritedFiend.java b/Mage.Sets/src/mage/cards/i/InheritedFiend.java index e76ba9ef80..52f35e6004 100644 --- a/Mage.Sets/src/mage/cards/i/InheritedFiend.java +++ b/Mage.Sets/src/mage/cards/i/InheritedFiend.java @@ -32,7 +32,6 @@ public final class InheritedFiend extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); this.color.setBlack(true); - this.transformable = true; this.nightCard = true; // Flying diff --git a/Mage.Sets/src/mage/cards/i/InsidiousMist.java b/Mage.Sets/src/mage/cards/i/InsidiousMist.java index d429fc40be..f5598c337d 100644 --- a/Mage.Sets/src/mage/cards/i/InsidiousMist.java +++ b/Mage.Sets/src/mage/cards/i/InsidiousMist.java @@ -36,7 +36,6 @@ public final class InsidiousMist extends CardImpl { this.color.setBlue(true); this.nightCard = true; - this.transformable = true; // Hexproof this.addAbility(HexproofAbility.getInstance()); @@ -53,7 +52,7 @@ public final class InsidiousMist extends CardImpl { // Whenever Insideous Mist attacks and isn't blocked, you may pay {2}{B}. If you do, transform it. this.addAbility(new TransformAbility()); - this.addAbility(new AttacksAndIsNotBlockedTriggeredAbility(new DoIfCostPaid(new TransformSourceEffect(false), new ManaCostsImpl("{2}{B}"), "Pay {2}{B} to transform?"))); + this.addAbility(new AttacksAndIsNotBlockedTriggeredAbility(new DoIfCostPaid(new TransformSourceEffect(), new ManaCostsImpl("{2}{B}"), "Pay {2}{B} to transform?"))); } private InsidiousMist(final InsidiousMist card) { diff --git a/Mage.Sets/src/mage/cards/i/InstigatorGang.java b/Mage.Sets/src/mage/cards/i/InstigatorGang.java index adbbb4ac48..a88e96462f 100644 --- a/Mage.Sets/src/mage/cards/i/InstigatorGang.java +++ b/Mage.Sets/src/mage/cards/i/InstigatorGang.java @@ -24,7 +24,6 @@ public final class InstigatorGang extends CardImpl { this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = mage.cards.w.WildbloodPack.class; this.power = new MageInt(2); diff --git a/Mage.Sets/src/mage/cards/i/Ironfang.java b/Mage.Sets/src/mage/cards/i/Ironfang.java index 2e287c1351..500ad43411 100644 --- a/Mage.Sets/src/mage/cards/i/Ironfang.java +++ b/Mage.Sets/src/mage/cards/i/Ironfang.java @@ -22,7 +22,6 @@ public final class Ironfang extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(3); this.toughness = new MageInt(1); diff --git a/Mage.Sets/src/mage/cards/j/JaceTelepathUnbound.java b/Mage.Sets/src/mage/cards/j/JaceTelepathUnbound.java index 16aa5f01c5..2ae3ad22e5 100644 --- a/Mage.Sets/src/mage/cards/j/JaceTelepathUnbound.java +++ b/Mage.Sets/src/mage/cards/j/JaceTelepathUnbound.java @@ -31,7 +31,6 @@ public final class JaceTelepathUnbound extends CardImpl { this.color.setBlue(true); this.nightCard = true; - this.transformable = true; this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(5)); diff --git a/Mage.Sets/src/mage/cards/j/JaceVrynsProdigy.java b/Mage.Sets/src/mage/cards/j/JaceVrynsProdigy.java index e2af5275a3..ec26a8ab46 100644 --- a/Mage.Sets/src/mage/cards/j/JaceVrynsProdigy.java +++ b/Mage.Sets/src/mage/cards/j/JaceVrynsProdigy.java @@ -34,7 +34,6 @@ public final class JaceVrynsProdigy extends CardImpl { this.power = new MageInt(0); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = JaceTelepathUnbound.class; // {T}: Draw a card, then discard a card. If there are five or more cards in your graveyard, exile Jace, Vryn's Prodigy, then return him to the battefield transformed under his owner's control. diff --git a/Mage.Sets/src/mage/cards/j/JerrenCorruptedBishop.java b/Mage.Sets/src/mage/cards/j/JerrenCorruptedBishop.java index aafbae1716..36eb28f00a 100644 --- a/Mage.Sets/src/mage/cards/j/JerrenCorruptedBishop.java +++ b/Mage.Sets/src/mage/cards/j/JerrenCorruptedBishop.java @@ -45,7 +45,6 @@ public final class JerrenCorruptedBishop extends CardImpl { this.subtype.add(SubType.CLERIC); this.power = new MageInt(2); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.o.OrmendahlTheCorrupter.class; // Whenever Jerren, Corrupted Bishop enters the battlefield or another nontoken Human you control dies, you lose 1 life and create a 1/1 white Human creature token. @@ -61,7 +60,7 @@ public final class JerrenCorruptedBishop extends CardImpl { // At the beginning of your end step, if you have exactly 13 life, you may pay {4}{B}{B}. If you do, transform Jerren. this.addAbility(new TransformAbility()); this.addAbility(new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, new DoIfCostPaid( - new TransformSourceEffect(true), new ManaCostsImpl<>("{4}{B}{B}") + new TransformSourceEffect(), new ManaCostsImpl<>("{4}{B}{B}") ), TargetController.YOU, JerrenCorruptedBishopCondition.instance, false)); } diff --git a/Mage.Sets/src/mage/cards/j/JourneyToEternity.java b/Mage.Sets/src/mage/cards/j/JourneyToEternity.java index 71595f95f7..cb54bb7b77 100644 --- a/Mage.Sets/src/mage/cards/j/JourneyToEternity.java +++ b/Mage.Sets/src/mage/cards/j/JourneyToEternity.java @@ -34,7 +34,6 @@ public final class JourneyToEternity extends CardImpl { this.addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.AURA); - this.transformable = true; this.secondSideCardClazz = mage.cards.a.AtzalCaveOfEternity.class; // Enchant creature you control diff --git a/Mage.Sets/src/mage/cards/k/KessigForgemaster.java b/Mage.Sets/src/mage/cards/k/KessigForgemaster.java index 110c958e84..1b2339634d 100644 --- a/Mage.Sets/src/mage/cards/k/KessigForgemaster.java +++ b/Mage.Sets/src/mage/cards/k/KessigForgemaster.java @@ -26,7 +26,6 @@ public final class KessigForgemaster extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.f.FlameheartWerewolf.class; // Whenever Kessig Forgemaster blocks or becomes blocked by a creature, Kessig Forgemaster deals 1 damage to that creature. diff --git a/Mage.Sets/src/mage/cards/k/KessigNaturalist.java b/Mage.Sets/src/mage/cards/k/KessigNaturalist.java index bc9096b8f5..bd4771b75f 100644 --- a/Mage.Sets/src/mage/cards/k/KessigNaturalist.java +++ b/Mage.Sets/src/mage/cards/k/KessigNaturalist.java @@ -30,7 +30,6 @@ public final class KessigNaturalist extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.l.LordOfTheUlvenwald.class; // Whenever Kessig Naturalist attacks, add {R} or {G}. Until end of turn, you don't lose this mana as steps and phases end. diff --git a/Mage.Sets/src/mage/cards/k/KessigProwler.java b/Mage.Sets/src/mage/cards/k/KessigProwler.java index 358e2cd746..93a7767ae4 100644 --- a/Mage.Sets/src/mage/cards/k/KessigProwler.java +++ b/Mage.Sets/src/mage/cards/k/KessigProwler.java @@ -26,12 +26,11 @@ public final class KessigProwler extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.s.SinuousPredator.class; // {4}{G}: Transform Kessig Prowler. this.addAbility(new TransformAbility()); - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new ManaCostsImpl("{4}{G}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new ManaCostsImpl("{4}{G}"))); } private KessigProwler(final KessigProwler card) { diff --git a/Mage.Sets/src/mage/cards/k/KindlyStranger.java b/Mage.Sets/src/mage/cards/k/KindlyStranger.java index 93e43fbd9e..d6edfa74ec 100644 --- a/Mage.Sets/src/mage/cards/k/KindlyStranger.java +++ b/Mage.Sets/src/mage/cards/k/KindlyStranger.java @@ -26,13 +26,12 @@ public final class KindlyStranger extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.d.DemonPossessedWitch.class; // Delirium — {2}{B}: Transform Kindly Stranger. Activate this ability only if there are four or more card types among cards in your graveyard. this.addAbility(new TransformAbility()); this.addAbility(new ConditionalActivatedAbility( - Zone.BATTLEFIELD, new TransformSourceEffect(true), new ManaCostsImpl<>("{2}{B}"), + Zone.BATTLEFIELD, new TransformSourceEffect(), new ManaCostsImpl<>("{2}{B}"), DeliriumCondition.instance, "Delirium — {2}{B}: Transform {this}. " + "Activate only if there are four or more card types among cards in your graveyard." ).addHint(CardTypesInGraveyardHint.YOU)); diff --git a/Mage.Sets/src/mage/cards/k/KrallenhordeHowler.java b/Mage.Sets/src/mage/cards/k/KrallenhordeHowler.java index 6d7fcccf93..c57d2e864b 100644 --- a/Mage.Sets/src/mage/cards/k/KrallenhordeHowler.java +++ b/Mage.Sets/src/mage/cards/k/KrallenhordeHowler.java @@ -29,7 +29,6 @@ public final class KrallenhordeHowler extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; // Creature spells you cast cost {1} less to cast. this.addAbility(new SimpleStaticAbility(new SpellsCostReductionControllerEffect(FILTER, 1))); diff --git a/Mage.Sets/src/mage/cards/k/KrallenhordeKiller.java b/Mage.Sets/src/mage/cards/k/KrallenhordeKiller.java index 71088f5410..6e7e4c4c8d 100644 --- a/Mage.Sets/src/mage/cards/k/KrallenhordeKiller.java +++ b/Mage.Sets/src/mage/cards/k/KrallenhordeKiller.java @@ -28,7 +28,6 @@ public final class KrallenhordeKiller extends CardImpl { this.toughness = new MageInt(2); this.nightCard = true; - this.transformable = true; // {3}{G}: Krallenhorde Killer gets +4/+4 until end of turn. Activate this ability only once each turn. this.addAbility(new LimitedTimesPerTurnActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(4, 4, Duration.EndOfTurn), new ManaCostsImpl("{3}{G}"))); diff --git a/Mage.Sets/src/mage/cards/k/KrallenhordeWantons.java b/Mage.Sets/src/mage/cards/k/KrallenhordeWantons.java index abd6712e7e..dc8e262460 100644 --- a/Mage.Sets/src/mage/cards/k/KrallenhordeWantons.java +++ b/Mage.Sets/src/mage/cards/k/KrallenhordeWantons.java @@ -21,7 +21,6 @@ public final class KrallenhordeWantons extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(7); this.toughness = new MageInt(7); diff --git a/Mage.Sets/src/mage/cards/k/KruinOutlaw.java b/Mage.Sets/src/mage/cards/k/KruinOutlaw.java index 63c8a27ebc..71b4862197 100644 --- a/Mage.Sets/src/mage/cards/k/KruinOutlaw.java +++ b/Mage.Sets/src/mage/cards/k/KruinOutlaw.java @@ -22,7 +22,6 @@ public final class KruinOutlaw extends CardImpl { this.subtype.add(SubType.ROGUE); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = mage.cards.t.TerrorOfKruinPass.class; this.power = new MageInt(2); diff --git a/Mage.Sets/src/mage/cards/k/KytheonHeroOfAkros.java b/Mage.Sets/src/mage/cards/k/KytheonHeroOfAkros.java index 0cb6d0ab75..768d3aaa97 100644 --- a/Mage.Sets/src/mage/cards/k/KytheonHeroOfAkros.java +++ b/Mage.Sets/src/mage/cards/k/KytheonHeroOfAkros.java @@ -40,7 +40,6 @@ public final class KytheonHeroOfAkros extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.g.GideonBattleForged.class; // At end of combat, if Kytheon, Hero of Akros and at least two other creatures attacked this combat, exile Kytheon, diff --git a/Mage.Sets/src/mage/cards/l/LambholtButcher.java b/Mage.Sets/src/mage/cards/l/LambholtButcher.java index b44499d9a5..7e168fbffb 100644 --- a/Mage.Sets/src/mage/cards/l/LambholtButcher.java +++ b/Mage.Sets/src/mage/cards/l/LambholtButcher.java @@ -2,18 +2,11 @@ package mage.cards.l; import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; -import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.WerewolfBackTriggeredAbility; -import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.common.TransformSourceEffect; -import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.TargetController; /** * @@ -30,7 +23,6 @@ public final class LambholtButcher extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Lambholt Butcher. this.addAbility(new WerewolfBackTriggeredAbility()); diff --git a/Mage.Sets/src/mage/cards/l/LambholtElder.java b/Mage.Sets/src/mage/cards/l/LambholtElder.java index 6ef1223ee3..9706367e69 100644 --- a/Mage.Sets/src/mage/cards/l/LambholtElder.java +++ b/Mage.Sets/src/mage/cards/l/LambholtElder.java @@ -23,7 +23,6 @@ public final class LambholtElder extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.s.SilverpeltWerewolf.class; // At the beginning of each upkeep, if no spells were cast last turn, transform Lambholt Elder. diff --git a/Mage.Sets/src/mage/cards/l/LambholtPacifist.java b/Mage.Sets/src/mage/cards/l/LambholtPacifist.java index 023c468e6c..3c19a77b79 100644 --- a/Mage.Sets/src/mage/cards/l/LambholtPacifist.java +++ b/Mage.Sets/src/mage/cards/l/LambholtPacifist.java @@ -29,7 +29,6 @@ public final class LambholtPacifist extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = LambholtButcher.class; // Lambholt Pacifist can't attack unless you control a creature with power 4 or greater. diff --git a/Mage.Sets/src/mage/cards/l/LeechingLurker.java b/Mage.Sets/src/mage/cards/l/LeechingLurker.java new file mode 100644 index 0000000000..1fc7474793 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LeechingLurker.java @@ -0,0 +1,43 @@ +package mage.cards.l; + +import mage.MageInt; +import mage.abilities.keyword.LifelinkAbility; +import mage.abilities.keyword.NightboundAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class LeechingLurker extends CardImpl { + + public LeechingLurker(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); + + this.subtype.add(SubType.LEECH); + this.subtype.add(SubType.HORROR); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + this.color.setBlack(true); + this.nightCard = true; + + // Lifelink + this.addAbility(LifelinkAbility.getInstance()); + + // Nightbound + this.addAbility(new NightboundAbility()); + } + + private LeechingLurker(final LeechingLurker card) { + super(card); + } + + @Override + public LeechingLurker copy() { + return new LeechingLurker(this); + } +} diff --git a/Mage.Sets/src/mage/cards/l/LegionsLanding.java b/Mage.Sets/src/mage/cards/l/LegionsLanding.java index 62dc9fed1c..baed5ab241 100644 --- a/Mage.Sets/src/mage/cards/l/LegionsLanding.java +++ b/Mage.Sets/src/mage/cards/l/LegionsLanding.java @@ -28,7 +28,6 @@ public final class LegionsLanding extends CardImpl { this.addSuperType(SuperType.LEGENDARY); - this.transformable = true; this.secondSideCardClazz = mage.cards.a.AdantoTheFirstFort.class; // When Legion's Landing enters the battlefield, create a 1/1 white Vampire creature token with lifelink. @@ -36,7 +35,7 @@ public final class LegionsLanding extends CardImpl { // When you attack with three or more creatures, transform Legion's Landing. this.addAbility(new TransformAbility()); - this.addAbility(new LegionsLandingTriggeredAbility(new TransformSourceEffect(true))); + this.addAbility(new LegionsLandingTriggeredAbility(new TransformSourceEffect())); } private LegionsLanding(final LegionsLanding card) { diff --git a/Mage.Sets/src/mage/cards/l/LilianaHereticalHealer.java b/Mage.Sets/src/mage/cards/l/LilianaHereticalHealer.java index fd5b07b1b8..740f2f2186 100644 --- a/Mage.Sets/src/mage/cards/l/LilianaHereticalHealer.java +++ b/Mage.Sets/src/mage/cards/l/LilianaHereticalHealer.java @@ -42,7 +42,6 @@ public final class LilianaHereticalHealer extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = LilianaDefiantNecromancer.class; this.addAbility(new TransformAbility()); diff --git a/Mage.Sets/src/mage/cards/l/LoneRider.java b/Mage.Sets/src/mage/cards/l/LoneRider.java index 8dc9205f81..b87c872bc6 100644 --- a/Mage.Sets/src/mage/cards/l/LoneRider.java +++ b/Mage.Sets/src/mage/cards/l/LoneRider.java @@ -37,7 +37,6 @@ public final class LoneRider extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.i.ItThatRidesAsOne.class; // First strike @@ -50,7 +49,7 @@ public final class LoneRider extends CardImpl { this.addAbility(new TransformAbility()); this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfEndStepTriggeredAbility( - new TransformSourceEffect(true), TargetController.NEXT, false + new TransformSourceEffect(), TargetController.NEXT, false ), condition, ruleText ).addHint(hint), new PlayerGainedLifeWatcher()); } diff --git a/Mage.Sets/src/mage/cards/l/LoneWolfOfTheNatterknolls.java b/Mage.Sets/src/mage/cards/l/LoneWolfOfTheNatterknolls.java index 1f6020f6f6..7dd9ba8be1 100644 --- a/Mage.Sets/src/mage/cards/l/LoneWolfOfTheNatterknolls.java +++ b/Mage.Sets/src/mage/cards/l/LoneWolfOfTheNatterknolls.java @@ -11,7 +11,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.filter.FilterSpell; import mage.filter.StaticFilters; import java.util.UUID; @@ -29,7 +28,6 @@ public final class LoneWolfOfTheNatterknolls extends CardImpl { this.color.setGreen(true); this.nightCard = true; - this.transformable = true; // Whenever an opponent cast a spell during your turn, draw two cards. this.addAbility(new ConditionalTriggeredAbility( diff --git a/Mage.Sets/src/mage/cards/l/LordOfLineage.java b/Mage.Sets/src/mage/cards/l/LordOfLineage.java index b20e7d6150..1c8d607999 100644 --- a/Mage.Sets/src/mage/cards/l/LordOfLineage.java +++ b/Mage.Sets/src/mage/cards/l/LordOfLineage.java @@ -40,7 +40,6 @@ public final class LordOfLineage extends CardImpl { // this card is the second face of double-faced card Bloodline Keeper this.nightCard = true; - this.transformable = true; this.addAbility(FlyingAbility.getInstance()); // Other Vampire creatures you control get +2/+2. diff --git a/Mage.Sets/src/mage/cards/l/LordOfTheUlvenwald.java b/Mage.Sets/src/mage/cards/l/LordOfTheUlvenwald.java index 05f56567b3..7fed8fc3c0 100644 --- a/Mage.Sets/src/mage/cards/l/LordOfTheUlvenwald.java +++ b/Mage.Sets/src/mage/cards/l/LordOfTheUlvenwald.java @@ -45,7 +45,6 @@ public final class LordOfTheUlvenwald extends CardImpl { this.color.setRed(true); this.color.setGreen(true); this.nightCard = true; - this.transformable = true; // Other Wolves and Werewolves you control get +1/+1. this.addAbility(new SimpleStaticAbility(new BoostControlledEffect( diff --git a/Mage.Sets/src/mage/cards/l/LoyalCathar.java b/Mage.Sets/src/mage/cards/l/LoyalCathar.java index 656073481f..eaa5912934 100644 --- a/Mage.Sets/src/mage/cards/l/LoyalCathar.java +++ b/Mage.Sets/src/mage/cards/l/LoyalCathar.java @@ -32,7 +32,6 @@ public final class LoyalCathar extends CardImpl { this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.SOLDIER); - this.transformable = true; this.secondSideCardClazz = mage.cards.u.UnhallowedCathar.class; this.power = new MageInt(2); diff --git a/Mage.Sets/src/mage/cards/l/LudevicNecrogenius.java b/Mage.Sets/src/mage/cards/l/LudevicNecrogenius.java new file mode 100644 index 0000000000..d7dab640a3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LudevicNecrogenius.java @@ -0,0 +1,61 @@ +package mage.cards.l; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.ActivateAsSorceryActivatedAbility; +import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility; +import mage.abilities.costs.common.ExileXFromYourGraveCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.costs.mana.VariableManaCost; +import mage.abilities.effects.common.InfoEffect; +import mage.abilities.effects.common.MillCardsControllerEffect; +import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.keyword.TransformAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.StaticFilters; +import mage.util.CardUtil; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class LudevicNecrogenius extends CardImpl { + + public LudevicNecrogenius(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}{B}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + this.secondSideCardClazz = mage.cards.o.OlagLudevicsHubris.class; + + // Whenever Ludevic, Necrogenius enters the battlefield or attacks, mill a card. + this.addAbility(new EntersBattlefieldOrAttacksSourceTriggeredAbility(new MillCardsControllerEffect(1))); + + // {X}{U}{U}{B}{B}, Exile X creature cards from your graveyard: Transform Ludevic, Necrogenius. X can't be zero. Activate only as a sorcery. + this.addAbility(new TransformAbility()); + Ability ability = new ActivateAsSorceryActivatedAbility( + new TransformSourceEffect(), new ManaCostsImpl<>("{X}{U}{U}{B}{B}") + ); + ability.addEffect(new InfoEffect("X can't be 0")); + ability.addCost(new ExileXFromYourGraveCost(StaticFilters.FILTER_CARD_CREATURES_YOUR_GRAVEYARD)); + CardUtil.castStream(ability.getCosts().stream(), VariableManaCost.class).forEach(cost -> cost.setMinX(1)); + this.addAbility(ability); + } + + private LudevicNecrogenius(final LudevicNecrogenius card) { + super(card); + } + + @Override + public LudevicNecrogenius copy() { + return new LudevicNecrogenius(this); + } +} diff --git a/Mage.Sets/src/mage/cards/l/LudevicsAbomination.java b/Mage.Sets/src/mage/cards/l/LudevicsAbomination.java index 4d9f5c3370..dcfe9517ef 100644 --- a/Mage.Sets/src/mage/cards/l/LudevicsAbomination.java +++ b/Mage.Sets/src/mage/cards/l/LudevicsAbomination.java @@ -23,7 +23,6 @@ public final class LudevicsAbomination extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(13); this.toughness = new MageInt(13); diff --git a/Mage.Sets/src/mage/cards/l/LudevicsTestSubject.java b/Mage.Sets/src/mage/cards/l/LudevicsTestSubject.java index 6733f34f0a..509e225b80 100644 --- a/Mage.Sets/src/mage/cards/l/LudevicsTestSubject.java +++ b/Mage.Sets/src/mage/cards/l/LudevicsTestSubject.java @@ -34,7 +34,6 @@ public final class LudevicsTestSubject extends CardImpl { this.power = new MageInt(0); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = LudevicsAbomination.class; this.addAbility(DefenderAbility.getInstance()); @@ -72,7 +71,7 @@ class LudevicsTestSubjectEffect extends OneShotEffect { if (p != null) { if (p.getCounters(game).getCount(CounterType.HATCHLING) >= 5) { p.removeCounters(CounterType.HATCHLING.getName(), p.getCounters(game).getCount(CounterType.HATCHLING), source, game); - TransformSourceEffect effect = new TransformSourceEffect(true); + TransformSourceEffect effect = new TransformSourceEffect(); return effect.apply(game, source); } } diff --git a/Mage.Sets/src/mage/cards/l/LuminousPhantom.java b/Mage.Sets/src/mage/cards/l/LuminousPhantom.java index 577fd9493f..052b41b86d 100644 --- a/Mage.Sets/src/mage/cards/l/LuminousPhantom.java +++ b/Mage.Sets/src/mage/cards/l/LuminousPhantom.java @@ -36,7 +36,6 @@ public final class LuminousPhantom extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); this.color.setWhite(true); - this.transformable = true; this.nightCard = true; // Flying diff --git a/Mage.Sets/src/mage/cards/l/LunarchVeteran.java b/Mage.Sets/src/mage/cards/l/LunarchVeteran.java index 61596d263f..a446183f23 100644 --- a/Mage.Sets/src/mage/cards/l/LunarchVeteran.java +++ b/Mage.Sets/src/mage/cards/l/LunarchVeteran.java @@ -26,7 +26,6 @@ public final class LunarchVeteran extends CardImpl { this.subtype.add(SubType.CLERIC); this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.l.LuminousPhantom.class; // Whenever another creature enters the battlefield under your control, you gain 1 life. diff --git a/Mage.Sets/src/mage/cards/m/MalevolentHermit.java b/Mage.Sets/src/mage/cards/m/MalevolentHermit.java index 743e168f11..83cd130ef3 100644 --- a/Mage.Sets/src/mage/cards/m/MalevolentHermit.java +++ b/Mage.Sets/src/mage/cards/m/MalevolentHermit.java @@ -30,7 +30,6 @@ public final class MalevolentHermit extends CardImpl { this.subtype.add(SubType.WIZARD); this.power = new MageInt(2); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.b.BenevolentGeist.class; // {U}, Sacrifice Malevolent Hermit: Counter target noncreature spell unless its controller pays {3}. diff --git a/Mage.Sets/src/mage/cards/m/MarkovsServant.java b/Mage.Sets/src/mage/cards/m/MarkovsServant.java index 5b73ca58c8..81a62c5356 100644 --- a/Mage.Sets/src/mage/cards/m/MarkovsServant.java +++ b/Mage.Sets/src/mage/cards/m/MarkovsServant.java @@ -22,7 +22,6 @@ public final class MarkovsServant extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); - this.transformable = true; this.nightCard = true; } diff --git a/Mage.Sets/src/mage/cards/m/MayorOfAvabruck.java b/Mage.Sets/src/mage/cards/m/MayorOfAvabruck.java index d3a85d1084..f9f11c9335 100644 --- a/Mage.Sets/src/mage/cards/m/MayorOfAvabruck.java +++ b/Mage.Sets/src/mage/cards/m/MayorOfAvabruck.java @@ -31,7 +31,6 @@ public final class MayorOfAvabruck extends CardImpl { this.subtype.add(SubType.ADVISOR); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = mage.cards.h.HowlpackAlpha.class; this.power = new MageInt(1); diff --git a/Mage.Sets/src/mage/cards/m/MercilessPredator.java b/Mage.Sets/src/mage/cards/m/MercilessPredator.java index 579f9b79f7..9ea43ac8cd 100644 --- a/Mage.Sets/src/mage/cards/m/MercilessPredator.java +++ b/Mage.Sets/src/mage/cards/m/MercilessPredator.java @@ -21,7 +21,6 @@ public final class MercilessPredator extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(3); this.toughness = new MageInt(2); diff --git a/Mage.Sets/src/mage/cards/m/MondronenShaman.java b/Mage.Sets/src/mage/cards/m/MondronenShaman.java index 2bedb848b5..8683524fe7 100644 --- a/Mage.Sets/src/mage/cards/m/MondronenShaman.java +++ b/Mage.Sets/src/mage/cards/m/MondronenShaman.java @@ -24,7 +24,6 @@ public final class MondronenShaman extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.t.TovolarsMagehunter.class; // At the beginning of each upkeep, if no spells were cast last turn, transform Mondronen Shaman. diff --git a/Mage.Sets/src/mage/cards/m/Moonmist.java b/Mage.Sets/src/mage/cards/m/Moonmist.java index e039f421f2..a952836ca1 100644 --- a/Mage.Sets/src/mage/cards/m/Moonmist.java +++ b/Mage.Sets/src/mage/cards/m/Moonmist.java @@ -1,7 +1,5 @@ - package mage.cards.m; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.PreventAllDamageByAllPermanentsEffect; @@ -16,13 +14,15 @@ import mage.filter.predicate.Predicates; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.UUID; + /** - * * @author BetaSteward */ public final class Moonmist extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures other than Werewolves and Wolves"); + private static final FilterCreaturePermanent filter + = new FilterCreaturePermanent("creatures other than Werewolves and Wolves"); static { filter.add(Predicates.not(SubType.WEREWOLF.getPredicate())); @@ -30,8 +30,7 @@ public final class Moonmist extends CardImpl { } public Moonmist(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{G}"); - + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}"); // Transform all Humans. Prevent all combat damage that would be dealt this turn by creatures other than Werewolves and Wolves. this.getSpellAbility().addEffect(new MoonmistEffect()); @@ -67,11 +66,8 @@ class MoonmistEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) { - if (permanent.isTransformable()) { - permanent.transform(game); - game.informPlayers(permanent.getName() + " transforms into " + permanent.getSecondCardFace().getName()); - } + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) { + permanent.transform(source, game); } return true; } @@ -80,5 +76,4 @@ class MoonmistEffect extends OneShotEffect { public MoonmistEffect copy() { return new MoonmistEffect(this); } - } diff --git a/Mage.Sets/src/mage/cards/m/MoonrageBrute.java b/Mage.Sets/src/mage/cards/m/MoonrageBrute.java index bbd90c57b4..eb754cd791 100644 --- a/Mage.Sets/src/mage/cards/m/MoonrageBrute.java +++ b/Mage.Sets/src/mage/cards/m/MoonrageBrute.java @@ -24,7 +24,6 @@ public final class MoonrageBrute extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(3); this.color.setRed(true); - this.transformable = true; this.nightCard = true; // First strike diff --git a/Mage.Sets/src/mage/cards/m/MoonragersSlash.java b/Mage.Sets/src/mage/cards/m/MoonragersSlash.java index f76db81ef3..a9167956ce 100644 --- a/Mage.Sets/src/mage/cards/m/MoonragersSlash.java +++ b/Mage.Sets/src/mage/cards/m/MoonragersSlash.java @@ -4,7 +4,7 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.NightCondition; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect; -import mage.abilities.hint.common.NightHint; +import mage.abilities.hint.common.DayNightHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -24,7 +24,7 @@ public final class MoonragersSlash extends CardImpl { // This spell costs {2} less to cast if it's night. this.addAbility(new SimpleStaticAbility( Zone.ALL, new SpellCostReductionSourceEffect(2, NightCondition.instance) - ).addHint(NightHint.instance).setRuleAtTheTop(true)); + ).addHint(DayNightHint.instance).setRuleAtTheTop(true)); // Moonrager's Slash deals 3 damage to any target. this.getSpellAbility().addEffect(new DamageTargetEffect(3)); diff --git a/Mage.Sets/src/mage/cards/m/MoonriseIntruder.java b/Mage.Sets/src/mage/cards/m/MoonriseIntruder.java index b765b98d6a..0d53062f18 100644 --- a/Mage.Sets/src/mage/cards/m/MoonriseIntruder.java +++ b/Mage.Sets/src/mage/cards/m/MoonriseIntruder.java @@ -24,7 +24,6 @@ public final class MoonriseIntruder extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; // Menace this.addAbility(new MenaceAbility()); diff --git a/Mage.Sets/src/mage/cards/m/MoonscarredWerewolf.java b/Mage.Sets/src/mage/cards/m/MoonscarredWerewolf.java index c5ee197498..7bc6a02be3 100644 --- a/Mage.Sets/src/mage/cards/m/MoonscarredWerewolf.java +++ b/Mage.Sets/src/mage/cards/m/MoonscarredWerewolf.java @@ -29,7 +29,6 @@ public final class MoonscarredWerewolf extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.addAbility(VigilanceAbility.getInstance()); diff --git a/Mage.Sets/src/mage/cards/m/MorningApparition.java b/Mage.Sets/src/mage/cards/m/MorningApparition.java index 2ab7a6c258..3b04cf354d 100644 --- a/Mage.Sets/src/mage/cards/m/MorningApparition.java +++ b/Mage.Sets/src/mage/cards/m/MorningApparition.java @@ -25,7 +25,6 @@ public final class MorningApparition extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); this.color.setWhite(true); - this.transformable = true; this.nightCard = true; // Flying diff --git a/Mage.Sets/src/mage/cards/m/MourningPatrol.java b/Mage.Sets/src/mage/cards/m/MourningPatrol.java index 8065c06f1f..cf0aad468d 100644 --- a/Mage.Sets/src/mage/cards/m/MourningPatrol.java +++ b/Mage.Sets/src/mage/cards/m/MourningPatrol.java @@ -24,7 +24,6 @@ public final class MourningPatrol extends CardImpl { this.subtype.add(SubType.SOLDIER); this.power = new MageInt(2); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.m.MorningApparition.class; // Vigilance diff --git a/Mage.Sets/src/mage/cards/m/MysteriousTome.java b/Mage.Sets/src/mage/cards/m/MysteriousTome.java index 3458823bb0..100d607c82 100644 --- a/Mage.Sets/src/mage/cards/m/MysteriousTome.java +++ b/Mage.Sets/src/mage/cards/m/MysteriousTome.java @@ -21,7 +21,6 @@ public final class MysteriousTome extends CardImpl { public MysteriousTome(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}{U}"); - this.transformable = true; this.secondSideCardClazz = mage.cards.c.ChillingChronicle.class; // {2}, {T}: Draw a card. Transform Mysterious Tome. @@ -30,7 +29,7 @@ public final class MysteriousTome extends CardImpl { new DrawCardSourceControllerEffect(1), new GenericManaCost(2) ); ability.addCost(new TapSourceCost()); - ability.addEffect(new TransformSourceEffect(true)); + ability.addEffect(new TransformSourceEffect()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MysticMonstrosity.java b/Mage.Sets/src/mage/cards/m/MysticMonstrosity.java index 931d03eba2..3ba9014ef3 100644 --- a/Mage.Sets/src/mage/cards/m/MysticMonstrosity.java +++ b/Mage.Sets/src/mage/cards/m/MysticMonstrosity.java @@ -24,7 +24,6 @@ public final class MysticMonstrosity extends CardImpl { this.subtype.add(SubType.CONSTRUCT); this.power = new MageInt(5); this.toughness = new MageInt(6); - this.transformable = true; this.nightCard = true; // Lands you control have "{T}: Add one mana of any color." diff --git a/Mage.Sets/src/mage/cards/m/MysticSkull.java b/Mage.Sets/src/mage/cards/m/MysticSkull.java index 5c655efc6d..e9a14a8635 100644 --- a/Mage.Sets/src/mage/cards/m/MysticSkull.java +++ b/Mage.Sets/src/mage/cards/m/MysticSkull.java @@ -21,7 +21,6 @@ public final class MysticSkull extends CardImpl { public MysticSkull(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); - this.transformable = true; this.secondSideCardClazz = mage.cards.m.MysticMonstrosity.class; // {1}, {T}: Add one mana of any color. @@ -31,7 +30,7 @@ public final class MysticSkull extends CardImpl { // {5}, {T}: Transform Mystic Skull. this.addAbility(new TransformAbility()); - ability = new SimpleActivatedAbility(new TransformSourceEffect(true), new GenericManaCost(5)); + ability = new SimpleActivatedAbility(new TransformSourceEffect(), new GenericManaCost(5)); ability.addCost(new TapSourceCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/n/NeckBreaker.java b/Mage.Sets/src/mage/cards/n/NeckBreaker.java index 4f9b4f0b7f..96ced371e3 100644 --- a/Mage.Sets/src/mage/cards/n/NeckBreaker.java +++ b/Mage.Sets/src/mage/cards/n/NeckBreaker.java @@ -30,7 +30,6 @@ public final class NeckBreaker extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; // Attacking creatures you control get +1/+0 and have trample. Ability ability = new SimpleStaticAbility(new BoostControlledEffect( diff --git a/Mage.Sets/src/mage/cards/n/NeglectedHeirloom.java b/Mage.Sets/src/mage/cards/n/NeglectedHeirloom.java index f2506666e4..810e1cb6d3 100644 --- a/Mage.Sets/src/mage/cards/n/NeglectedHeirloom.java +++ b/Mage.Sets/src/mage/cards/n/NeglectedHeirloom.java @@ -28,7 +28,6 @@ public final class NeglectedHeirloom extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}"); this.subtype.add(SubType.EQUIPMENT); - this.transformable = true; this.secondSideCardClazz = mage.cards.a.AshmouthBlade.class; // Equipped creature gets +1/+1. @@ -56,7 +55,7 @@ public final class NeglectedHeirloom extends CardImpl { class NeglectedHeirloomTriggeredAbility extends TriggeredAbilityImpl { public NeglectedHeirloomTriggeredAbility() { - super(Zone.BATTLEFIELD, new TransformSourceEffect(true), false); + super(Zone.BATTLEFIELD, new TransformSourceEffect(), false); } public NeglectedHeirloomTriggeredAbility(final NeglectedHeirloomTriggeredAbility ability) { diff --git a/Mage.Sets/src/mage/cards/n/NicolBolasTheArisen.java b/Mage.Sets/src/mage/cards/n/NicolBolasTheArisen.java index 1b28ff7329..de5f1adbe8 100644 --- a/Mage.Sets/src/mage/cards/n/NicolBolasTheArisen.java +++ b/Mage.Sets/src/mage/cards/n/NicolBolasTheArisen.java @@ -48,7 +48,6 @@ public final class NicolBolasTheArisen extends CardImpl { this.color.setBlack(true); this.color.setRed(true); this.nightCard = true; - this.transformable = true; this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(7)); diff --git a/Mage.Sets/src/mage/cards/n/NicolBolasTheRavager.java b/Mage.Sets/src/mage/cards/n/NicolBolasTheRavager.java index 30a8d6b826..2ffc04c2ac 100644 --- a/Mage.Sets/src/mage/cards/n/NicolBolasTheRavager.java +++ b/Mage.Sets/src/mage/cards/n/NicolBolasTheRavager.java @@ -34,7 +34,6 @@ public final class NicolBolasTheRavager extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = NicolBolasTheArisen.class; // Flying diff --git a/Mage.Sets/src/mage/cards/n/NightfallPredator.java b/Mage.Sets/src/mage/cards/n/NightfallPredator.java index 7b3d840e22..bc354ed542 100644 --- a/Mage.Sets/src/mage/cards/n/NightfallPredator.java +++ b/Mage.Sets/src/mage/cards/n/NightfallPredator.java @@ -30,7 +30,6 @@ public final class NightfallPredator extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; // {R}, {tap}: Nightfall Predator fights target creature. Ability activatedAbility = new SimpleActivatedAbility( diff --git a/Mage.Sets/src/mage/cards/n/NissaVastwoodSeer.java b/Mage.Sets/src/mage/cards/n/NissaVastwoodSeer.java index 0323490ff2..63dbfb1898 100644 --- a/Mage.Sets/src/mage/cards/n/NissaVastwoodSeer.java +++ b/Mage.Sets/src/mage/cards/n/NissaVastwoodSeer.java @@ -40,8 +40,7 @@ public final class NissaVastwoodSeer extends CardImpl { this.subtype.add(SubType.SCOUT); this.power = new MageInt(2); this.toughness = new MageInt(2); - - this.transformable = true; + this.secondSideCardClazz = NissaSageAnimist.class; // When Nissa, Vastwood Seer enters the battlefield, you may search your library for a basic Forest card, reveal it, put it into your hand, then shuffle your library. diff --git a/Mage.Sets/src/mage/cards/o/OlagLudevicsHubris.java b/Mage.Sets/src/mage/cards/o/OlagLudevicsHubris.java new file mode 100644 index 0000000000..b3cf3cd498 --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/OlagLudevicsHubris.java @@ -0,0 +1,135 @@ +package mage.cards.o; + +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.CopyEffect; +import mage.cards.*; +import mage.constants.*; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.permanent.PermanentCard; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.common.TargetCardInExile; +import mage.util.CardUtil; +import mage.util.functions.CopyApplier; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class OlagLudevicsHubris extends CardImpl { + + public OlagLudevicsHubris(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.ZOMBIE); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + this.color.setBlue(true); + this.color.setBlack(true); + this.nightCard = true; + + // As this creature transforms in Olag, Ludevic's Hubris, it becomes a copy of a creature card exiled with it, except its name is Olag, Ludevic's Hubris, it's 4/4, and it's a legendary blue and black Zombie in addition to its other colors and types. Put a number of +1/+1 counters on Olag equal to the number of creature cards exiled with it. + this.addAbility(new SimpleStaticAbility(new OlagLudevicsHubrisEffect())); + } + + private OlagLudevicsHubris(final OlagLudevicsHubris card) { + super(card); + } + + @Override + public OlagLudevicsHubris copy() { + return new OlagLudevicsHubris(this); + } +} + +class OlagLudevicsHubrisEffect extends ReplacementEffectImpl { + + OlagLudevicsHubrisEffect() { + super(Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = "as this creature transforms into {this}, it becomes a copy of a creature card exiled with it, " + + "except its name is Olag, Ludevic's Hubris, it's 4/4, and it's a legendary blue and black " + + "Zombie in addition to its other colors and types. Put a number of +1/+1 counters on {this} " + + "equal to the number of creature cards exiled with it"; + } + + private OlagLudevicsHubrisEffect(final OlagLudevicsHubrisEffect effect) { + super(effect); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Cards cards = new CardsImpl(game.getExile().getExileZone(CardUtil.getExileZoneId(game, source))); + cards.removeIf(uuid -> !game.getCard(uuid).isCreature(game)); + if (cards.isEmpty()) { + return false; + } + Card copyFromCard = getCard(cards, source, game); + if (copyFromCard == null) { + return false; + } + Permanent newBluePrint = new PermanentCard(copyFromCard, source.getControllerId(), game); + newBluePrint.assignNewId(); + CopyApplier applier = new OlagLudevicsHubrisCopyApplier(); + applier.apply(game, newBluePrint, source, source.getSourceId()); + CopyEffect copyEffect = new CopyEffect(Duration.Custom, newBluePrint, source.getSourceId()); + copyEffect.newId(); + copyEffect.setApplier(applier); + Ability newAbility = source.copy(); + copyEffect.init(newAbility, game); + game.addEffect(copyEffect, newAbility); + return false; + } + + private Card getCard(Cards cards, Ability source, Game game) { + if (cards.size() == 1) { + return cards.getRandom(game); + } + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return cards.getRandom(game); + } + TargetCard target = new TargetCardInExile(StaticFilters.FILTER_CARD); + player.choose(outcome, target, source.getSourceId(), game); + return cards.get(target.getFirstTarget(), game); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.TRANSFORMING; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + return source.getSourceId().equals(event.getTargetId()) + && source.getSourcePermanentIfItStillExists(game) != null; + } + + @Override + public OlagLudevicsHubrisEffect copy() { + return new OlagLudevicsHubrisEffect(this); + } +} + +class OlagLudevicsHubrisCopyApplier extends CopyApplier { + + @Override + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { + blueprint.setName("Olag, Ludevic's Hubris"); + blueprint.addSuperType(SuperType.LEGENDARY); + blueprint.addSubType(SubType.ZOMBIE); + blueprint.getColor().setBlue(true); + blueprint.getColor().setBlack(true); + blueprint.getPower().modifyBaseValue(4); + blueprint.getToughness().modifyBaseValue(4); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/o/OliviasMidnightAmbush.java b/Mage.Sets/src/mage/cards/o/OliviasMidnightAmbush.java index 872ea104fa..ca02f9b792 100644 --- a/Mage.Sets/src/mage/cards/o/OliviasMidnightAmbush.java +++ b/Mage.Sets/src/mage/cards/o/OliviasMidnightAmbush.java @@ -4,7 +4,7 @@ import mage.abilities.Ability; import mage.abilities.condition.common.NightCondition; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; -import mage.abilities.hint.common.NightHint; +import mage.abilities.hint.common.DayNightHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -25,7 +25,7 @@ public final class OliviasMidnightAmbush extends CardImpl { // Target creature gets -2/-2 until end of turn. If it's night, that creature gets -13/-13 until end of turn instead. this.getSpellAbility().addEffect(new OliviasMidnightAmbushEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - this.getSpellAbility().addHint(NightHint.instance); + this.getSpellAbility().addHint(DayNightHint.instance); } private OliviasMidnightAmbush(final OliviasMidnightAmbush card) { diff --git a/Mage.Sets/src/mage/cards/o/OneOfThePack.java b/Mage.Sets/src/mage/cards/o/OneOfThePack.java index 9a47b281d5..40ce2562a2 100644 --- a/Mage.Sets/src/mage/cards/o/OneOfThePack.java +++ b/Mage.Sets/src/mage/cards/o/OneOfThePack.java @@ -22,7 +22,6 @@ public final class OneOfThePack extends CardImpl { this.color.setGreen(true); this.nightCard = true; - this.transformable = true; // At the beginning of each upkeep, if a player cast two or more spells last turn, transform One of the Pack. this.addAbility(new WerewolfBackTriggeredAbility()); diff --git a/Mage.Sets/src/mage/cards/o/OrmendahlTheCorrupter.java b/Mage.Sets/src/mage/cards/o/OrmendahlTheCorrupter.java index 59c786aa5d..5fd1f827fc 100644 --- a/Mage.Sets/src/mage/cards/o/OrmendahlTheCorrupter.java +++ b/Mage.Sets/src/mage/cards/o/OrmendahlTheCorrupter.java @@ -30,7 +30,6 @@ public final class OrmendahlTheCorrupter extends CardImpl { this.power = new MageInt(6); this.toughness = new MageInt(6); this.color.setBlack(true); - this.transformable = true; this.nightCard = true; // Flying diff --git a/Mage.Sets/src/mage/cards/o/OutlandLiberator.java b/Mage.Sets/src/mage/cards/o/OutlandLiberator.java index 3e27af7711..d384f06dc5 100644 --- a/Mage.Sets/src/mage/cards/o/OutlandLiberator.java +++ b/Mage.Sets/src/mage/cards/o/OutlandLiberator.java @@ -12,6 +12,8 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import java.util.UUID; @@ -27,12 +29,12 @@ public final class OutlandLiberator extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(2); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.f.FrenziedTrapbreaker.class; // {1}, Sacrifice Outland Liberator: Destroy target artifact or enchantment. Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new GenericManaCost(1)); ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT)); this.addAbility(ability); // Daybound diff --git a/Mage.Sets/src/mage/cards/o/OverwhelmedArchivist.java b/Mage.Sets/src/mage/cards/o/OverwhelmedArchivist.java index 724a434b1f..52313b4b83 100644 --- a/Mage.Sets/src/mage/cards/o/OverwhelmedArchivist.java +++ b/Mage.Sets/src/mage/cards/o/OverwhelmedArchivist.java @@ -25,7 +25,6 @@ public final class OverwhelmedArchivist extends CardImpl { this.subtype.add(SubType.WIZARD); this.power = new MageInt(3); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.a.ArchiveHaunt.class; // When Overwhelmed Archivist enters the battlefield, draw a card, then discard a card. diff --git a/Mage.Sets/src/mage/cards/p/PathOfMettle.java b/Mage.Sets/src/mage/cards/p/PathOfMettle.java index 78af4037d5..70584579e9 100644 --- a/Mage.Sets/src/mage/cards/p/PathOfMettle.java +++ b/Mage.Sets/src/mage/cards/p/PathOfMettle.java @@ -45,7 +45,6 @@ public final class PathOfMettle extends CardImpl { this.addSuperType(SuperType.LEGENDARY); - this.transformable = true; this.secondSideCardClazz = mage.cards.m.MetzaliTowerOfTriumph.class; // When Path of Mettle enters the battlefield, it deals 1 damage to each creature that doesn't have first strike, double strike, vigilance, or haste. @@ -80,7 +79,7 @@ class PathOfMettleTriggeredAbility extends TriggeredAbilityImpl { } public PathOfMettleTriggeredAbility() { - super(Zone.BATTLEFIELD, new TransformSourceEffect(true)); + super(Zone.BATTLEFIELD, new TransformSourceEffect()); } public PathOfMettleTriggeredAbility(final PathOfMettleTriggeredAbility ability) { diff --git a/Mage.Sets/src/mage/cards/p/PersistentNightmare.java b/Mage.Sets/src/mage/cards/p/PersistentNightmare.java index 13511fdea1..d1825f3f44 100644 --- a/Mage.Sets/src/mage/cards/p/PersistentNightmare.java +++ b/Mage.Sets/src/mage/cards/p/PersistentNightmare.java @@ -1,7 +1,5 @@ - package mage.cards.p; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.effects.common.ReturnToHandSourceEffect; @@ -11,14 +9,15 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class PersistentNightmare extends CardImpl { public PersistentNightmare(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},""); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); this.subtype.add(SubType.NIGHTMARE); this.power = new MageInt(1); this.toughness = new MageInt(1); @@ -31,7 +30,9 @@ public final class PersistentNightmare extends CardImpl { this.addAbility(new SkulkAbility()); // When Persistent Nightmare deals combat damage to a player, return it to its owner's hand. - this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new ReturnToHandSourceEffect(), false)); + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility( + new ReturnToHandSourceEffect(), false + ).setTriggerPhrase("When {this} deals combat damage to a player, ")); } private PersistentNightmare(final PersistentNightmare card) { diff --git a/Mage.Sets/src/mage/cards/p/PiousEvangel.java b/Mage.Sets/src/mage/cards/p/PiousEvangel.java index e4dd6ae851..c7ac5cb8e3 100644 --- a/Mage.Sets/src/mage/cards/p/PiousEvangel.java +++ b/Mage.Sets/src/mage/cards/p/PiousEvangel.java @@ -43,7 +43,6 @@ public final class PiousEvangel extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.w.WaywardDisciple.class; // Whenever Pious Evangel or another creature enters the battlefield under your control, you gain 1 life. @@ -51,7 +50,7 @@ public final class PiousEvangel extends CardImpl { // {2}, {T}, Sacrifice another permanent: Transform Pious Evangel. this.addAbility(new TransformAbility()); - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new GenericManaCost(2)); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new GenericManaCost(2)); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(filter2))); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/p/PoppetFactory.java b/Mage.Sets/src/mage/cards/p/PoppetFactory.java index b4a7985bb2..0dd4568570 100644 --- a/Mage.Sets/src/mage/cards/p/PoppetFactory.java +++ b/Mage.Sets/src/mage/cards/p/PoppetFactory.java @@ -26,14 +26,13 @@ public final class PoppetFactory extends CardImpl { this.color.setBlue(true); this.nightCard = true; - this.transformable = true; // Creature tokens you control lose all abilities and have base power and toughness 3/3. this.addAbility(new SimpleStaticAbility(new PoppetFactoryEffect())); // At the beginning of your upkeep, you may transform Poppet Factory. this.addAbility(new BeginningOfUpkeepTriggeredAbility( - new TransformSourceEffect(false), TargetController.YOU, true + new TransformSourceEffect(), TargetController.YOU, true )); } diff --git a/Mage.Sets/src/mage/cards/p/PoppetStitcher.java b/Mage.Sets/src/mage/cards/p/PoppetStitcher.java index 7cd11c4d79..07e4dab0ae 100644 --- a/Mage.Sets/src/mage/cards/p/PoppetStitcher.java +++ b/Mage.Sets/src/mage/cards/p/PoppetStitcher.java @@ -43,7 +43,6 @@ public final class PoppetStitcher extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.p.PoppetFactory.class; // Whenever you cast an instant or sorcery spell, create a 2/2 black Zombie creature token with decayed. @@ -56,7 +55,7 @@ public final class PoppetStitcher extends CardImpl { this.addAbility(new TransformAbility()); this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility( - new TransformSourceEffect(true), + new TransformSourceEffect(), TargetController.YOU, true ), condition, "At the beginning of your upkeep, " + "if you control three or more creature tokens, you may transform {this}." diff --git a/Mage.Sets/src/mage/cards/p/PrimalAmulet.java b/Mage.Sets/src/mage/cards/p/PrimalAmulet.java index d8e17789c6..b15a482046 100644 --- a/Mage.Sets/src/mage/cards/p/PrimalAmulet.java +++ b/Mage.Sets/src/mage/cards/p/PrimalAmulet.java @@ -39,7 +39,6 @@ public final class PrimalAmulet extends CardImpl { public PrimalAmulet(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); - this.transformable = true; this.secondSideCardClazz = PrimalWellspring.class; // Instant and sorcery spells you cast cost {1} less to cast. @@ -87,7 +86,7 @@ class PrimalAmuletEffect extends OneShotEffect { int counters = permanent.getCounters(game).getCount(CounterType.CHARGE); if (counters > 3 && player.chooseUse(Outcome.Benefit, "Transform this?", source, game)) { permanent.removeCounters("charge", counters, source, game); - new TransformSourceEffect(true).apply(game, source); + new TransformSourceEffect().apply(game, source); } return true; } diff --git a/Mage.Sets/src/mage/cards/p/ProfaneProcession.java b/Mage.Sets/src/mage/cards/p/ProfaneProcession.java index 3c0baffc3e..cdf06c4a1a 100644 --- a/Mage.Sets/src/mage/cards/p/ProfaneProcession.java +++ b/Mage.Sets/src/mage/cards/p/ProfaneProcession.java @@ -33,7 +33,6 @@ public final class ProfaneProcession extends CardImpl { this.addSuperType(SuperType.LEGENDARY); - this.transformable = true; this.secondSideCardClazz = mage.cards.t.TombOfTheDuskRose.class; // {3}{W}{B}: Exile target creature. Then if there are three or more cards exiled with Profane Procession, transform it. @@ -79,7 +78,7 @@ class ProfaneProcessionEffect extends OneShotEffect { game.getState().processAction(game); ExileZone exileZone = game.getExile().getExileZone(exileId); if (exileZone != null && exileZone.size() > 2) { - new TransformSourceEffect(true).apply(game, source); + new TransformSourceEffect().apply(game, source); } return true; } diff --git a/Mage.Sets/src/mage/cards/r/RampagingWerewolf.java b/Mage.Sets/src/mage/cards/r/RampagingWerewolf.java index 93cbf1d62a..b31735e695 100644 --- a/Mage.Sets/src/mage/cards/r/RampagingWerewolf.java +++ b/Mage.Sets/src/mage/cards/r/RampagingWerewolf.java @@ -21,7 +21,6 @@ public final class RampagingWerewolf extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(6); this.toughness = new MageInt(4); diff --git a/Mage.Sets/src/mage/cards/r/RavagerOfTheFells.java b/Mage.Sets/src/mage/cards/r/RavagerOfTheFells.java index 8b4c020a10..788c49c74f 100644 --- a/Mage.Sets/src/mage/cards/r/RavagerOfTheFells.java +++ b/Mage.Sets/src/mage/cards/r/RavagerOfTheFells.java @@ -40,7 +40,6 @@ public final class RavagerOfTheFells extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(4); this.toughness = new MageInt(4); diff --git a/Mage.Sets/src/mage/cards/r/RavenousDemon.java b/Mage.Sets/src/mage/cards/r/RavenousDemon.java index 59e53fbb94..d4f60829f8 100644 --- a/Mage.Sets/src/mage/cards/r/RavenousDemon.java +++ b/Mage.Sets/src/mage/cards/r/RavenousDemon.java @@ -30,7 +30,6 @@ public final class RavenousDemon extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}"); this.subtype.add(SubType.DEMON); - this.transformable = true; this.secondSideCardClazz = mage.cards.a.ArchdemonOfGreed.class; this.power = new MageInt(4); @@ -38,7 +37,7 @@ public final class RavenousDemon extends CardImpl { // Sacrifice a Human: Transform Ravenous Demon. Activate this ability only any time you could cast a sorcery. this.addAbility(new TransformAbility()); - this.addAbility(new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new SacrificeTargetCost(new TargetControlledPermanent(filter)))); + this.addAbility(new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new SacrificeTargetCost(new TargetControlledPermanent(filter)))); } private RavenousDemon(final RavenousDemon card) { diff --git a/Mage.Sets/src/mage/cards/r/RecklessStormseeker.java b/Mage.Sets/src/mage/cards/r/RecklessStormseeker.java index 8b78f15c06..c6f1bce00c 100644 --- a/Mage.Sets/src/mage/cards/r/RecklessStormseeker.java +++ b/Mage.Sets/src/mage/cards/r/RecklessStormseeker.java @@ -30,7 +30,6 @@ public final class RecklessStormseeker extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(2); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.s.StormChargedSlasher.class; // At the beginning of combat on your turn, target creature you control gets +1/+0 and gains haste until end of turn. diff --git a/Mage.Sets/src/mage/cards/r/RecklessWaif.java b/Mage.Sets/src/mage/cards/r/RecklessWaif.java index 848d23ac62..dae8b27df7 100644 --- a/Mage.Sets/src/mage/cards/r/RecklessWaif.java +++ b/Mage.Sets/src/mage/cards/r/RecklessWaif.java @@ -21,7 +21,6 @@ public final class RecklessWaif extends CardImpl { this.subtype.add(SubType.ROGUE); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = mage.cards.m.MercilessPredator.class; this.power = new MageInt(1); diff --git a/Mage.Sets/src/mage/cards/s/SageOfAncientLore.java b/Mage.Sets/src/mage/cards/s/SageOfAncientLore.java index 1dd23df372..0d28e9a5cf 100644 --- a/Mage.Sets/src/mage/cards/s/SageOfAncientLore.java +++ b/Mage.Sets/src/mage/cards/s/SageOfAncientLore.java @@ -33,7 +33,6 @@ public final class SageOfAncientLore extends CardImpl { this.power = new MageInt(0); this.toughness = new MageInt(0); - this.transformable = true; this.secondSideCardClazz = mage.cards.w.WerewolfOfAncientHunger.class; // Sage of Ancient Lore's power and toughness are each equal to the number of cards in your hand. diff --git a/Mage.Sets/src/mage/cards/s/ScornedVillager.java b/Mage.Sets/src/mage/cards/s/ScornedVillager.java index 69cce60517..2092c0575b 100644 --- a/Mage.Sets/src/mage/cards/s/ScornedVillager.java +++ b/Mage.Sets/src/mage/cards/s/ScornedVillager.java @@ -24,7 +24,6 @@ public final class ScornedVillager extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.m.MoonscarredWerewolf.class; // {tap}: Add {G}. diff --git a/Mage.Sets/src/mage/cards/s/ScreechingBat.java b/Mage.Sets/src/mage/cards/s/ScreechingBat.java index 8c1c31fd8b..ddfabda856 100644 --- a/Mage.Sets/src/mage/cards/s/ScreechingBat.java +++ b/Mage.Sets/src/mage/cards/s/ScreechingBat.java @@ -1,12 +1,9 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.costs.Cost; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.TransformAbility; @@ -14,11 +11,9 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; +import mage.constants.TargetController; + +import java.util.UUID; /** * @author nantuko @@ -29,7 +24,6 @@ public final class ScreechingBat extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); this.subtype.add(SubType.BAT); - this.transformable = true; this.secondSideCardClazz = StalkingVampire.class; this.power = new MageInt(2); @@ -39,7 +33,10 @@ public final class ScreechingBat extends CardImpl { // At the beginning of your upkeep, you may pay {2}{B}{B}. If you do, transform Screeching Bat. this.addAbility(new TransformAbility()); - this.addAbility(new ScreechingBatBeginningOfUpkeepTriggeredAbility()); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DoIfCostPaid( + new TransformSourceEffect(), + new ManaCostsImpl<>("{2}{B}{B}") + ), TargetController.YOU, false)); } private ScreechingBat(final ScreechingBat card) { @@ -51,65 +48,3 @@ public final class ScreechingBat extends CardImpl { return new ScreechingBat(this); } } - -class ScreechingBatBeginningOfUpkeepTriggeredAbility extends TriggeredAbilityImpl { - - public ScreechingBatBeginningOfUpkeepTriggeredAbility() { - super(Zone.BATTLEFIELD, new ScreechingBatTransformSourceEffect(), true); - } - - public ScreechingBatBeginningOfUpkeepTriggeredAbility(final ScreechingBatBeginningOfUpkeepTriggeredAbility ability) { - super(ability); - } - - @Override - public ScreechingBatBeginningOfUpkeepTriggeredAbility copy() { - return new ScreechingBatBeginningOfUpkeepTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.UPKEEP_STEP_PRE; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - return event.getPlayerId().equals(this.controllerId); - } - - @Override - public String getRule() { - return "At the beginning of your upkeep, you may pay {2}{B}{B}. If you do, transform {this}."; - } -} - -class ScreechingBatTransformSourceEffect extends OneShotEffect { - - public ScreechingBatTransformSourceEffect() { - super(Outcome.Transform); - staticText = "transform {this}"; - } - - public ScreechingBatTransformSourceEffect(final ScreechingBatTransformSourceEffect effect) { - super(effect); - } - - @Override - public ScreechingBatTransformSourceEffect copy() { - return new ScreechingBatTransformSourceEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - Cost cost = new ManaCostsImpl("{2}{B}{B}"); - if (cost.pay(source, game, source, permanent.getControllerId(), false, null)) { - new TransformSourceEffect(true).apply(game, source); - } - return true; - } - return false; - } - -} diff --git a/Mage.Sets/src/mage/cards/s/SeafaringWerewolf.java b/Mage.Sets/src/mage/cards/s/SeafaringWerewolf.java index c075a58ed9..56b3b8c705 100644 --- a/Mage.Sets/src/mage/cards/s/SeafaringWerewolf.java +++ b/Mage.Sets/src/mage/cards/s/SeafaringWerewolf.java @@ -24,7 +24,6 @@ public final class SeafaringWerewolf extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); this.color.setGreen(true); - this.transformable = true; this.nightCard = true; // Seafaring Werewolf can't be blocked. diff --git a/Mage.Sets/src/mage/cards/s/SearchForAzcanta.java b/Mage.Sets/src/mage/cards/s/SearchForAzcanta.java index 32cb3ac144..6973145726 100644 --- a/Mage.Sets/src/mage/cards/s/SearchForAzcanta.java +++ b/Mage.Sets/src/mage/cards/s/SearchForAzcanta.java @@ -29,7 +29,6 @@ public final class SearchForAzcanta extends CardImpl { public SearchForAzcanta(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}"); - this.transformable = true; this.secondSideCardClazz = mage.cards.a.AzcantaTheSunkenRuin.class; this.addSuperType(SuperType.LEGENDARY); @@ -80,7 +79,7 @@ class SearchForAzcantaLookLibraryEffect extends OneShotEffect { controller.moveCards(card, Zone.GRAVEYARD, source, game); } if (controller.getGraveyard().size() > 6 && controller.chooseUse(Outcome.Neutral, "Transform " + sourceObject.getLogName() + "?", source, game)) { - new TransformSourceEffect(true).apply(game, source); + new TransformSourceEffect().apply(game, source); } } } diff --git a/Mage.Sets/src/mage/cards/s/SeasonedCathar.java b/Mage.Sets/src/mage/cards/s/SeasonedCathar.java index 85d9b7e587..57397897f3 100644 --- a/Mage.Sets/src/mage/cards/s/SeasonedCathar.java +++ b/Mage.Sets/src/mage/cards/s/SeasonedCathar.java @@ -22,7 +22,6 @@ public final class SeasonedCathar extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(3); this.color.setWhite(true); - this.transformable = true; this.nightCard = true; // Lifelink diff --git a/Mage.Sets/src/mage/cards/s/ShadyTraveler.java b/Mage.Sets/src/mage/cards/s/ShadyTraveler.java index f2424f3002..97840bed8d 100644 --- a/Mage.Sets/src/mage/cards/s/ShadyTraveler.java +++ b/Mage.Sets/src/mage/cards/s/ShadyTraveler.java @@ -23,7 +23,6 @@ public final class ShadyTraveler extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(2); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.s.StalkingPredator.class; // Menace diff --git a/Mage.Sets/src/mage/cards/s/ShrillHowler.java b/Mage.Sets/src/mage/cards/s/ShrillHowler.java index bfd0b23bd2..b08fa88df9 100644 --- a/Mage.Sets/src/mage/cards/s/ShrillHowler.java +++ b/Mage.Sets/src/mage/cards/s/ShrillHowler.java @@ -28,7 +28,6 @@ public final class ShrillHowler extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.h.HowlingChorus.class; // Creatures with power less than Shrill Howler's power can't block it. @@ -36,7 +35,7 @@ public final class ShrillHowler extends CardImpl { // {5}{G}: Transform Shrill Howler. this.addAbility(new TransformAbility()); - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new ManaCostsImpl<>("{5}{G}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new ManaCostsImpl<>("{5}{G}"))); } diff --git a/Mage.Sets/src/mage/cards/s/SilverpeltWerewolf.java b/Mage.Sets/src/mage/cards/s/SilverpeltWerewolf.java index e98bee109b..8bf1157c99 100644 --- a/Mage.Sets/src/mage/cards/s/SilverpeltWerewolf.java +++ b/Mage.Sets/src/mage/cards/s/SilverpeltWerewolf.java @@ -24,7 +24,6 @@ public final class SilverpeltWerewolf extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(5); - this.transformable = true; this.nightCard = true; // Whenever Silverpelt Werewolf deals combat damage to a player, draw a card. diff --git a/Mage.Sets/src/mage/cards/s/SkinInvasion.java b/Mage.Sets/src/mage/cards/s/SkinInvasion.java index 570fc75c93..d41fd9d265 100644 --- a/Mage.Sets/src/mage/cards/s/SkinInvasion.java +++ b/Mage.Sets/src/mage/cards/s/SkinInvasion.java @@ -34,7 +34,6 @@ public final class SkinInvasion extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{R}"); this.subtype.add(SubType.AURA); - this.transformable = true; this.secondSideCardClazz = SkinShedder.class; // Enchant creature diff --git a/Mage.Sets/src/mage/cards/s/SmolderingEgg.java b/Mage.Sets/src/mage/cards/s/SmolderingEgg.java index b64c045305..cf07316e41 100644 --- a/Mage.Sets/src/mage/cards/s/SmolderingEgg.java +++ b/Mage.Sets/src/mage/cards/s/SmolderingEgg.java @@ -33,7 +33,6 @@ public final class SmolderingEgg extends CardImpl { this.subtype.add(SubType.EGG); this.power = new MageInt(0); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = mage.cards.a.AshmouthDragon.class; // Defender @@ -92,7 +91,7 @@ class SmolderingEggEffect extends OneShotEffect { return true; } permanent.removeCounters(CounterType.EMBER.createInstance(counters), source, game); - new TransformSourceEffect(true).apply(game, source); + new TransformSourceEffect().apply(game, source); return true; } } diff --git a/Mage.Sets/src/mage/cards/s/SmolderingWerewolf.java b/Mage.Sets/src/mage/cards/s/SmolderingWerewolf.java index 755b9fa460..42825ddfee 100644 --- a/Mage.Sets/src/mage/cards/s/SmolderingWerewolf.java +++ b/Mage.Sets/src/mage/cards/s/SmolderingWerewolf.java @@ -31,7 +31,6 @@ public final class SmolderingWerewolf extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.e.EruptingDreadwolf.class; // When Smoldering Werewolf enters the battlefield, it deals 1 damage to each of up to two target creatures. @@ -43,7 +42,7 @@ public final class SmolderingWerewolf extends CardImpl { // {4}{R}{R}: Transform Smoldering Werewolf. this.addAbility(new TransformAbility()); - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new ManaCostsImpl("{4}{R}{R}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new ManaCostsImpl("{4}{R}{R}"))); } private SmolderingWerewolf(final SmolderingWerewolf card) { diff --git a/Mage.Sets/src/mage/cards/s/SolitaryHunter.java b/Mage.Sets/src/mage/cards/s/SolitaryHunter.java index 12a6694d70..29ca759d8e 100644 --- a/Mage.Sets/src/mage/cards/s/SolitaryHunter.java +++ b/Mage.Sets/src/mage/cards/s/SolitaryHunter.java @@ -24,7 +24,6 @@ public final class SolitaryHunter extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = mage.cards.o.OneOfThePack.class; // At the beginning of each upkeep, if no spells were cast last turn, transform Solitary Hunter. diff --git a/Mage.Sets/src/mage/cards/s/SoulSeizer.java b/Mage.Sets/src/mage/cards/s/SoulSeizer.java index f3b909ec3f..0902e44ae2 100644 --- a/Mage.Sets/src/mage/cards/s/SoulSeizer.java +++ b/Mage.Sets/src/mage/cards/s/SoulSeizer.java @@ -1,8 +1,5 @@ - package mage.cards.s; -import java.util.UUID; - import mage.MageInt; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; @@ -12,19 +9,20 @@ import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.events.DamagedPlayerEvent; import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** * @author BetaSteward */ @@ -34,7 +32,6 @@ public final class SoulSeizer extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}"); this.subtype.add(SubType.SPIRIT); - this.transformable = true; this.secondSideCardClazz = mage.cards.g.GhastlyHaunting.class; this.power = new MageInt(1); @@ -113,16 +110,11 @@ class SoulSeizerEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null && permanent.isTransformable()) { - if (permanent.transform(game)) { - game.informPlayers(permanent.getName() + " transforms into " + permanent.getSecondCardFace().getName()); - Permanent attachTo = game.getPermanent(targetPointer.getFirst(game, source)); - if (attachTo != null) { - return attachTo.addAttachment(source.getSourceId(), source, game); - } - } + if (permanent == null || !permanent.transform(source, game)) { + return false; } - return false; + Permanent attachTo = game.getPermanent(targetPointer.getFirst(game, source)); + return attachTo != null && attachTo.addAttachment(source.getSourceId(), source, game); } @Override diff --git a/Mage.Sets/src/mage/cards/s/SpellruneHowler.java b/Mage.Sets/src/mage/cards/s/SpellruneHowler.java index a7419fbe12..e8c5b16fdc 100644 --- a/Mage.Sets/src/mage/cards/s/SpellruneHowler.java +++ b/Mage.Sets/src/mage/cards/s/SpellruneHowler.java @@ -26,7 +26,6 @@ public final class SpellruneHowler extends CardImpl { this.toughness = new MageInt(4); this.color.setRed(true); this.nightCard = true; - this.transformable = true; // Whenever you cast an instant or sorcery spell, Spellrune Howler gets +2/+2 until end of turn. this.addAbility(new SpellCastControllerTriggeredAbility( diff --git a/Mage.Sets/src/mage/cards/s/SpellrunePainter.java b/Mage.Sets/src/mage/cards/s/SpellrunePainter.java index 8a7b20c345..572b4cf414 100644 --- a/Mage.Sets/src/mage/cards/s/SpellrunePainter.java +++ b/Mage.Sets/src/mage/cards/s/SpellrunePainter.java @@ -27,7 +27,6 @@ public final class SpellrunePainter extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(2); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.s.SpellruneHowler.class; // Whenever you cast an instant or sorcery spell, Spellrune Painter gets +1/+1 until end of turn. diff --git a/Mage.Sets/src/mage/cards/s/StalkingPredator.java b/Mage.Sets/src/mage/cards/s/StalkingPredator.java index 98ce16017b..41a12f42f9 100644 --- a/Mage.Sets/src/mage/cards/s/StalkingPredator.java +++ b/Mage.Sets/src/mage/cards/s/StalkingPredator.java @@ -22,7 +22,6 @@ public final class StalkingPredator extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); this.color.setBlack(true); - this.transformable = true; this.nightCard = true; // Menace diff --git a/Mage.Sets/src/mage/cards/s/StalkingVampire.java b/Mage.Sets/src/mage/cards/s/StalkingVampire.java index 66065d0fba..c126b2078e 100644 --- a/Mage.Sets/src/mage/cards/s/StalkingVampire.java +++ b/Mage.Sets/src/mage/cards/s/StalkingVampire.java @@ -1,23 +1,17 @@ package mage.cards.s; import mage.MageInt; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.TransformSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import mage.constants.TargetController; import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.costs.Cost; -import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.TransformSourceEffect; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; /** * @author nantuko @@ -30,13 +24,15 @@ public final class StalkingVampire extends CardImpl { this.color.setBlack(true); this.nightCard = true; - this.transformable = true; this.power = new MageInt(5); this.toughness = new MageInt(5); // At the beginning of your upkeep, you may pay {2}{B}{B}. If you do, transform Stalking Vampire. - this.addAbility(new StalkingVampireBeginningOfUpkeepTriggeredAbility()); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DoIfCostPaid( + new TransformSourceEffect(), + new ManaCostsImpl<>("{2}{B}{B}") + ), TargetController.YOU, false)); } private StalkingVampire(final StalkingVampire card) { @@ -48,65 +44,3 @@ public final class StalkingVampire extends CardImpl { return new StalkingVampire(this); } } - -class StalkingVampireBeginningOfUpkeepTriggeredAbility extends TriggeredAbilityImpl { - - public StalkingVampireBeginningOfUpkeepTriggeredAbility() { - super(Zone.BATTLEFIELD, new StalkingVampireTransformSourceEffect(), true); - } - - public StalkingVampireBeginningOfUpkeepTriggeredAbility(final StalkingVampireBeginningOfUpkeepTriggeredAbility ability) { - super(ability); - } - - @Override - public StalkingVampireBeginningOfUpkeepTriggeredAbility copy() { - return new StalkingVampireBeginningOfUpkeepTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.UPKEEP_STEP_PRE; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - return event.getPlayerId().equals(this.controllerId); - } - - @Override - public String getRule() { - return "At the beginning of your upkeep, you may pay {2}{B}{B}. If you do, transform {this}."; - } -} - -class StalkingVampireTransformSourceEffect extends OneShotEffect { - - public StalkingVampireTransformSourceEffect() { - super(Outcome.Transform); - staticText = "transform {this}"; - } - - public StalkingVampireTransformSourceEffect(final StalkingVampireTransformSourceEffect effect) { - super(effect); - } - - @Override - public StalkingVampireTransformSourceEffect copy() { - return new StalkingVampireTransformSourceEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - Cost cost = new ManaCostsImpl("{2}{B}{B}"); - if (cost.pay(source, game, source, permanent.getControllerId(), false, null)) { - new TransformSourceEffect(false).apply(game, source); - } - return true; - } - return false; - } - -} diff --git a/Mage.Sets/src/mage/cards/s/StartledAwake.java b/Mage.Sets/src/mage/cards/s/StartledAwake.java index ee34baf9f9..d2709bba45 100644 --- a/Mage.Sets/src/mage/cards/s/StartledAwake.java +++ b/Mage.Sets/src/mage/cards/s/StartledAwake.java @@ -1,8 +1,6 @@ - package mage.cards.s; -import java.util.UUID; - +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.ActivateAsSorceryActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; @@ -19,6 +17,8 @@ import mage.game.Game; import mage.players.Player; import mage.target.common.TargetOpponent; +import java.util.UUID; + /** * @author LevelX2 */ @@ -27,7 +27,6 @@ public final class StartledAwake extends CardImpl { public StartledAwake(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{U}{U}"); - this.transformable = true; this.secondSideCardClazz = mage.cards.p.PersistentNightmare.class; // Target opponent puts the top thirteen cards of their library into their graveyard. @@ -36,9 +35,9 @@ public final class StartledAwake extends CardImpl { // {3}{U}{U}: Put Startled Awake from your graveyard onto the battlefield transformed. Activate this ability only any time you could cast a sorcery. this.addAbility(new TransformAbility()); - Ability ability = new ActivateAsSorceryActivatedAbility(Zone.GRAVEYARD, new StartledAwakeReturnTransformedEffect(), new ManaCostsImpl("{3}{U}{U}")); - this.addAbility(ability); - + this.addAbility(new ActivateAsSorceryActivatedAbility( + Zone.GRAVEYARD, new StartledAwakeReturnTransformedEffect(), new ManaCostsImpl<>("{3}{U}{U}") + )); } private StartledAwake(final StartledAwake card) { @@ -70,16 +69,16 @@ class StartledAwakeReturnTransformedEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - if (game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD) { - game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE); - Card card = game.getCard(source.getSourceId()); - if (card != null) { - controller.moveCards(card, Zone.BATTLEFIELD, source, game); - } - } + MageObject sourceObject = source.getSourceObjectIfItStillExists(game); + if (controller == null || !(sourceObject instanceof Card)) { + return false; + } + if (game.getState().getZone(source.getSourceId()) != Zone.GRAVEYARD) { return true; } - return false; + Card card = (Card) sourceObject; + game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), true); + controller.moveCards(card, Zone.BATTLEFIELD, source, game); + return true; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/s/StormChargedSlasher.java b/Mage.Sets/src/mage/cards/s/StormChargedSlasher.java index 93ba611b36..7557903736 100644 --- a/Mage.Sets/src/mage/cards/s/StormChargedSlasher.java +++ b/Mage.Sets/src/mage/cards/s/StormChargedSlasher.java @@ -30,7 +30,6 @@ public final class StormChargedSlasher extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(4); this.color.setRed(true); - this.transformable = true; this.nightCard = true; // At the beginning of combat on your turn, target creature you control gets +2/+0 and gains trample and haste until end of turn. diff --git a/Mage.Sets/src/mage/cards/s/StormTheVault.java b/Mage.Sets/src/mage/cards/s/StormTheVault.java index 5dd55b22a3..7e40fbc049 100644 --- a/Mage.Sets/src/mage/cards/s/StormTheVault.java +++ b/Mage.Sets/src/mage/cards/s/StormTheVault.java @@ -29,7 +29,6 @@ public final class StormTheVault extends CardImpl { this.addSuperType(SuperType.LEGENDARY); - this.transformable = true; this.secondSideCardClazz = mage.cards.v.VaultOfCatlacan.class; // Whenever one or more creatures you control deal combat damage to a player, create a colorless Treasure artifact token with "{T}, Sacrifice this artifact: Add one mana of any color." @@ -38,7 +37,7 @@ public final class StormTheVault extends CardImpl { // At the beginning of your end step, if you control five or more artifacts, transform Storm the Vault. this.addAbility(new TransformAbility()); this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility(new TransformSourceEffect(true), TargetController.YOU, false), + new BeginningOfEndStepTriggeredAbility(new TransformSourceEffect(), TargetController.YOU, false), new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT, ComparisonType.MORE_THAN, 4), "At the beginning of your end step, if you control five or more artifacts, transform {this}")); diff --git a/Mage.Sets/src/mage/cards/s/StranglingGrasp.java b/Mage.Sets/src/mage/cards/s/StranglingGrasp.java index c3665cff1a..2c78cb5ff1 100644 --- a/Mage.Sets/src/mage/cards/s/StranglingGrasp.java +++ b/Mage.Sets/src/mage/cards/s/StranglingGrasp.java @@ -38,7 +38,6 @@ public final class StranglingGrasp extends CardImpl { this.subtype.add(SubType.AURA); this.color.setBlack(true); - this.transformable = true; this.nightCard = true; // Enchant creature or planeswalker an opponent controls diff --git a/Mage.Sets/src/mage/cards/s/SuspiciousStowaway.java b/Mage.Sets/src/mage/cards/s/SuspiciousStowaway.java index 83c217f6fc..f12bb5ecd9 100644 --- a/Mage.Sets/src/mage/cards/s/SuspiciousStowaway.java +++ b/Mage.Sets/src/mage/cards/s/SuspiciousStowaway.java @@ -26,7 +26,6 @@ public final class SuspiciousStowaway extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.s.SeafaringWerewolf.class; // Suspicious Stowaway can't be blocked. diff --git a/Mage.Sets/src/mage/cards/t/TangleclawWerewolf.java b/Mage.Sets/src/mage/cards/t/TangleclawWerewolf.java index a7133e5cb1..5ddfe0c12b 100644 --- a/Mage.Sets/src/mage/cards/t/TangleclawWerewolf.java +++ b/Mage.Sets/src/mage/cards/t/TangleclawWerewolf.java @@ -29,7 +29,6 @@ public final class TangleclawWerewolf extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = mage.cards.f.FibrousEntangler.class; // Tangleclaw Werewolf can block an additional creature each combat. @@ -37,7 +36,7 @@ public final class TangleclawWerewolf extends CardImpl { // {6}{G}: Transform Tangleclaw Werewolf. this.addAbility(new TransformAbility()); - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new ManaCostsImpl<>("{6}{G}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new ManaCostsImpl<>("{6}{G}"))); } private TangleclawWerewolf(final TangleclawWerewolf card) { diff --git a/Mage.Sets/src/mage/cards/t/TavernRuffian.java b/Mage.Sets/src/mage/cards/t/TavernRuffian.java index b06f875bd5..dc0e39395e 100644 --- a/Mage.Sets/src/mage/cards/t/TavernRuffian.java +++ b/Mage.Sets/src/mage/cards/t/TavernRuffian.java @@ -24,7 +24,6 @@ public final class TavernRuffian extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(5); - this.transformable = true; this.secondSideCardClazz = mage.cards.t.TavernSmasher.class; // Daybound diff --git a/Mage.Sets/src/mage/cards/t/TavernSmasher.java b/Mage.Sets/src/mage/cards/t/TavernSmasher.java index 8a3b1258e5..23e61cd013 100644 --- a/Mage.Sets/src/mage/cards/t/TavernSmasher.java +++ b/Mage.Sets/src/mage/cards/t/TavernSmasher.java @@ -22,7 +22,6 @@ public final class TavernSmasher extends CardImpl { this.color.setRed(true); this.nightCard = true; - this.transformable = true; this.power = new MageInt(6); this.toughness = new MageInt(5); diff --git a/Mage.Sets/src/mage/cards/t/TerrorOfKruinPass.java b/Mage.Sets/src/mage/cards/t/TerrorOfKruinPass.java index 7e3cb3b8a8..7811cf8be5 100644 --- a/Mage.Sets/src/mage/cards/t/TerrorOfKruinPass.java +++ b/Mage.Sets/src/mage/cards/t/TerrorOfKruinPass.java @@ -28,7 +28,6 @@ public final class TerrorOfKruinPass extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.color.setRed(true); this.power = new MageInt(3); diff --git a/Mage.Sets/src/mage/cards/t/ThaumaticCompass.java b/Mage.Sets/src/mage/cards/t/ThaumaticCompass.java index a3d446cfae..f8ca94370e 100644 --- a/Mage.Sets/src/mage/cards/t/ThaumaticCompass.java +++ b/Mage.Sets/src/mage/cards/t/ThaumaticCompass.java @@ -31,7 +31,6 @@ public final class ThaumaticCompass extends CardImpl { public ThaumaticCompass(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); - this.transformable = true; this.secondSideCardClazz = mage.cards.s.SpiresOfOrazca.class; // {3}, {T}: Search your library for a basic land card, reveal it, put it into your hand, then shuffle your library. @@ -43,7 +42,7 @@ public final class ThaumaticCompass extends CardImpl { // At the beginning of your end step, if you control seven or more lands, transform Thaumatic Compass. this.addAbility(new TransformAbility()); - TriggeredAbility ability2 = new BeginningOfEndStepTriggeredAbility(new TransformSourceEffect(true), TargetController.YOU, false); + TriggeredAbility ability2 = new BeginningOfEndStepTriggeredAbility(new TransformSourceEffect(), TargetController.YOU, false); this.addAbility(new ConditionalInterveningIfTriggeredAbility( ability2, new PermanentsOnTheBattlefieldCondition(new FilterLandPermanent(), ComparisonType.MORE_THAN, 6, true), diff --git a/Mage.Sets/src/mage/cards/t/TheCelestus.java b/Mage.Sets/src/mage/cards/t/TheCelestus.java new file mode 100644 index 0000000000..24bc5c1f85 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TheCelestus.java @@ -0,0 +1,114 @@ +package mage.cards.t; + +import mage.abilities.Ability; +import mage.abilities.common.ActivateAsSorceryActivatedAbility; +import mage.abilities.common.BecomeDayAsEntersAbility; +import mage.abilities.common.BecomesDayOrNightTriggeredAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.mana.AnyColorManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SuperType; +import mage.game.Game; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TheCelestus extends CardImpl { + + public TheCelestus(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); + + this.addSuperType(SuperType.LEGENDARY); + + // If it's neither day nor night, it becomes day as The Celestus enters the battlefield. + this.addAbility(new BecomeDayAsEntersAbility()); + + // {T}: Add one mana of any color. + this.addAbility(new AnyColorManaAbility()); + + // {3}, {T}: If it's night, it becomes day. Otherwise, it becomes night. Activate only as a sorcery. + Ability ability = new ActivateAsSorceryActivatedAbility( + new TheCelestusDayNightEffect(), new GenericManaCost(3) + ); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + + // Whenever day becomes night or night becomes day, you gain 1 life. You may draw a card. If you do, discard a card. + this.addAbility(new BecomesDayOrNightTriggeredAbility(new TheCelestusLootEffect())); + } + + private TheCelestus(final TheCelestus card) { + super(card); + } + + @Override + public TheCelestus copy() { + return new TheCelestus(this); + } +} + +class TheCelestusDayNightEffect extends OneShotEffect { + + TheCelestusDayNightEffect() { + super(Outcome.Benefit); + staticText = "if it's night, it becomes day. Otherwise, it becomes night"; + } + + private TheCelestusDayNightEffect(final TheCelestusDayNightEffect effect) { + super(effect); + } + + @Override + public TheCelestusDayNightEffect copy() { + return new TheCelestusDayNightEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + if (game.checkDayNight(false)) { + game.setDaytime(true); + } else { + game.setDaytime(false); + } + return true; + } +} + +class TheCelestusLootEffect extends OneShotEffect { + + TheCelestusLootEffect() { + super(Outcome.DrawCard); + staticText = "you gain 1 life. You may draw a card. If you do, discard a card"; + } + + private TheCelestusLootEffect(final TheCelestusLootEffect effect) { + super(effect); + } + + @Override + public TheCelestusLootEffect copy() { + return new TheCelestusLootEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + player.gainLife(1, game, source); + if (player.chooseUse(outcome, "Draw a card?", source, game)) { + player.drawCards(1, source, game); + player.discard(1, false, false, source, game); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/t/TheUpsideDown.java b/Mage.Sets/src/mage/cards/t/TheUpsideDown.java index a009868606..cdaed4dd00 100644 --- a/Mage.Sets/src/mage/cards/t/TheUpsideDown.java +++ b/Mage.Sets/src/mage/cards/t/TheUpsideDown.java @@ -33,9 +33,8 @@ public final class TheUpsideDown extends CardImpl { public TheUpsideDown(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); - this.addSuperType(SuperType.LEGENDARY); - this.transformable = true; + this.nightCard = true; // When this land transforms into The Upside Down, return target creature card from your graveyard to the battlefield. @@ -144,7 +143,7 @@ class TheUpsideDownEffect extends OneShotEffect { class TheUpsideDownLeavesAbility extends TriggeredAbilityImpl { TheUpsideDownLeavesAbility() { - super(Zone.BATTLEFIELD, new TransformSourceEffect(false)); + super(Zone.BATTLEFIELD, new TransformSourceEffect()); } private TheUpsideDownLeavesAbility(final TheUpsideDownLeavesAbility ability) { diff --git a/Mage.Sets/src/mage/cards/t/ThingInTheIce.java b/Mage.Sets/src/mage/cards/t/ThingInTheIce.java index 5274ac890e..20a0332349 100644 --- a/Mage.Sets/src/mage/cards/t/ThingInTheIce.java +++ b/Mage.Sets/src/mage/cards/t/ThingInTheIce.java @@ -42,7 +42,6 @@ public final class ThingInTheIce extends CardImpl { this.power = new MageInt(0); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = mage.cards.a.AwokenHorror.class; // Defender @@ -58,7 +57,7 @@ public final class ThingInTheIce extends CardImpl { effect = new RemoveCounterSourceEffect(CounterType.ICE.createInstance(1)); effect.setText("remove an ice counter from {this}"); Ability ability = new SpellCastControllerTriggeredAbility(effect, filter, false); - effect = new ConditionalOneShotEffect(new TransformSourceEffect(true), new SourceHasCounterCondition(CounterType.ICE, 0, 0), + effect = new ConditionalOneShotEffect(new TransformSourceEffect(), new SourceHasCounterCondition(CounterType.ICE, 0, 0), "if there are no ice counters on it, transform it"); ability.addEffect(effect); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/t/ThrabenGargoyle.java b/Mage.Sets/src/mage/cards/t/ThrabenGargoyle.java index 0aa7323da1..d2861c441b 100644 --- a/Mage.Sets/src/mage/cards/t/ThrabenGargoyle.java +++ b/Mage.Sets/src/mage/cards/t/ThrabenGargoyle.java @@ -26,7 +26,6 @@ public final class ThrabenGargoyle extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.s.StonewingAntagonizer.class; // Defender @@ -34,7 +33,7 @@ public final class ThrabenGargoyle extends CardImpl { // {6}: Transform Thraben Gargoyle. this.addAbility(new TransformAbility()); - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new GenericManaCost(6))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new GenericManaCost(6))); } private ThrabenGargoyle(final ThrabenGargoyle card) { diff --git a/Mage.Sets/src/mage/cards/t/ThrabenMilitia.java b/Mage.Sets/src/mage/cards/t/ThrabenMilitia.java index 65bad5e707..d9998dc592 100644 --- a/Mage.Sets/src/mage/cards/t/ThrabenMilitia.java +++ b/Mage.Sets/src/mage/cards/t/ThrabenMilitia.java @@ -22,7 +22,6 @@ public final class ThrabenMilitia extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(5); this.toughness = new MageInt(4); diff --git a/Mage.Sets/src/mage/cards/t/ThrabenSentry.java b/Mage.Sets/src/mage/cards/t/ThrabenSentry.java index 5b6ceba84f..1269ff1b84 100644 --- a/Mage.Sets/src/mage/cards/t/ThrabenSentry.java +++ b/Mage.Sets/src/mage/cards/t/ThrabenSentry.java @@ -23,7 +23,6 @@ public final class ThrabenSentry extends CardImpl { this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.SOLDIER); - this.transformable = true; this.secondSideCardClazz = ThrabenMilitia.class; this.power = new MageInt(2); @@ -33,7 +32,7 @@ public final class ThrabenSentry extends CardImpl { // Whenever another creature you control dies, you may transform Thraben Sentry. this.addAbility(new TransformAbility()); - this.addAbility(new DiesCreatureTriggeredAbility(new TransformSourceEffect(true), true, new FilterControlledCreaturePermanent())); + this.addAbility(new DiesCreatureTriggeredAbility(new TransformSourceEffect(), true, new FilterControlledCreaturePermanent())); } private ThrabenSentry(final ThrabenSentry card) { diff --git a/Mage.Sets/src/mage/cards/t/TimberShredder.java b/Mage.Sets/src/mage/cards/t/TimberShredder.java index 186ba31618..6fe22125f0 100644 --- a/Mage.Sets/src/mage/cards/t/TimberShredder.java +++ b/Mage.Sets/src/mage/cards/t/TimberShredder.java @@ -24,7 +24,6 @@ public final class TimberShredder extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; // Trample this.addAbility(TrampleAbility.getInstance()); diff --git a/Mage.Sets/src/mage/cards/t/TirelessHauler.java b/Mage.Sets/src/mage/cards/t/TirelessHauler.java index c50d0ac4ca..5c643892b1 100644 --- a/Mage.Sets/src/mage/cards/t/TirelessHauler.java +++ b/Mage.Sets/src/mage/cards/t/TirelessHauler.java @@ -23,7 +23,6 @@ public final class TirelessHauler extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(4); this.toughness = new MageInt(5); - this.transformable = true; this.secondSideCardClazz = mage.cards.d.DireStrainBrawler.class; // Vigilance diff --git a/Mage.Sets/src/mage/cards/t/TormentedPariah.java b/Mage.Sets/src/mage/cards/t/TormentedPariah.java index 36a88c23c0..7d5997a1c5 100644 --- a/Mage.Sets/src/mage/cards/t/TormentedPariah.java +++ b/Mage.Sets/src/mage/cards/t/TormentedPariah.java @@ -21,7 +21,6 @@ public final class TormentedPariah extends CardImpl { this.subtype.add(SubType.WARRIOR); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = mage.cards.r.RampagingWerewolf.class; this.power = new MageInt(3); diff --git a/Mage.Sets/src/mage/cards/t/TovolarDireOverlord.java b/Mage.Sets/src/mage/cards/t/TovolarDireOverlord.java new file mode 100644 index 0000000000..4a50e15529 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TovolarDireOverlord.java @@ -0,0 +1,125 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.hint.Hint; +import mage.abilities.hint.ValueHint; +import mage.abilities.keyword.DayboundAbility; +import mage.abilities.keyword.TransformAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.Predicates; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TovolarDireOverlord extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledPermanent("a Wolf or Werewolf you control"); + + static { + filter.add(Predicates.or( + SubType.WOLF.getPredicate(), + SubType.WEREWOLF.getPredicate() + )); + } + + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 2); + private static final Hint hint = new ValueHint("Wolves and Werewolves you control", new PermanentsOnBattlefieldCount(filter)); + + public TovolarDireOverlord(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{G}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WEREWOLF); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + this.secondSideCardClazz = mage.cards.t.TovolarTheMidnightScourge.class; + + // Whenever a Wolf or Werewolf you control deals combat damage to a player, draw a card. + this.addAbility(new DealsDamageToAPlayerAllTriggeredAbility( + new DrawCardSourceControllerEffect(1), filter, + false, SetTargetPointer.NONE, true + )); + + // At the beginning of your upkeep, if you control three or more Wolves and/or Werewolves, it becomes night. Then transform any number of Human Werewolves you control. + this.addAbility(new ConditionalInterveningIfTriggeredAbility( + new BeginningOfUpkeepTriggeredAbility( + new TovolarDireOverlordEffect(), TargetController.YOU, false + ), condition, "At the beginning of your upkeep, if you control three or more Wolves " + + "and/or Werewolves, it becomes night. Then transform any number of Human Werewolves you control." + )); + + // Daybound + this.addAbility(new TransformAbility()); + this.addAbility(new DayboundAbility()); + } + + private TovolarDireOverlord(final TovolarDireOverlord card) { + super(card); + } + + @Override + public TovolarDireOverlord copy() { + return new TovolarDireOverlord(this); + } +} + +class TovolarDireOverlordEffect extends OneShotEffect { + + private static final FilterPermanent filter = new FilterControlledPermanent("Human Werewolves you control"); + + static { + filter.add(SubType.HUMAN.getPredicate()); + filter.add(SubType.WEREWOLF.getPredicate()); + } + + TovolarDireOverlordEffect() { + super(Outcome.Benefit); + } + + private TovolarDireOverlordEffect(final TovolarDireOverlordEffect effect) { + super(effect); + } + + @Override + public TovolarDireOverlordEffect copy() { + return new TovolarDireOverlordEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + game.setDaytime(false); + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return true; + } + TargetPermanent target = new TargetPermanent(0, Integer.MAX_VALUE, filter, true); + player.choose(outcome, target, source.getControllerId(), game); + for (UUID permanentId : target.getTargets()) { + Permanent permanent = game.getPermanent(permanentId); + if (permanent != null) { + permanent.transform(source, game); + } + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/t/TovolarTheMidnightScourge.java b/Mage.Sets/src/mage/cards/t/TovolarTheMidnightScourge.java new file mode 100644 index 0000000000..667ce36043 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TovolarTheMidnightScourge.java @@ -0,0 +1,78 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.common.ManacostVariableValue; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.NightboundAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TovolarTheMidnightScourge extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledPermanent("a Wolf or Werewolf you control"); + + static { + filter.add(Predicates.or( + SubType.WOLF.getPredicate(), + SubType.WEREWOLF.getPredicate() + )); + } + + public TovolarTheMidnightScourge(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.WEREWOLF); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + this.color.setRed(true); + this.color.setGreen(true); + this.nightCard = true; + + // Whenever a Wolf or Werewolf you control deals combat damage to a player, draw a card. + this.addAbility(new DealsDamageToAPlayerAllTriggeredAbility( + new DrawCardSourceControllerEffect(1), filter, + false, SetTargetPointer.NONE, true + )); + + // {X}{R}{G}: Target Wolf or Werewolf you control gets +X/+0 and gains trample until end of turn. + Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect( + TrampleAbility.getInstance(), Duration.EndOfTurn + ).setText("Target Wolf or Werewolf you control gets +X/+0"), new ManaCostsImpl<>("{X}{R}{G}")); + ability.addEffect(new BoostTargetEffect( + ManacostVariableValue.REGULAR, StaticValue.get(0), Duration.EndOfTurn + ).setText("and gains trample until end of turn")); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + + // Nightbound + this.addAbility(new NightboundAbility()); + } + + private TovolarTheMidnightScourge(final TovolarTheMidnightScourge card) { + super(card); + } + + @Override + public TovolarTheMidnightScourge copy() { + return new TovolarTheMidnightScourge(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TovolarsHuntmaster.java b/Mage.Sets/src/mage/cards/t/TovolarsHuntmaster.java index 728ea25305..1c3af8d996 100644 --- a/Mage.Sets/src/mage/cards/t/TovolarsHuntmaster.java +++ b/Mage.Sets/src/mage/cards/t/TovolarsHuntmaster.java @@ -25,7 +25,6 @@ public final class TovolarsHuntmaster extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(6); this.toughness = new MageInt(6); - this.transformable = true; this.secondSideCardClazz = mage.cards.t.TovolarsPackleader.class; // Whenever Tovolar's Huntmaster enters the battlefield, create two 2/2 green Wolf creature tokens. diff --git a/Mage.Sets/src/mage/cards/t/TovolarsMagehunter.java b/Mage.Sets/src/mage/cards/t/TovolarsMagehunter.java index 046a6da18a..0fcba4dc88 100644 --- a/Mage.Sets/src/mage/cards/t/TovolarsMagehunter.java +++ b/Mage.Sets/src/mage/cards/t/TovolarsMagehunter.java @@ -30,7 +30,6 @@ public final class TovolarsMagehunter extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; // Whenever an opponent casts a spell, Tovolar's Magehunter deals 2 damage to that player. this.addAbility(new TovolarsMagehunterTriggeredAbility()); diff --git a/Mage.Sets/src/mage/cards/t/TovolarsPackleader.java b/Mage.Sets/src/mage/cards/t/TovolarsPackleader.java index ce1a3bff2a..83475a7ea2 100644 --- a/Mage.Sets/src/mage/cards/t/TovolarsPackleader.java +++ b/Mage.Sets/src/mage/cards/t/TovolarsPackleader.java @@ -45,7 +45,6 @@ public final class TovolarsPackleader extends CardImpl { this.power = new MageInt(7); this.toughness = new MageInt(7); this.color.setGreen(true); - this.transformable = true; this.nightCard = true; // Whenever Tovolar's Packleader enters the battlefield or attacks, create two 2/2 green Wolf creature tokens. diff --git a/Mage.Sets/src/mage/cards/t/TownGossipmonger.java b/Mage.Sets/src/mage/cards/t/TownGossipmonger.java index 672fac061f..1d032506c2 100644 --- a/Mage.Sets/src/mage/cards/t/TownGossipmonger.java +++ b/Mage.Sets/src/mage/cards/t/TownGossipmonger.java @@ -36,12 +36,11 @@ public final class TownGossipmonger extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.i.IncitedRabble.class; // {T}, Tap an untapped creature you control: Transform Town Gossipmonger. this.addAbility(new TransformAbility()); - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new TapSourceCost()); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new TapSourceCost()); ability.addCost(new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, true))); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/TreasureMap.java b/Mage.Sets/src/mage/cards/t/TreasureMap.java index 5a36dbcd0f..f641c5d6b1 100644 --- a/Mage.Sets/src/mage/cards/t/TreasureMap.java +++ b/Mage.Sets/src/mage/cards/t/TreasureMap.java @@ -29,7 +29,6 @@ public final class TreasureMap extends CardImpl { public TreasureMap(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); - this.transformable = true; this.secondSideCardClazz = TreasureCove.class; // {1}, {T}: Scry 1. Put a landmark counter on Treasure Map. Then if there are three or more landmark counters on it, remove those counters, transform Treasure Map, and create three colorless Treasure artifact tokens with "{T}, Sacrifice this artifact: Add one mana of any color." @@ -79,7 +78,7 @@ class TreasureMapEffect extends OneShotEffect { int counters = permanent.getCounters(game).getCount(CounterType.LANDMARK); if (counters > 2) { permanent.removeCounters("landmark", counters, source, game); - new TransformSourceEffect(true).apply(game, source); + new TransformSourceEffect().apply(game, source); new CreateTokenEffect(new TreasureToken(), 3).apply(game, source); } return true; diff --git a/Mage.Sets/src/mage/cards/u/UlrichOfTheKrallenhorde.java b/Mage.Sets/src/mage/cards/u/UlrichOfTheKrallenhorde.java index 276c819511..5d575350b4 100644 --- a/Mage.Sets/src/mage/cards/u/UlrichOfTheKrallenhorde.java +++ b/Mage.Sets/src/mage/cards/u/UlrichOfTheKrallenhorde.java @@ -29,7 +29,6 @@ public final class UlrichOfTheKrallenhorde extends CardImpl { this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = UlrichUncontestedAlpha.class; // Whenever this creature enters the battlefield or transforms into Ulrich of the Krallenhorde, target creature gets +4/+4 until end of turn. diff --git a/Mage.Sets/src/mage/cards/u/UlrichUncontestedAlpha.java b/Mage.Sets/src/mage/cards/u/UlrichUncontestedAlpha.java index 5da9d4f8c4..912555a267 100644 --- a/Mage.Sets/src/mage/cards/u/UlrichUncontestedAlpha.java +++ b/Mage.Sets/src/mage/cards/u/UlrichUncontestedAlpha.java @@ -33,7 +33,6 @@ public final class UlrichUncontestedAlpha extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; // Whenever this creature transforms into Ulrich, Uncontested Alpha, you may have it fight target non-Werewolf creature you don't control. this.addAbility(new UlrichUncontestedAlphaAbility()); diff --git a/Mage.Sets/src/mage/cards/u/UlvenwaldCaptive.java b/Mage.Sets/src/mage/cards/u/UlvenwaldCaptive.java index c6a47b7eef..bc813d5ac1 100644 --- a/Mage.Sets/src/mage/cards/u/UlvenwaldCaptive.java +++ b/Mage.Sets/src/mage/cards/u/UlvenwaldCaptive.java @@ -28,7 +28,6 @@ public final class UlvenwaldCaptive extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = UlvenwaldAbomination.class; // Defender @@ -39,7 +38,7 @@ public final class UlvenwaldCaptive extends CardImpl { // {5}{G}{G}: Transform Ulvenwald Captive. this.addAbility(new TransformAbility()); - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new ManaCostsImpl("{5}{G}{G}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new ManaCostsImpl("{5}{G}{G}"))); } private UlvenwaldCaptive(final UlvenwaldCaptive card) { diff --git a/Mage.Sets/src/mage/cards/u/UlvenwaldMystics.java b/Mage.Sets/src/mage/cards/u/UlvenwaldMystics.java index 3703f8792a..f4c838a6c3 100644 --- a/Mage.Sets/src/mage/cards/u/UlvenwaldMystics.java +++ b/Mage.Sets/src/mage/cards/u/UlvenwaldMystics.java @@ -21,7 +21,6 @@ public final class UlvenwaldMystics extends CardImpl { this.subtype.add(SubType.SHAMAN); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = UlvenwaldPrimordials.class; this.power = new MageInt(3); diff --git a/Mage.Sets/src/mage/cards/u/UlvenwaldOddity.java b/Mage.Sets/src/mage/cards/u/UlvenwaldOddity.java index b46afa7a5c..ae8c3820b7 100644 --- a/Mage.Sets/src/mage/cards/u/UlvenwaldOddity.java +++ b/Mage.Sets/src/mage/cards/u/UlvenwaldOddity.java @@ -25,7 +25,6 @@ public final class UlvenwaldOddity extends CardImpl { this.subtype.add(SubType.BEAST); this.power = new MageInt(4); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = mage.cards.u.UlvenwaldBehemoth.class; // Trample @@ -37,7 +36,7 @@ public final class UlvenwaldOddity extends CardImpl { // {5}{G}{G}: Transform Ulvenwald Oddity. this.addAbility(new TransformAbility()); this.addAbility(new SimpleActivatedAbility( - new TransformSourceEffect(true), new ManaCostsImpl<>("{5}{G}{G}") + new TransformSourceEffect(), new ManaCostsImpl<>("{5}{G}{G}") )); } diff --git a/Mage.Sets/src/mage/cards/u/UlvenwaldPrimordials.java b/Mage.Sets/src/mage/cards/u/UlvenwaldPrimordials.java index b76a5fe24a..d963de0208 100644 --- a/Mage.Sets/src/mage/cards/u/UlvenwaldPrimordials.java +++ b/Mage.Sets/src/mage/cards/u/UlvenwaldPrimordials.java @@ -24,7 +24,6 @@ public final class UlvenwaldPrimordials extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(5); this.toughness = new MageInt(5); diff --git a/Mage.Sets/src/mage/cards/u/UnhallowedCathar.java b/Mage.Sets/src/mage/cards/u/UnhallowedCathar.java index b765c55e0d..9f61fbec89 100644 --- a/Mage.Sets/src/mage/cards/u/UnhallowedCathar.java +++ b/Mage.Sets/src/mage/cards/u/UnhallowedCathar.java @@ -23,7 +23,6 @@ public final class UnhallowedCathar extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(2); this.toughness = new MageInt(1); diff --git a/Mage.Sets/src/mage/cards/u/UninvitedGeist.java b/Mage.Sets/src/mage/cards/u/UninvitedGeist.java index f83b9c384b..1a635c3c0d 100644 --- a/Mage.Sets/src/mage/cards/u/UninvitedGeist.java +++ b/Mage.Sets/src/mage/cards/u/UninvitedGeist.java @@ -24,7 +24,6 @@ public final class UninvitedGeist extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = UnimpededTrespasser.class; // Skulk (This creature can't be blocked by creatures with greater power.) @@ -32,7 +31,7 @@ public final class UninvitedGeist extends CardImpl { // When Uninvited Geist deals combat damage to a player, transform it. this.addAbility(new TransformAbility()); - this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new TransformSourceEffect(true), false)); + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new TransformSourceEffect(), false)); } diff --git a/Mage.Sets/src/mage/cards/u/UnnaturalMoonrise.java b/Mage.Sets/src/mage/cards/u/UnnaturalMoonrise.java new file mode 100644 index 0000000000..45824e42ec --- /dev/null +++ b/Mage.Sets/src/mage/cards/u/UnnaturalMoonrise.java @@ -0,0 +1,81 @@ +package mage.cards.u; + +import mage.abilities.Ability; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.hint.common.DayNightHint; +import mage.abilities.keyword.FlashbackAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.game.Game; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class UnnaturalMoonrise extends CardImpl { + + public UnnaturalMoonrise(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{R}{G}"); + + // It becomes night. Until end of turn, target creature gets +1/+0 and gains trample and has "Whenever this creature deals combat damage to a player, draw a card." + this.getSpellAbility().addEffect(new UnnaturalMoonriseEffect()); + this.getSpellAbility().addEffect(new BoostTargetEffect(1, 0) + .setText("Until end of turn, target creature gets +1/+0")); + this.getSpellAbility().addEffect(new GainAbilityTargetEffect( + TrampleAbility.getInstance(), Duration.EndOfTurn + ).setText("and gains trample")); + this.getSpellAbility().addEffect(new GainAbilityTargetEffect( + new DealsCombatDamageToAPlayerTriggeredAbility( + new DrawCardSourceControllerEffect(1), false + ).setTriggerPhrase("Whenever this creature deals combat damage to a player, "), Duration.EndOfTurn + ).setText("and \"Whenever this creature deals combat damage to a player, draw a card.\"")); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().addHint(DayNightHint.instance); + + // Flashback {2}{R}{G} + this.addAbility(new FlashbackAbility(this, new ManaCostsImpl<>("{2}{R}{G}"))); + } + + private UnnaturalMoonrise(final UnnaturalMoonrise card) { + super(card); + } + + @Override + public UnnaturalMoonrise copy() { + return new UnnaturalMoonrise(this); + } +} + +class UnnaturalMoonriseEffect extends OneShotEffect { + + UnnaturalMoonriseEffect() { + super(Outcome.Benefit); + staticText = "It becomes night."; + } + + private UnnaturalMoonriseEffect(final UnnaturalMoonriseEffect effect) { + super(effect); + } + + @Override + public UnnaturalMoonriseEffect copy() { + return new UnnaturalMoonriseEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + game.setDaytime(false); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/u/UntamedPup.java b/Mage.Sets/src/mage/cards/u/UntamedPup.java index 519b2ef335..4dbcd4007c 100644 --- a/Mage.Sets/src/mage/cards/u/UntamedPup.java +++ b/Mage.Sets/src/mage/cards/u/UntamedPup.java @@ -42,7 +42,6 @@ public final class UntamedPup extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); this.color.setGreen(true); - this.transformable = true; this.nightCard = true; // Trample @@ -50,7 +49,7 @@ public final class UntamedPup extends CardImpl { // Other Wolves and Werewolves you control have trample. this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect( - TrampleAbility.getInstance(), Duration.WhileOnBattlefield, filter + TrampleAbility.getInstance(), Duration.WhileOnBattlefield, filter, true ))); // {3}{G}: Put a +1/+1 counter on target creature. diff --git a/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java b/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java index 2c8eac60ff..225ad68753 100644 --- a/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java +++ b/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java @@ -37,7 +37,6 @@ public final class VancesBlastingCannons extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}"); this.addSuperType(SuperType.LEGENDARY); - this.transformable = true; this.secondSideCardClazz = mage.cards.s.SpitfireBastion.class; // At the beginning of your upkeep, exile the top card of your library. If it's a nonland card, you may cast that card this turn. @@ -132,7 +131,7 @@ class CastFromNonHandZoneTargetEffect extends AsThoughEffectImpl { class VancesBlastingCannonsFlipTrigger extends TriggeredAbilityImpl { public VancesBlastingCannonsFlipTrigger() { - super(Zone.BATTLEFIELD, new TransformSourceEffect(true), true); + super(Zone.BATTLEFIELD, new TransformSourceEffect(), true); } public VancesBlastingCannonsFlipTrigger(final VancesBlastingCannonsFlipTrigger ability) { diff --git a/Mage.Sets/src/mage/cards/v/VengefulStrangler.java b/Mage.Sets/src/mage/cards/v/VengefulStrangler.java index f1ca4ac043..1b1de17929 100644 --- a/Mage.Sets/src/mage/cards/v/VengefulStrangler.java +++ b/Mage.Sets/src/mage/cards/v/VengefulStrangler.java @@ -38,7 +38,6 @@ public final class VengefulStrangler extends CardImpl { this.subtype.add(SubType.ROGUE); this.power = new MageInt(2); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.s.StranglingGrasp.class; // Vengeful Strangler can't block. diff --git a/Mage.Sets/src/mage/cards/v/VildinPackAlpha.java b/Mage.Sets/src/mage/cards/v/VildinPackAlpha.java index a567911d8a..37bbb7367b 100644 --- a/Mage.Sets/src/mage/cards/v/VildinPackAlpha.java +++ b/Mage.Sets/src/mage/cards/v/VildinPackAlpha.java @@ -8,6 +8,7 @@ import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; +import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; @@ -20,6 +21,8 @@ import java.util.UUID; */ public final class VildinPackAlpha extends CardImpl { + private static final FilterPermanent filter = new FilterCreaturePermanent(SubType.WEREWOLF, "a Werewolf"); + public VildinPackAlpha(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); this.subtype.add(SubType.WEREWOLF); @@ -27,11 +30,13 @@ public final class VildinPackAlpha extends CardImpl { this.toughness = new MageInt(3); this.color.setRed(true); - this.transformable = true; this.nightCard = true; // Whenever a Werewolf enters the battlefield under your control, you may transform it. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new VildinPackAlphaEffect(), new FilterCreaturePermanent(SubType.WEREWOLF, "a Werewolf"), true, SetTargetPointer.PERMANENT, null)); + this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + Zone.BATTLEFIELD, new VildinPackAlphaEffect(), filter, + true, SetTargetPointer.PERMANENT, null + )); // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Vildin-Pack Alpha. this.addAbility(new WerewolfBackTriggeredAbility()); @@ -66,13 +71,13 @@ class VildinPackAlphaEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - Permanent werewolf = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (werewolf != null && werewolf.isTransformable()) { - werewolf.transform(game); - } - return true; + if (controller == null) { + return false; } - return false; + Permanent werewolf = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (werewolf != null) { + werewolf.transform(source, game); + } + return true; } } diff --git a/Mage.Sets/src/mage/cards/v/VildinPackOutcast.java b/Mage.Sets/src/mage/cards/v/VildinPackOutcast.java index 67e4cdb437..60678b9ff2 100644 --- a/Mage.Sets/src/mage/cards/v/VildinPackOutcast.java +++ b/Mage.Sets/src/mage/cards/v/VildinPackOutcast.java @@ -29,7 +29,6 @@ public final class VildinPackOutcast extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = mage.cards.d.DronepackKindred.class; // Trample @@ -40,7 +39,7 @@ public final class VildinPackOutcast extends CardImpl { // {5}{R}{R}: Transform Vildin-Pack Outcast. this.addAbility(new TransformAbility()); - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new ManaCostsImpl("{5}{R}{R}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new ManaCostsImpl("{5}{R}{R}"))); } private VildinPackOutcast(final VildinPackOutcast card) { diff --git a/Mage.Sets/src/mage/cards/v/VillageIronsmith.java b/Mage.Sets/src/mage/cards/v/VillageIronsmith.java index 7bbf0b9366..408f637c9d 100644 --- a/Mage.Sets/src/mage/cards/v/VillageIronsmith.java +++ b/Mage.Sets/src/mage/cards/v/VillageIronsmith.java @@ -21,7 +21,6 @@ public final class VillageIronsmith extends CardImpl { this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = mage.cards.i.Ironfang.class; this.power = new MageInt(1); diff --git a/Mage.Sets/src/mage/cards/v/VillageMessenger.java b/Mage.Sets/src/mage/cards/v/VillageMessenger.java index 72d6bc1031..c1f2f7b5aa 100644 --- a/Mage.Sets/src/mage/cards/v/VillageMessenger.java +++ b/Mage.Sets/src/mage/cards/v/VillageMessenger.java @@ -23,7 +23,6 @@ public final class VillageMessenger extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.m.MoonriseIntruder.class; // Haste diff --git a/Mage.Sets/src/mage/cards/v/VillageReavers.java b/Mage.Sets/src/mage/cards/v/VillageReavers.java index efa4fe5e3f..ccdf291873 100644 --- a/Mage.Sets/src/mage/cards/v/VillageReavers.java +++ b/Mage.Sets/src/mage/cards/v/VillageReavers.java @@ -38,7 +38,6 @@ public final class VillageReavers extends CardImpl { this.color.setRed(true); this.nightCard = true; - this.transformable = true; this.power = new MageInt(5); this.toughness = new MageInt(4); diff --git a/Mage.Sets/src/mage/cards/v/VillageWatch.java b/Mage.Sets/src/mage/cards/v/VillageWatch.java index c620c73046..67a7484622 100644 --- a/Mage.Sets/src/mage/cards/v/VillageWatch.java +++ b/Mage.Sets/src/mage/cards/v/VillageWatch.java @@ -24,7 +24,6 @@ public final class VillageWatch extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.v.VillageReavers.class; // Haste diff --git a/Mage.Sets/src/mage/cards/v/VillagersOfEstwald.java b/Mage.Sets/src/mage/cards/v/VillagersOfEstwald.java index ed3cdb7f6a..ce821011a2 100644 --- a/Mage.Sets/src/mage/cards/v/VillagersOfEstwald.java +++ b/Mage.Sets/src/mage/cards/v/VillagersOfEstwald.java @@ -20,7 +20,6 @@ public final class VillagersOfEstwald extends CardImpl { this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = mage.cards.h.HowlpackOfEstwald.class; this.power = new MageInt(2); diff --git a/Mage.Sets/src/mage/cards/v/VodalianWarMachine.java b/Mage.Sets/src/mage/cards/v/VodalianWarMachine.java index f178d60313..ff4b32081b 100644 --- a/Mage.Sets/src/mage/cards/v/VodalianWarMachine.java +++ b/Mage.Sets/src/mage/cards/v/VodalianWarMachine.java @@ -1,11 +1,6 @@ package mage.cards.v; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.UUID; import mage.MageInt; import mage.MageObjectReference; import mage.abilities.Ability; @@ -19,25 +14,20 @@ import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.keyword.DefenderAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.SubType; -import mage.constants.WatcherScope; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; import mage.game.stack.StackAbility; import mage.target.common.TargetControlledCreaturePermanent; import mage.watchers.Watcher; +import java.util.*; + /** - * * @author L_J */ public final class VodalianWarMachine extends CardImpl { @@ -66,7 +56,7 @@ public final class VodalianWarMachine extends CardImpl { this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(2, 1, Duration.EndOfTurn), new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, true)))); // When Vodalian War Machine dies, destroy all Merfolk tapped this turn to pay for its abilities. - this.addAbility(new VodalianWarMachineTriggeredAbility(), new VodalianWarMachineWatcher()); + this.addAbility(new DiesSourceTriggeredAbility(new VodalianWarMachineEffect()), new VodalianWarMachineWatcher()); } private VodalianWarMachine(final VodalianWarMachine card) { @@ -79,41 +69,6 @@ public final class VodalianWarMachine extends CardImpl { } } -class VodalianWarMachineTriggeredAbility extends DiesSourceTriggeredAbility { - - public VodalianWarMachineTriggeredAbility() { - super(new VodalianWarMachineEffect(), false); - } - - public VodalianWarMachineTriggeredAbility(VodalianWarMachineTriggeredAbility ability) { - super(ability); - } - - @Override - public VodalianWarMachineTriggeredAbility copy() { - return new VodalianWarMachineTriggeredAbility(this); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - Permanent before = ((ZoneChangeEvent) event).getTarget(); - if (before == null) { - return false; - } - if (super.checkTrigger(event, game)) { - ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - if (zEvent.getTarget().isTransformable()) { - if (!zEvent.getTarget().getAbilities().contains(this)) { - return false; - } - } - return true; - } - return false; - } - -} - class VodalianWarMachineEffect extends OneShotEffect { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Merfolk tapped this turn to pay for its abilities"); diff --git a/Mage.Sets/src/mage/cards/v/VoldarenPariah.java b/Mage.Sets/src/mage/cards/v/VoldarenPariah.java index 09dbf6d09a..d5ead03280 100644 --- a/Mage.Sets/src/mage/cards/v/VoldarenPariah.java +++ b/Mage.Sets/src/mage/cards/v/VoldarenPariah.java @@ -38,7 +38,6 @@ public final class VoldarenPariah extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.a.AbolisherOfBloodlines.class; // Flying @@ -46,7 +45,7 @@ public final class VoldarenPariah extends CardImpl { // Sacrifice three other creatures: Transform Voldaren Pariah. this.addAbility(new TransformAbility()); - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new SacrificeTargetCost(new TargetControlledPermanent(3, 3, filter, false)))); // Madness {B}{B}{B} diff --git a/Mage.Sets/src/mage/cards/w/Waildrifter.java b/Mage.Sets/src/mage/cards/w/Waildrifter.java index 14dde19604..dec610a203 100644 --- a/Mage.Sets/src/mage/cards/w/Waildrifter.java +++ b/Mage.Sets/src/mage/cards/w/Waildrifter.java @@ -24,7 +24,6 @@ public final class Waildrifter extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); this.color.setBlue(true); - this.transformable = true; this.nightCard = true; // Flying diff --git a/Mage.Sets/src/mage/cards/w/WaxingMoon.java b/Mage.Sets/src/mage/cards/w/WaxingMoon.java index 2d6a8a3e8f..d3b293fb03 100644 --- a/Mage.Sets/src/mage/cards/w/WaxingMoon.java +++ b/Mage.Sets/src/mage/cards/w/WaxingMoon.java @@ -1,45 +1,43 @@ - package mage.cards.w; -import java.util.UUID; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.TransformTargetEffect; -import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; +import mage.constants.Outcome; import mage.constants.SubType; -import mage.constants.TargetController; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.common.FilterCreaturePermanent; -import mage.target.common.TargetCreaturePermanent; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledPermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class WaxingMoon extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Werewolf you control"); - - static { - filter.add(SubType.WEREWOLF.getPredicate()); - filter.add(TargetController.YOU.getControllerPredicate()); - } + private static final FilterPermanent filter = new FilterControlledPermanent(SubType.WEREWOLF); public WaxingMoon(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}"); // Transform up to one target Werewolf you control. - Effect effect = new TransformTargetEffect(false); - effect.setText("Transform up to one target Werewolf you control"); - this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 1, filter, false)); + this.getSpellAbility().addEffect(new WaxingMoonEffect()); + this.getSpellAbility().addTarget(new TargetPermanent(0, 1, filter)); // Creatures you control gain trample until end of turn. - this.getSpellAbility().addEffect(new GainAbilityAllEffect(TrampleAbility.getInstance(), Duration.EndOfTurn, new FilterControlledCreaturePermanent(), "Creatures you control gain trample until end of turn")); + this.getSpellAbility().addEffect(new GainAbilityControlledEffect( + TrampleAbility.getInstance(), Duration.EndOfTurn, + StaticFilters.FILTER_PERMANENT_CREATURES + )); } private WaxingMoon(final WaxingMoon card) { @@ -51,3 +49,26 @@ public final class WaxingMoon extends CardImpl { return new WaxingMoon(this); } } + +class WaxingMoonEffect extends OneShotEffect { + + WaxingMoonEffect() { + super(Outcome.Benefit); + staticText = "transform up to one target Werewolf you control"; + } + + private WaxingMoonEffect(final WaxingMoonEffect effect) { + super(effect); + } + + @Override + public WaxingMoonEffect copy() { + return new WaxingMoonEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getFirstTarget()); + return permanent != null && permanent.transform(source, game); + } +} diff --git a/Mage.Sets/src/mage/cards/w/WearyPrisoner.java b/Mage.Sets/src/mage/cards/w/WearyPrisoner.java index ccfdb51a9a..4feabe4041 100644 --- a/Mage.Sets/src/mage/cards/w/WearyPrisoner.java +++ b/Mage.Sets/src/mage/cards/w/WearyPrisoner.java @@ -23,6 +23,7 @@ public final class WearyPrisoner extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(2); this.toughness = new MageInt(6); + this.secondSideCardClazz = mage.cards.w.WrathfulJailbreaker.class; // Defender diff --git a/Mage.Sets/src/mage/cards/w/WeddingAnnouncement.java b/Mage.Sets/src/mage/cards/w/WeddingAnnouncement.java index 1c256f09d3..a690a4dc8b 100644 --- a/Mage.Sets/src/mage/cards/w/WeddingAnnouncement.java +++ b/Mage.Sets/src/mage/cards/w/WeddingAnnouncement.java @@ -29,7 +29,6 @@ public final class WeddingAnnouncement extends CardImpl { public WeddingAnnouncement(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}"); - this.transformable = true; this.secondSideCardClazz = mage.cards.w.WeddingFestivity.class; // At the beginning of your end step, put an invitation counter on Wedding Announcement. @@ -45,7 +44,7 @@ public final class WeddingAnnouncement extends CardImpl { "If you attacked with two or more creatures this turn, draw card. Otherwise, create a 1/1 white Human creature token" )); ability.addEffect(new ConditionalOneShotEffect( - new TransformSourceEffect(true, true), + new TransformSourceEffect(), new SourceHasCounterCondition(CounterType.INVITATION, 3), "Then if {this} has three or more invitation counters on it, transform it" )); diff --git a/Mage.Sets/src/mage/cards/w/WerewolfOfAncientHunger.java b/Mage.Sets/src/mage/cards/w/WerewolfOfAncientHunger.java index 511f969c93..9a834b909b 100644 --- a/Mage.Sets/src/mage/cards/w/WerewolfOfAncientHunger.java +++ b/Mage.Sets/src/mage/cards/w/WerewolfOfAncientHunger.java @@ -31,7 +31,6 @@ public final class WerewolfOfAncientHunger extends CardImpl { this.color.setGreen(true); this.nightCard = true; - this.transformable = true; // Vigilance this.addAbility(VigilanceAbility.getInstance()); diff --git a/Mage.Sets/src/mage/cards/w/WerewolfRansacker.java b/Mage.Sets/src/mage/cards/w/WerewolfRansacker.java index bc1614ded9..c29592c747 100644 --- a/Mage.Sets/src/mage/cards/w/WerewolfRansacker.java +++ b/Mage.Sets/src/mage/cards/w/WerewolfRansacker.java @@ -31,7 +31,6 @@ public final class WerewolfRansacker extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(5); this.toughness = new MageInt(4); diff --git a/Mage.Sets/src/mage/cards/w/WestvaleAbbey.java b/Mage.Sets/src/mage/cards/w/WestvaleAbbey.java index d3b45ed59f..9e52eaf3d8 100644 --- a/Mage.Sets/src/mage/cards/w/WestvaleAbbey.java +++ b/Mage.Sets/src/mage/cards/w/WestvaleAbbey.java @@ -30,7 +30,6 @@ public final class WestvaleAbbey extends CardImpl { public WestvaleAbbey(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); - this.transformable = true; this.secondSideCardClazz = mage.cards.o.OrmendahlProfanePrince.class; // {T}: Add {C}. @@ -44,7 +43,7 @@ public final class WestvaleAbbey extends CardImpl { // {5}, {T}, Sacrifice five creatures: Transform Westvale Abbey and untap it. this.addAbility(new TransformAbility()); - ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new GenericManaCost(5)); + ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new GenericManaCost(5)); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(5, 5, new FilterControlledCreaturePermanent("creatures"), true))); ability.addEffect(new UntapSourceEffect()); diff --git a/Mage.Sets/src/mage/cards/w/WildbloodPack.java b/Mage.Sets/src/mage/cards/w/WildbloodPack.java index 07981c1cdd..6dd0d6f908 100644 --- a/Mage.Sets/src/mage/cards/w/WildbloodPack.java +++ b/Mage.Sets/src/mage/cards/w/WildbloodPack.java @@ -26,7 +26,6 @@ public final class WildbloodPack extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(5); this.toughness = new MageInt(5); diff --git a/Mage.Sets/src/mage/cards/w/WingShredder.java b/Mage.Sets/src/mage/cards/w/WingShredder.java index e1946dd6e5..daf016f1dd 100644 --- a/Mage.Sets/src/mage/cards/w/WingShredder.java +++ b/Mage.Sets/src/mage/cards/w/WingShredder.java @@ -18,13 +18,11 @@ public final class WingShredder extends CardImpl { public WingShredder(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); - this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(3); this.toughness = new MageInt(5); this.color.setGreen(true); this.nightCard = true; - this.transformable = true; // Reach this.addAbility(ReachAbility.getInstance()); diff --git a/Mage.Sets/src/mage/cards/w/WithengarUnbound.java b/Mage.Sets/src/mage/cards/w/WithengarUnbound.java index e06bd24c18..523c7e10c9 100644 --- a/Mage.Sets/src/mage/cards/w/WithengarUnbound.java +++ b/Mage.Sets/src/mage/cards/w/WithengarUnbound.java @@ -17,7 +17,6 @@ import mage.constants.Zone; import mage.counters.CounterType; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; /** * @@ -33,7 +32,6 @@ public final class WithengarUnbound extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(13); this.toughness = new MageInt(13); diff --git a/Mage.Sets/src/mage/cards/w/WolfbittenCaptive.java b/Mage.Sets/src/mage/cards/w/WolfbittenCaptive.java index 692ca2c899..947f1e86a9 100644 --- a/Mage.Sets/src/mage/cards/w/WolfbittenCaptive.java +++ b/Mage.Sets/src/mage/cards/w/WolfbittenCaptive.java @@ -28,7 +28,6 @@ public final class WolfbittenCaptive extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.k.KrallenhordeKiller.class; // {1}{G}: Wolfbitten Captive gets +2/+2 until end of turn. Activate this ability only once each turn. diff --git a/Mage.Sets/src/mage/cards/w/WrathfulJailbreaker.java b/Mage.Sets/src/mage/cards/w/WrathfulJailbreaker.java index b3befd7c8c..3e0bf2c9f1 100644 --- a/Mage.Sets/src/mage/cards/w/WrathfulJailbreaker.java +++ b/Mage.Sets/src/mage/cards/w/WrathfulJailbreaker.java @@ -22,6 +22,7 @@ public final class WrathfulJailbreaker extends CardImpl { this.power = new MageInt(6); this.toughness = new MageInt(6); this.color.setRed(true); + this.nightCard = true; // Wrathful Jailbreaker attacks each combat if able. diff --git a/Mage.Sets/src/mage/sets/InnistradMidnightHunt.java b/Mage.Sets/src/mage/sets/InnistradMidnightHunt.java index a4201ba0e3..bbc78f743d 100644 --- a/Mage.Sets/src/mage/sets/InnistradMidnightHunt.java +++ b/Mage.Sets/src/mage/sets/InnistradMidnightHunt.java @@ -17,7 +17,7 @@ import java.util.List; */ public final class InnistradMidnightHunt extends ExpansionSet { - private static final List unfinished = Arrays.asList("Arlinn, the Pack's Hope", "Arlinn, the Moon's Fury", "Baithook Angler", "Hook-Haunt Drifter", "Baneblade Scoundrel", "Baneclaw Marauder", "Beloved Beggar", "Generous Soul", "Bird Admirer", "Wing Shredder", "Brimstone Vandal", "Brutal Cathar", "Moonrage Brute", "Burly Breaker", "Dire-Strain Demolisher", "Celestus Sanctifier", "Chaplain of Alms", "Chapel Shieldgeist", "Component Collector", "Covert Cutpurse", "Covetous Geist", "Covetous Castaway", "Ghostly Castigator", "Curse of Leeches", "Leeching Lurker", "Dennick, Pious Apprentice", "Dennick, Pious Apparition", "Devoted Grafkeeper", "Departed Soulkeeper", "Fangblade Brigand", "Fangblade Eviscerator", "Firmament Sage", "Galedrifter", "Waildrifter", "Gavony Dawnguard", "Graveyard Trespasser", "Graveyard Glutton", "Harvesttide Infiltrator", "Harvesttide Assailant", "Hound Tamer", "Untamed Pup", "Kessig Naturalist", "Lord of the Ulvenwald", "Lunarch Veteran", "Luminous Phantom", "Malevolent Hermit", "Benevolent Geist", "Mourning Patrol", "Morning Apparition", "Obsessive Astronomer", "Outland Liberator", "Frenzied Trapbreaker", "Overwhelmed Archivist", "Archive Haunt", "Phantom Carriage", "Reckless Stormseeker", "Storm-Charged Slasher", "Shady Traveler", "Stalking Predator", "Shipwreck Sifters", "Spellrune Painter", "Spellrune Howler", "Sunrise Cavalier", "Sunstreak Phoenix", "Suspicious Stowaway", "Seafaring Werewolf", "Tavern Ruffian", "Tavern Smasher", "The Celestus", "Thraben Exorcism", "Tireless Hauler", "Dire-Strain Brawler", "Tovolar, Dire Overlord", "Tovolar, the Midnight Scourge", "Tovolar's Huntmaster", "Tovolar's Packleader", "Unblinking Observer", "Vadrik, Astral Archmage", "Village Watch", "Village Reavers"); + private static final List unfinished = Arrays.asList("Baithook Angler", "Hook-Haunt Drifter", "Beloved Beggar", "Generous Soul", "Chaplain of Alms", "Chapel Shieldgeist", "Covert Cutpurse", "Covetous Geist", "Covetous Castaway", "Ghostly Castigator", "Dennick, Pious Apprentice", "Dennick, Pious Apparition", "Devoted Grafkeeper", "Departed Soulkeeper", "Galedrifter", "Waildrifter", "Lunarch Veteran", "Luminous Phantom", "Malevolent Hermit", "Benevolent Geist", "Mourning Patrol", "Morning Apparition", "Overwhelmed Archivist", "Archive Haunt", "Phantom Carriage", "Shipwreck Sifters", "Thraben Exorcism", "Unblinking Observer"); private static final InnistradMidnightHunt instance = new InnistradMidnightHunt(); public static InnistradMidnightHunt getInstance() { @@ -40,6 +40,7 @@ public final class InnistradMidnightHunt extends ExpansionSet { cards.add(new SetCardInfo("Adeline, Resplendent Cathar", 1, Rarity.RARE, mage.cards.a.AdelineResplendentCathar.class)); cards.add(new SetCardInfo("Ambitious Farmhand", 2, Rarity.UNCOMMON, mage.cards.a.AmbitiousFarmhand.class)); cards.add(new SetCardInfo("Angelfire Ignition", 209, Rarity.RARE, mage.cards.a.AngelfireIgnition.class)); + cards.add(new SetCardInfo("Angelic Enforcer", 17, Rarity.MYTHIC, mage.cards.a.AngelicEnforcer.class)); cards.add(new SetCardInfo("Arcane Infusion", 210, Rarity.UNCOMMON, mage.cards.a.ArcaneInfusion.class)); cards.add(new SetCardInfo("Archive Haunt", 68, Rarity.UNCOMMON, mage.cards.a.ArchiveHaunt.class)); cards.add(new SetCardInfo("Ardent Elementalist", 128, Rarity.COMMON, mage.cards.a.ArdentElementalist.class)); @@ -50,6 +51,8 @@ public final class InnistradMidnightHunt extends ExpansionSet { cards.add(new SetCardInfo("Augur of Autumn", 168, Rarity.RARE, mage.cards.a.AugurOfAutumn.class)); cards.add(new SetCardInfo("Awoken Demon", 100, Rarity.COMMON, mage.cards.a.AwokenDemon.class)); cards.add(new SetCardInfo("Baithook Angler", 42, Rarity.COMMON, mage.cards.b.BaithookAngler.class)); + cards.add(new SetCardInfo("Baneblade Scoundrel", 85, Rarity.UNCOMMON, mage.cards.b.BanebladeScoundrel.class)); + cards.add(new SetCardInfo("Baneclaw Marauder", 85, Rarity.UNCOMMON, mage.cards.b.BaneclawMarauder.class)); cards.add(new SetCardInfo("Bat Whisperer", 86, Rarity.COMMON, mage.cards.b.BatWhisperer.class)); cards.add(new SetCardInfo("Benevolent Geist", 61, Rarity.RARE, mage.cards.b.BenevolentGeist.class)); cards.add(new SetCardInfo("Bereaved Survivor", 4, Rarity.UNCOMMON, mage.cards.b.BereavedSurvivor.class)); @@ -97,6 +100,7 @@ public final class InnistradMidnightHunt extends ExpansionSet { cards.add(new SetCardInfo("Creeping Inn", 264, Rarity.MYTHIC, mage.cards.c.CreepingInn.class)); cards.add(new SetCardInfo("Croaking Counterpart", 215, Rarity.RARE, mage.cards.c.CroakingCounterpart.class)); cards.add(new SetCardInfo("Crossroads Candleguide", 253, Rarity.COMMON, mage.cards.c.CrossroadsCandleguide.class)); + cards.add(new SetCardInfo("Curse of Leeches", 94, Rarity.RARE, mage.cards.c.CurseOfLeeches.class)); cards.add(new SetCardInfo("Curse of Shaken Faith", 134, Rarity.RARE, mage.cards.c.CurseOfShakenFaith.class)); cards.add(new SetCardInfo("Curse of Silence", 15, Rarity.RARE, mage.cards.c.CurseOfSilence.class)); cards.add(new SetCardInfo("Curse of Surveillance", 46, Rarity.RARE, mage.cards.c.CurseOfSurveillance.class)); @@ -132,6 +136,7 @@ public final class InnistradMidnightHunt extends ExpansionSet { cards.add(new SetCardInfo("Ecstatic Awakener", 100, Rarity.COMMON, mage.cards.e.EcstaticAwakener.class)); cards.add(new SetCardInfo("Electric Revelation", 135, Rarity.COMMON, mage.cards.e.ElectricRevelation.class)); cards.add(new SetCardInfo("Embodiment of Flame", 141, Rarity.UNCOMMON, mage.cards.e.EmbodimentOfFlame.class)); + cards.add(new SetCardInfo("Enduring Angel", 17, Rarity.MYTHIC, mage.cards.e.EnduringAngel.class)); cards.add(new SetCardInfo("Evolving Wilds", 261, Rarity.COMMON, mage.cards.e.EvolvingWilds.class)); cards.add(new SetCardInfo("Fading Hope", 51, Rarity.UNCOMMON, mage.cards.f.FadingHope.class)); cards.add(new SetCardInfo("Faithful Mending", 221, Rarity.UNCOMMON, mage.cards.f.FaithfulMending.class)); @@ -196,6 +201,7 @@ public final class InnistradMidnightHunt extends ExpansionSet { cards.add(new SetCardInfo("Kessig Naturalist", 231, Rarity.UNCOMMON, mage.cards.k.KessigNaturalist.class)); cards.add(new SetCardInfo("Lambholt Harrier", 145, Rarity.COMMON, mage.cards.l.LambholtHarrier.class)); cards.add(new SetCardInfo("Larder Zombie", 58, Rarity.COMMON, mage.cards.l.LarderZombie.class)); + cards.add(new SetCardInfo("Leeching Lurker", 94, Rarity.RARE, mage.cards.l.LeechingLurker.class)); cards.add(new SetCardInfo("Lier, Disciple of the Drowned", 59, Rarity.MYTHIC, mage.cards.l.LierDiscipleOfTheDrowned.class)); cards.add(new SetCardInfo("Liesa, Forgotten Archangel", 232, Rarity.RARE, mage.cards.l.LiesaForgottenArchangel.class)); cards.add(new SetCardInfo("Light Up the Night", 146, Rarity.RARE, mage.cards.l.LightUpTheNight.class)); @@ -203,6 +209,7 @@ public final class InnistradMidnightHunt extends ExpansionSet { cards.add(new SetCardInfo("Lord of the Forsaken", 110, Rarity.MYTHIC, mage.cards.l.LordOfTheForsaken.class)); cards.add(new SetCardInfo("Lord of the Ulvenwald", 231, Rarity.UNCOMMON, mage.cards.l.LordOfTheUlvenwald.class)); cards.add(new SetCardInfo("Loyal Gryff", 26, Rarity.UNCOMMON, mage.cards.l.LoyalGryff.class)); + cards.add(new SetCardInfo("Ludevic, Necrogenius", 233, Rarity.RARE, mage.cards.l.LudevicNecrogenius.class)); cards.add(new SetCardInfo("Luminous Phantom", 27, Rarity.COMMON, mage.cards.l.LuminousPhantom.class)); cards.add(new SetCardInfo("Lunar Frenzy", 147, Rarity.UNCOMMON, mage.cards.l.LunarFrenzy.class)); cards.add(new SetCardInfo("Lunarch Veteran", 27, Rarity.COMMON, mage.cards.l.LunarchVeteran.class)); @@ -230,6 +237,7 @@ public final class InnistradMidnightHunt extends ExpansionSet { cards.add(new SetCardInfo("Novice Occultist", 117, Rarity.COMMON, mage.cards.n.NoviceOccultist.class)); cards.add(new SetCardInfo("Obsessive Astronomer", 152, Rarity.UNCOMMON, mage.cards.o.ObsessiveAstronomer.class)); cards.add(new SetCardInfo("Odric's Outrider", 29, Rarity.UNCOMMON, mage.cards.o.OdricsOutrider.class)); + cards.add(new SetCardInfo("Olag, Ludevic's Hubris", 233, Rarity.RARE, mage.cards.o.OlagLudevicsHubris.class)); cards.add(new SetCardInfo("Old Stickfingers", 234, Rarity.RARE, mage.cards.o.OldStickfingers.class)); cards.add(new SetCardInfo("Olivia's Midnight Ambush", 118, Rarity.COMMON, mage.cards.o.OliviasMidnightAmbush.class)); cards.add(new SetCardInfo("Ominous Roost", 65, Rarity.UNCOMMON, mage.cards.o.OminousRoost.class)); @@ -314,6 +322,7 @@ public final class InnistradMidnightHunt extends ExpansionSet { cards.add(new SetCardInfo("Tavern Ruffian", 163, Rarity.COMMON, mage.cards.t.TavernRuffian.class)); cards.add(new SetCardInfo("Tavern Smasher", 163, Rarity.COMMON, mage.cards.t.TavernSmasher.class)); cards.add(new SetCardInfo("Teferi, Who Slows the Sunset", 245, Rarity.MYTHIC, mage.cards.t.TeferiWhoSlowsTheSunset.class)); + cards.add(new SetCardInfo("The Celestus", 252, Rarity.RARE, mage.cards.t.TheCelestus.class)); cards.add(new SetCardInfo("The Meathook Massacre", 112, Rarity.MYTHIC, mage.cards.t.TheMeathookMassacre.class)); cards.add(new SetCardInfo("Thermo-Alchemist", 164, Rarity.UNCOMMON, mage.cards.t.ThermoAlchemist.class)); cards.add(new SetCardInfo("Thraben Exorcism", 39, Rarity.COMMON, mage.cards.t.ThrabenExorcism.class)); @@ -321,10 +330,13 @@ public final class InnistradMidnightHunt extends ExpansionSet { cards.add(new SetCardInfo("Tireless Hauler", 203, Rarity.COMMON, mage.cards.t.TirelessHauler.class)); cards.add(new SetCardInfo("Tovolar's Huntmaster", 204, Rarity.RARE, mage.cards.t.TovolarsHuntmaster.class)); cards.add(new SetCardInfo("Tovolar's Packleader", 204, Rarity.RARE, mage.cards.t.TovolarsPackleader.class)); + cards.add(new SetCardInfo("Tovolar, Dire Overlord", 246, Rarity.RARE, mage.cards.t.TovolarDireOverlord.class)); + cards.add(new SetCardInfo("Tovolar, the Midnight Scourge", 246, Rarity.RARE, mage.cards.t.TovolarTheMidnightScourge.class)); cards.add(new SetCardInfo("Triskaidekaphile", 81, Rarity.RARE, mage.cards.t.Triskaidekaphile.class)); cards.add(new SetCardInfo("Turn the Earth", 205, Rarity.UNCOMMON, mage.cards.t.TurnTheEarth.class)); cards.add(new SetCardInfo("Unblinking Observer", 82, Rarity.COMMON, mage.cards.u.UnblinkingObserver.class)); cards.add(new SetCardInfo("Unnatural Growth", 206, Rarity.RARE, mage.cards.u.UnnaturalGrowth.class)); + cards.add(new SetCardInfo("Unnatural Moonrise", 247, Rarity.UNCOMMON, mage.cards.u.UnnaturalMoonrise.class)); cards.add(new SetCardInfo("Unruly Mob", 40, Rarity.COMMON, mage.cards.u.UnrulyMob.class)); cards.add(new SetCardInfo("Untamed Pup", 187, Rarity.UNCOMMON, mage.cards.u.UntamedPup.class)); cards.add(new SetCardInfo("Vadrik, Astral Archmage", 248, Rarity.RARE, mage.cards.v.VadrikAstralArchmage.class)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DayNightTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DayNightTest.java new file mode 100644 index 0000000000..6525e7c000 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DayNightTest.java @@ -0,0 +1,349 @@ +package org.mage.test.cards.abilities.keywords; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import mage.game.permanent.Permanent; +import org.junit.Assert; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author TheElk801 + */ +public class DayNightTest extends CardTestPlayerBase { + + private static final String ruffian = "Tavern Ruffian"; + private static final String smasher = "Tavern Smasher"; + private static final String moonmist = "Moonmist"; + private static final String outcasts = "Grizzled Outcasts"; + private static final String wantons = "Krallenhorde Wantons"; + private static final String immerwolf = "Immerwolf"; + private static final String bolt = "Lightning Bolt"; + private static final String curse = "Curse of Leeches"; + private static final String lurker = "Leeching Lurker"; + private static final String vandal = "Brimstone Vandal"; + + private void assertDayNight(boolean daytime) { + Assert.assertTrue("It should not be neither day nor night", currentGame.hasDayNight()); + Assert.assertTrue("It should be " + (daytime ? "day" : "night"), currentGame.checkDayNight(daytime)); + Assert.assertFalse("It should not be " + (daytime ? "night" : "day"), currentGame.checkDayNight(!daytime)); + } + + private void assertRuffianSmasher(boolean daytime) { + assertDayNight(daytime); + if (daytime) { + assertPowerToughness(playerA, ruffian, 2, 5); + assertPermanentCount(playerA, smasher, 0); + } else { + assertPermanentCount(playerA, ruffian, 0); + assertPowerToughness(playerA, smasher, 6, 5); + } + } + + private void setDayNight(int turn, PhaseStep phaseStep, boolean daytime) { + runCode("set game to " + (daytime ? "day" : "night"), turn, phaseStep, playerA, (i, p, game) -> game.setDaytime(daytime)); + } + + @Test + public void testRegularDay() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); + addCard(Zone.HAND, playerA, ruffian); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, ruffian); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertRuffianSmasher(true); + } + + @Test + public void testNightbound() { + currentGame.setDaytime(false); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); + addCard(Zone.HAND, playerA, ruffian); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, ruffian); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertRuffianSmasher(false); + } + + @Test + public void testDayToNightTransform() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); + addCard(Zone.HAND, playerA, ruffian); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, ruffian); + setDayNight(1, PhaseStep.POSTCOMBAT_MAIN, false); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertRuffianSmasher(false); + } + + @Test + public void testNightToDayTransform() { + currentGame.setDaytime(false); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); + addCard(Zone.HAND, playerA, ruffian); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, ruffian); + setDayNight(1, PhaseStep.POSTCOMBAT_MAIN, true); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertRuffianSmasher(true); + } + + @Test + public void testMoonmistFails() { + addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); + addCard(Zone.BATTLEFIELD, playerA, ruffian); + addCard(Zone.BATTLEFIELD, playerA, outcasts); + addCard(Zone.HAND, playerA, moonmist); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, moonmist); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertRuffianSmasher(true); + assertPermanentCount(playerA, outcasts, 0); + assertPowerToughness(playerA, wantons, 7, 7); + } + + @Test + public void testImmerwolfPreventsTransformation() { + currentGame.setDaytime(false); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); + addCard(Zone.BATTLEFIELD, playerA, immerwolf); + addCard(Zone.HAND, playerA, ruffian); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, ruffian); + setDayNight(1, PhaseStep.POSTCOMBAT_MAIN, true); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertDayNight(true); + assertPowerToughness(playerA, smasher, 6 + 1, 5 + 1); + assertPermanentCount(playerA, ruffian, 0); + } + + @Test + public void testImmerwolfRemoved() { + currentGame.setDaytime(false); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5); + addCard(Zone.BATTLEFIELD, playerA, immerwolf); + addCard(Zone.HAND, playerA, bolt); + addCard(Zone.HAND, playerA, ruffian); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, ruffian); + setDayNight(1, PhaseStep.BEGIN_COMBAT, true); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_COMBAT); + execute(); + + assertDayNight(true); + assertPowerToughness(playerA, smasher, 6 + 1, 5 + 1); + assertPermanentCount(playerA, ruffian, 0); + + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, bolt, immerwolf); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertRuffianSmasher(true); + } + + @Test + public void testNoSpellsBecomesNight() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); + addCard(Zone.HAND, playerA, ruffian); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, ruffian); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertRuffianSmasher(true); + + setStopAt(2, PhaseStep.END_TURN); + execute(); + + assertRuffianSmasher(true); + + setStopAt(3, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertRuffianSmasher(false); + } + + @Test + public void testTwoSpellsBecomesDay() { + currentGame.setDaytime(false); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5); + addCard(Zone.HAND, playerA, ruffian); + addCard(Zone.HAND, playerA, bolt); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, ruffian); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bolt, playerB); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertLife(playerB, 20 - 3); + assertGraveyardCount(playerA, bolt, 1); + assertRuffianSmasher(false); + + setStopAt(2, PhaseStep.END_TURN); + execute(); + + assertRuffianSmasher(true); + + setStopAt(3, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertRuffianSmasher(false); + } + + @Test + public void testCurseOfLeechesRegular() { + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3); + addCard(Zone.HAND, playerA, curse); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, curse, playerB); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertDayNight(true); + Permanent permanent = getPermanent(curse); + Assert.assertTrue("Curse is attached to playerB", permanent.isAttachedTo(playerB.getId())); + assertPermanentCount(playerA, lurker, 0); + } + + @Test + public void testCurseOfLeechesNightbound() { + currentGame.setDaytime(false); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3); + addCard(Zone.HAND, playerA, curse); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, curse, playerB); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertDayNight(false); + assertPermanentCount(playerA, curse, 0); + assertPermanentCount(playerA, lurker, 1); + } + + @Test + public void testCurseOfLeechesDayToNight() { + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3); + addCard(Zone.HAND, playerA, curse); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, curse, playerB); + setDayNight(1, PhaseStep.POSTCOMBAT_MAIN, false); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertDayNight(false); + assertPermanentCount(playerA, curse, 0); + assertPermanentCount(playerA, lurker, 1); + } + + @Test + public void testCurseOfLeechesNightToDay() { + currentGame.setDaytime(false); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3); + addCard(Zone.HAND, playerA, curse); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, curse, playerB); + setChoice(playerA, playerB.getName()); + setDayNight(1, PhaseStep.POSTCOMBAT_MAIN, true); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertDayNight(true); + Permanent permanent = getPermanent(curse); + Assert.assertTrue("Curse is attached to playerB", permanent.isAttachedTo(playerB.getId())); + assertPermanentCount(playerA, lurker, 0); + } + + @Test + public void testBrimstoneVandalBecomeDay() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); + addCard(Zone.HAND, playerA, vandal); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, vandal); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertDayNight(true); + assertLife(playerB, 20); + } + + @Test + public void testBrimstoneVandalTrigger() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); + addCard(Zone.HAND, playerA, bolt, 2); + addCard(Zone.HAND, playerA, vandal); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, vandal); + + setStrictChooseMode(true); + setStopAt(3, PhaseStep.UPKEEP); + execute(); + + assertDayNight(false); + assertLife(playerB, 20 - 1); + + castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, bolt, playerB); + castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, bolt, playerB); + + setStopAt(4, PhaseStep.UPKEEP); + execute(); + assertAllCommandsUsed(); + + assertDayNight(true); + assertLife(playerB, 20 - 1 - 3 - 3 - 1); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransformTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransformTest.java index 5329f99df1..9ef18543e7 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransformTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransformTest.java @@ -1,15 +1,13 @@ package org.mage.test.cards.abilities.keywords; +import mage.constants.CardType; import mage.constants.PhaseStep; import mage.constants.Zone; import mage.counters.CounterType; -import mage.game.permanent.Permanent; -import org.junit.Assert; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; /** - * * @author LevelX2 */ public class TransformTest extends CardTestPlayerBase { @@ -133,7 +131,7 @@ public class TransformTest extends CardTestPlayerBase { * 4G Creature - Human Shaman Whenever a permanent you control transforms * into a non-Human creature, put a 2/2 green Wolf creature token onto the * battlefield. - * + *

* Reported bug: "It appears to trigger either when a non-human creature * transforms OR when a creature transforms from a non-human into a human * (as in when a werewolf flips back to the sun side), rather than when a @@ -171,24 +169,51 @@ public class TransformTest extends CardTestPlayerBase { addCard(Zone.HAND, playerA, "Startled Awake"); // SORCERY {2}{U}{U}" addCard(Zone.BATTLEFIELD, playerA, "Island", 9); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Startled Awake"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Startled Awake", playerB); activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{3}{U}{U}"); + + setStrictChooseMode(true); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); + assertAllCommandsUsed(); assertGraveyardCount(playerB, 13); assertGraveyardCount(playerA, "Startled Awake", 0); assertPermanentCount(playerA, "Persistent Nightmare", 1); // Night-side card of Startled Awake - Permanent nightmare = getPermanent("Persistent Nightmare", playerA); - Assert.assertTrue("Has to have creature card type", nightmare.isCreature(currentGame)); - Assert.assertFalse("Has not to have sorcery card type", nightmare.isSorcery(currentGame)); + assertType("Persistent Nightmare", CardType.CREATURE, true); + assertType("Persistent Nightmare", CardType.SORCERY, false); + } + + @Test + public void testStartledAwakeMoonmist() { + addCard(Zone.HAND, playerA, "Startled Awake"); + addCard(Zone.HAND, playerA, "Moonmist"); + addCard(Zone.BATTLEFIELD, playerA, "Tropical Island", 11); + addCard(Zone.BATTLEFIELD, playerA, "Maskwood Nexus"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Startled Awake", playerB); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{3}{U}{U}"); + + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Moonmist"); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertGraveyardCount(playerB, 13); + assertGraveyardCount(playerA, "Startled Awake", 0); + assertPermanentCount(playerA, "Persistent Nightmare", 1); // Night-side card of Startled Awake + assertType("Persistent Nightmare", CardType.CREATURE, true); + assertType("Persistent Nightmare", CardType.SORCERY, false); } /** * When copy token of Lambholt Pacifist transforms with "its transform * ability", I see below error. Then rollback. - * + *

* 701.25a Only permanents represented by double-faced cards can transform. * (See rule 711, “Double-Faced Cards.”) If a spell or ability instructs a * player to transform any permanent that isn‘t represented by a @@ -221,7 +246,7 @@ public class TransformTest extends CardTestPlayerBase { /** * Mirror Mockery copies the front face of a Transformed card rather than * the current face. - * + *

* It's worth pointing out that my opponent cast Mirror Mockery the previous * turn - after it had transformed. I should have included the part of the * log that showed that Mirror Mockery was applied to the Unimpeded @@ -280,11 +305,13 @@ public class TransformTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerB, "Wastes", 3); castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Silvercoat Lion"); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, true); - activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{2}{C}", "Archangel Avacyn", "Whenever a non-Angel creature you control dies"); + activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{2}{C}", "Archangel Avacyn"); setStopAt(3, PhaseStep.PRECOMBAT_MAIN); execute(); + assertAllCommandsUsed(); assertGraveyardCount(playerA, "Lightning Bolt", 1); assertGraveyardCount(playerA, "Silvercoat Lion", 1); @@ -317,9 +344,9 @@ public class TransformTest extends CardTestPlayerBase { * was on stack, my opponent used Displacer's ability targeting Huntmaster. * That ability resolved and Huntmaster still transformed like it never left * the battlefield. - * + *

* http://www.slightlymagic.net/forum/viewtopic.php?f=70&t=20014&p=210533#p210513 - * + *

* The transform effect on the stack should fizzle. The card brought back * from Exile should be a new object unless I am interpreting the rules * incorrectly. The returned permanent uses the same GUID. @@ -356,12 +383,13 @@ public class TransformTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Ravager of the Fells", 0); assertPermanentCount(playerA, "Huntmaster of the Fells", 1); - assertPowerToughness(playerA, "Huntmaster of the Fells", 2, 2); + assertPowerToughness(playerA, "Huntmaster of the Fells", 2, 2); assertTappedCount("Plains", true, 2); assertTappedCount("Wastes", true, 1); } - @Test + + @Test public void testHuntmasterTransformed() { // Whenever this creature enters the battlefield or transforms into Huntmaster of the Fells, create a 2/2 green Wolf creature token and you gain 2 life. // At the beginning of each upkeep, if no spells were cast last turn, transform Huntmaster of the Fells. @@ -387,15 +415,16 @@ public class TransformTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Ravager of the Fells", 0); assertPermanentCount(playerA, "Huntmaster of the Fells", 1); assertPowerToughness(playerA, "Huntmaster of the Fells", 2, 2); - + } + /** * Having cast Phantasmal Image copying my opponent's flipped Thing in the * Ice, I was left with a 0/4 Awoken Horror. - * + *

* https://github.com/magefree/mage/issues/5893 - * + *

* The transform effect on the stack should fizzle. The card brought back * from Exile should be a new object unless I am interpreting the rules * incorrectly. The returned permanent uses the same GUID. @@ -440,4 +469,32 @@ public class TransformTest extends CardTestPlayerBase { } + @Test + public void testMoonmistDelver() { + addCard(Zone.BATTLEFIELD, playerA, "Island"); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 4); + addCard(Zone.HAND, playerA, "Delver of Secrets"); + addCard(Zone.HAND, playerA, "Moonmist", 2); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Delver of Secrets"); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Moonmist"); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Delver of Secrets", 0); + assertPermanentCount(playerA, "Insectile Aberration", 1); + + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Moonmist"); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertPermanentCount(playerA, "Delver of Secrets", 1); + assertPermanentCount(playerA, "Insectile Aberration", 0); + } } diff --git a/Mage/src/main/java/mage/abilities/Ability.java b/Mage/src/main/java/mage/abilities/Ability.java index 63cb477b0c..725c671925 100644 --- a/Mage/src/main/java/mage/abilities/Ability.java +++ b/Mage/src/main/java/mage/abilities/Ability.java @@ -531,6 +531,10 @@ public interface Ability extends Controllable, Serializable { */ Permanent getSourcePermanentOrLKI(Game game); + void setSourcePermanentTransformCount(Game game); + + boolean checkTransformCount(Permanent permanent, Game game); + String getTargetDescription(Targets targets, Game game); void setCanFizzle(boolean canFizzle); diff --git a/Mage/src/main/java/mage/abilities/AbilityImpl.java b/Mage/src/main/java/mage/abilities/AbilityImpl.java index 4430621822..e9cdf56991 100644 --- a/Mage/src/main/java/mage/abilities/AbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/AbilityImpl.java @@ -80,6 +80,7 @@ public abstract class AbilityImpl implements Ability { protected Outcome customOutcome = null; // uses for AI decisions instead effects protected MageIdentifier identifier; // used to identify specific ability (e.g. to match with corresponding watcher) protected String appendToRule = null; + protected int sourcePermanentTransformCount = 0; public AbilityImpl(AbilityType abilityType, Zone zone) { this.id = UUID.randomUUID(); @@ -135,6 +136,7 @@ public abstract class AbilityImpl implements Ability { this.identifier = ability.identifier; this.activated = ability.activated; this.appendToRule = ability.appendToRule; + this.sourcePermanentTransformCount = ability.sourcePermanentTransformCount; } @Override @@ -246,6 +248,7 @@ public abstract class AbilityImpl implements Ability { if (getSourceObjectZoneChangeCounter() == 0) { setSourceObjectZoneChangeCounter(game.getState().getZoneChangeCounter(getSourceId())); } + setSourcePermanentTransformCount(game); /* 20130201 - 601.2b * If the player wishes to splice any cards onto the spell (see rule 702.45), he @@ -1292,6 +1295,24 @@ public abstract class AbilityImpl implements Ability { return sourceObjectZoneChangeCounter; } + @Override + public void setSourcePermanentTransformCount(Game game) { + Permanent permanent = getSourcePermanentOrLKI(game); + if (permanent != null) { + this.sourcePermanentTransformCount = permanent.getTransformCount(); + } + } + + @Override + public boolean checkTransformCount(Permanent permanent, Game game) { + if (permanent == null + || !permanent.getId().equals(sourceId) + || permanent.getZoneChangeCounter(game) != sourceObjectZoneChangeCounter) { + return true; + } + return permanent.getTransformCount() == sourcePermanentTransformCount; + } + @Override public boolean canFizzle() { return canFizzle; diff --git a/Mage/src/main/java/mage/abilities/common/BecomeDayAsEntersAbility.java b/Mage/src/main/java/mage/abilities/common/BecomeDayAsEntersAbility.java index ac555d784e..80ec12f0dc 100644 --- a/Mage/src/main/java/mage/abilities/common/BecomeDayAsEntersAbility.java +++ b/Mage/src/main/java/mage/abilities/common/BecomeDayAsEntersAbility.java @@ -2,17 +2,18 @@ package mage.abilities.common; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; +import mage.abilities.hint.common.DayNightHint; import mage.constants.Outcome; import mage.game.Game; /** * @author TheElk801 - * TODO: this is just a placeholder for the actual ability */ public class BecomeDayAsEntersAbility extends EntersBattlefieldAbility { public BecomeDayAsEntersAbility() { super(new BecomeDayEffect()); + this.addHint(DayNightHint.instance); } private BecomeDayAsEntersAbility(final BecomeDayAsEntersAbility ability) { @@ -33,7 +34,7 @@ public class BecomeDayAsEntersAbility extends EntersBattlefieldAbility { class BecomeDayEffect extends OneShotEffect { BecomeDayEffect() { - super(Outcome.Benefit); + super(Outcome.Neutral); } private BecomeDayEffect(final BecomeDayEffect effect) { @@ -47,6 +48,10 @@ class BecomeDayEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - return true; + if (!game.hasDayNight()) { + game.setDaytime(true); + return true; + } + return false; } } diff --git a/Mage/src/main/java/mage/abilities/common/BecomesDayOrNightTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/BecomesDayOrNightTriggeredAbility.java index e955649af1..237805acbb 100644 --- a/Mage/src/main/java/mage/abilities/common/BecomesDayOrNightTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/BecomesDayOrNightTriggeredAbility.java @@ -8,7 +8,6 @@ import mage.game.events.GameEvent; /** * @author TheElk801 - * TODO: this is just a placeholder for the actual ability */ public class BecomesDayOrNightTriggeredAbility extends TriggeredAbilityImpl { @@ -26,7 +25,7 @@ public class BecomesDayOrNightTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkEventType(GameEvent event, Game game) { - return false; + return event.getType() == GameEvent.EventType.BECOMES_DAY_NIGHT; } @Override diff --git a/Mage/src/main/java/mage/abilities/common/WerewolfBackTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/WerewolfBackTriggeredAbility.java index 536d4c10a0..1915abb7ec 100644 --- a/Mage/src/main/java/mage/abilities/common/WerewolfBackTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/WerewolfBackTriggeredAbility.java @@ -11,7 +11,7 @@ import mage.game.Game; public class WerewolfBackTriggeredAbility extends BeginningOfUpkeepTriggeredAbility { public WerewolfBackTriggeredAbility() { - super(new TransformSourceEffect(false), TargetController.ANY, false); + super(new TransformSourceEffect(), TargetController.ANY, false); } private WerewolfBackTriggeredAbility(final WerewolfBackTriggeredAbility ability) { diff --git a/Mage/src/main/java/mage/abilities/common/WerewolfFrontTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/WerewolfFrontTriggeredAbility.java index 70d91b1a37..033cb06681 100644 --- a/Mage/src/main/java/mage/abilities/common/WerewolfFrontTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/WerewolfFrontTriggeredAbility.java @@ -11,7 +11,7 @@ import mage.game.Game; public class WerewolfFrontTriggeredAbility extends BeginningOfUpkeepTriggeredAbility { public WerewolfFrontTriggeredAbility() { - super(new TransformSourceEffect(true), TargetController.ANY, false); + super(new TransformSourceEffect(), TargetController.ANY, false); } private WerewolfFrontTriggeredAbility(final WerewolfFrontTriggeredAbility ability) { diff --git a/Mage/src/main/java/mage/abilities/condition/common/NightCondition.java b/Mage/src/main/java/mage/abilities/condition/common/NightCondition.java index 29e5c709d6..11a6cd4bb5 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/NightCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/NightCondition.java @@ -6,14 +6,13 @@ import mage.game.Game; /** * @author TheElk801 - * TODO: Implement this */ public enum NightCondition implements Condition { instance; @Override public boolean apply(Game game, Ability source) { - return false; + return game.checkDayNight(false); } @Override diff --git a/Mage/src/main/java/mage/abilities/effects/common/TransformSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/TransformSourceEffect.java index 13e8b95d1f..329cab439e 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/TransformSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/TransformSourceEffect.java @@ -1,43 +1,23 @@ - package mage.abilities.effects.common; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; import mage.constants.Outcome; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.game.permanent.PermanentCard; /** - * * @author nantuko */ public class TransformSourceEffect extends OneShotEffect { - private boolean withoutTrigger; - private boolean fromDayToNight; - - /** - * @param fromDayToNight Defines whether we transform from "day" side to - * "night" or vice versa. - */ - public TransformSourceEffect(boolean fromDayToNight) { - this(fromDayToNight, false); - } - - public TransformSourceEffect(boolean fromDayToNight, boolean withoutTrigger) { + public TransformSourceEffect() { super(Outcome.Transform); - this.withoutTrigger = withoutTrigger; - this.fromDayToNight = fromDayToNight; staticText = "transform {this}"; } public TransformSourceEffect(final TransformSourceEffect effect) { super(effect); - this.withoutTrigger = effect.withoutTrigger; - this.fromDayToNight = effect.fromDayToNight; } @Override @@ -47,37 +27,8 @@ public class TransformSourceEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - MageObject sourceObject = source.getSourceObjectIfItStillExists(game); // Transform only if it's the same object as the effect was put on the stack - if (sourceObject instanceof Permanent) { - Permanent sourcePermanent = (Permanent) sourceObject; - if (sourcePermanent.canTransform(source, game)) { - // check not to transform twice the same side - if (sourcePermanent.isTransformed() != fromDayToNight) { - if (withoutTrigger) { - sourcePermanent.setTransformed(fromDayToNight); - } else { - if (sourcePermanent.isTransformed()) { - Card orgCard = game.getCard(source.getSourceId()); - sourcePermanent.getPower().modifyBaseValue(orgCard.getPower().getValue()); - sourcePermanent.getToughness().modifyBaseValue(orgCard.getToughness().getValue()); - } - sourcePermanent.transform(game); - } - if (!game.isSimulation()) { - if (fromDayToNight) { - if (sourcePermanent.getSecondCardFace() != null) { - if (sourcePermanent instanceof PermanentCard) { - game.informPlayers(((PermanentCard) sourcePermanent).getCard().getLogName() + " transforms into " + sourcePermanent.getSecondCardFace().getLogName()); - } - } - } else { - game.informPlayers(sourcePermanent.getSecondCardFace().getLogName() + " transforms into " + sourcePermanent.getLogName()); - } - } - } - } - } - return true; + Permanent permanent = source.getSourcePermanentIfItStillExists(game); + // check not to transform twice the same side + return permanent != null && permanent.transform(source, game); } - } diff --git a/Mage/src/main/java/mage/abilities/effects/common/TransformTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/TransformTargetEffect.java deleted file mode 100644 index b128ae0108..0000000000 --- a/Mage/src/main/java/mage/abilities/effects/common/TransformTargetEffect.java +++ /dev/null @@ -1,88 +0,0 @@ -package mage.abilities.effects.common; - -import mage.abilities.Ability; -import mage.abilities.Mode; -import mage.abilities.effects.OneShotEffect; -import mage.constants.Outcome; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.game.permanent.PermanentCard; -import mage.target.Target; -import mage.util.CardUtil; - -/** - * - * @author LevelX2 - */ -public class TransformTargetEffect extends OneShotEffect { - - private boolean withoutTrigger; - - public TransformTargetEffect() { - this(true); - } - - public TransformTargetEffect(boolean withoutTrigger) { - super(Outcome.Transform); - this.withoutTrigger = withoutTrigger; - } - - public TransformTargetEffect(final TransformTargetEffect effect) { - super(effect); - this.withoutTrigger = effect.withoutTrigger; - } - - @Override - public TransformTargetEffect copy() { - return new TransformTargetEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (permanent != null) { - if (permanent.canTransform(source, game)) { - // check not to transform twice the same side - if (withoutTrigger) { - permanent.setTransformed(!permanent.isTransformed()); - } else { - permanent.transform(game); - } - if (!game.isSimulation()) { - if (permanent.isTransformed()) { - if (permanent.getSecondCardFace() != null) { - if (permanent instanceof PermanentCard) { - game.informPlayers(((PermanentCard) permanent).getCard().getLogName() + " transforms into " + permanent.getSecondCardFace().getLogName()); - } - } - } else { - game.informPlayers(permanent.getSecondCardFace().getLogName() + " transforms into " + permanent.getLogName()); - } - } - } - - return true; - } - return false; - } - - @Override - public String getText(Mode mode) { - if (staticText != null && !staticText.isEmpty()) { - return staticText; - } - if (mode.getTargets().isEmpty()) { - return "transform target"; - } - Target target = mode.getTargets().get(0); - if (target.getMaxNumberOfTargets() > 1) { - if (target.getMaxNumberOfTargets() == target.getNumberOfTargets()) { - return "transform " + CardUtil.numberToText(target.getNumberOfTargets()) + " target " + target.getTargetName(); - } else { - return "transform up to " + CardUtil.numberToText(target.getMaxNumberOfTargets()) + " target " + target.getTargetName(); - } - } else { - return "transform target " + mode.getTargets().get(0).getTargetName(); - } - } -} diff --git a/Mage/src/main/java/mage/abilities/hint/common/DayNightHint.java b/Mage/src/main/java/mage/abilities/hint/common/DayNightHint.java new file mode 100644 index 0000000000..a4b56be021 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/hint/common/DayNightHint.java @@ -0,0 +1,40 @@ +package mage.abilities.hint.common; + +import mage.abilities.Ability; +import mage.abilities.hint.Hint; +import mage.game.Game; +import mage.watchers.common.CastSpellLastTurnWatcher; + +/** + * @author TheElk801 + */ +public enum DayNightHint implements Hint { + instance; + + @Override + public String getText(Game game, Ability ability) { + if (!game.hasDayNight()) { + return "It's neither day nor night."; + } + boolean isDay = game.checkDayNight(true); + int spellsThisTurn = game + .getState() + .getWatcher(CastSpellLastTurnWatcher.class) + .getActivePlayerThisTurnCount(); + StringBuilder sb = new StringBuilder("It's currently "); + sb.append(isDay ? "day" : "night"); + sb.append(", active player has cast "); + sb.append(spellsThisTurn); + sb.append(" spells this turn. It will "); + sb.append((isDay ? spellsThisTurn == 0 : spellsThisTurn >= 2) ? "" : "not"); + sb.append(" become "); + sb.append(isDay ? "night" : "day"); + sb.append(" next turn."); + return sb.toString(); + } + + @Override + public DayNightHint copy() { + return this; + } +} diff --git a/Mage/src/main/java/mage/abilities/hint/common/NightHint.java b/Mage/src/main/java/mage/abilities/hint/common/NightHint.java deleted file mode 100644 index afc7f2631d..0000000000 --- a/Mage/src/main/java/mage/abilities/hint/common/NightHint.java +++ /dev/null @@ -1,27 +0,0 @@ -package mage.abilities.hint.common; - -import mage.abilities.Ability; -import mage.abilities.condition.common.NightCondition; -import mage.abilities.hint.ConditionHint; -import mage.abilities.hint.Hint; -import mage.game.Game; - -/** - * @author TheElk801 - */ -public enum NightHint implements Hint { - instance; - private static final Hint hint = new ConditionHint( - NightCondition.instance, "It's currently night" - ); - - @Override - public String getText(Game game, Ability ability) { - return hint.getText(game, ability); - } - - @Override - public Hint copy() { - return this; - } -} diff --git a/Mage/src/main/java/mage/abilities/keyword/DayboundAbility.java b/Mage/src/main/java/mage/abilities/keyword/DayboundAbility.java index 1e8761d6b4..619210a997 100644 --- a/Mage/src/main/java/mage/abilities/keyword/DayboundAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/DayboundAbility.java @@ -1,16 +1,20 @@ package mage.abilities.keyword; +import mage.abilities.Ability; import mage.abilities.StaticAbility; -import mage.constants.Zone; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.hint.common.DayNightHint; +import mage.constants.*; +import mage.game.Game; /** * @author TheElk801 - * TODO: Implement this */ public class DayboundAbility extends StaticAbility { public DayboundAbility() { - super(Zone.BATTLEFIELD, null); + super(Zone.BATTLEFIELD, new DayboundEffect()); + this.addHint(DayNightHint.instance); } private DayboundAbility(final DayboundAbility ability) { @@ -27,3 +31,27 @@ public class DayboundAbility extends StaticAbility { return new DayboundAbility(this); } } + +class DayboundEffect extends ContinuousEffectImpl { + + DayboundEffect() { + super(Duration.WhileOnBattlefield, Layer.PlayerEffects, SubLayer.NA, Outcome.Benefit); + } + + private DayboundEffect(final DayboundEffect effect) { + super(effect); + } + + @Override + public DayboundEffect copy() { + return new DayboundEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + if (!game.hasDayNight()) { + game.setDaytime(true); + } + return true; + } +} diff --git a/Mage/src/main/java/mage/abilities/keyword/NightboundAbility.java b/Mage/src/main/java/mage/abilities/keyword/NightboundAbility.java index 804b63c83c..5269cd301b 100644 --- a/Mage/src/main/java/mage/abilities/keyword/NightboundAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/NightboundAbility.java @@ -1,16 +1,21 @@ package mage.abilities.keyword; +import mage.abilities.Ability; import mage.abilities.StaticAbility; -import mage.constants.Zone; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.hint.common.DayNightHint; +import mage.cards.Card; +import mage.constants.*; +import mage.game.Game; /** * @author TheElk801 - * TODO: Implement this */ public class NightboundAbility extends StaticAbility { public NightboundAbility() { - super(Zone.BATTLEFIELD, null); + super(Zone.BATTLEFIELD, new NightboundEffect()); + this.addHint(DayNightHint.instance); } private NightboundAbility(final NightboundAbility ability) { @@ -26,4 +31,34 @@ public class NightboundAbility extends StaticAbility { public NightboundAbility copy() { return new NightboundAbility(this); } + + public static boolean checkCard(Card card, Game game) { + return game.checkDayNight(false) + && card.getSecondCardFace() != null + && card.getSecondCardFace().getAbilities().containsClass(NightboundAbility.class); + } +} + +class NightboundEffect extends ContinuousEffectImpl { + + NightboundEffect() { + super(Duration.WhileOnBattlefield, Layer.PlayerEffects, SubLayer.NA, Outcome.Benefit); + } + + private NightboundEffect(final NightboundEffect effect) { + super(effect); + } + + @Override + public NightboundEffect copy() { + return new NightboundEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + if (!game.hasDayNight()) { + game.setDaytime(false); + } + return true; + } } diff --git a/Mage/src/main/java/mage/abilities/keyword/TransformAbility.java b/Mage/src/main/java/mage/abilities/keyword/TransformAbility.java index 7017d0cd06..37223ad614 100644 --- a/Mage/src/main/java/mage/abilities/keyword/TransformAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/TransformAbility.java @@ -64,7 +64,6 @@ public class TransformAbility extends SimpleStaticAbility { } permanent.getPower().modifyBaseValue(sourceCard.getPower().getValue()); permanent.getToughness().modifyBaseValue(sourceCard.getToughness().getValue()); - permanent.setTransformable(sourceCard.isTransformable()); } } diff --git a/Mage/src/main/java/mage/cards/Card.java b/Mage/src/main/java/mage/cards/Card.java index c00bffaf70..5db0ca7208 100644 --- a/Mage/src/main/java/mage/cards/Card.java +++ b/Mage/src/main/java/mage/cards/Card.java @@ -70,8 +70,6 @@ public interface Card extends MageObject { boolean isTransformable(); - void setTransformable(boolean transformable); - Card getSecondCardFace(); boolean isNightCard(); diff --git a/Mage/src/main/java/mage/cards/CardImpl.java b/Mage/src/main/java/mage/cards/CardImpl.java index e20db01632..a06431ed07 100644 --- a/Mage/src/main/java/mage/cards/CardImpl.java +++ b/Mage/src/main/java/mage/cards/CardImpl.java @@ -43,7 +43,6 @@ public abstract class CardImpl extends MageObjectImpl implements Card { protected String tokenSetCode; protected String tokenDescriptor; protected Rarity rarity; - protected boolean transformable; protected Class secondSideCardClazz; protected Card secondSideCard; protected boolean nightCard; @@ -121,7 +120,6 @@ public abstract class CardImpl extends MageObjectImpl implements Card { tokenDescriptor = card.tokenDescriptor; rarity = card.rarity; - transformable = card.transformable; secondSideCardClazz = card.secondSideCardClazz; secondSideCard = null; // will be set on first getSecondCardFace call if card has one nightCard = card.nightCard; @@ -618,12 +616,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card { @Override public boolean isTransformable() { - return this.transformable; - } - - @Override - public void setTransformable(boolean transformable) { - this.transformable = transformable; + return this.secondSideCardClazz != null || this.nightCard; } @Override diff --git a/Mage/src/main/java/mage/cards/mock/MockCard.java b/Mage/src/main/java/mage/cards/mock/MockCard.java index 0a6b411344..1e94fe8d55 100644 --- a/Mage/src/main/java/mage/cards/mock/MockCard.java +++ b/Mage/src/main/java/mage/cards/mock/MockCard.java @@ -63,7 +63,6 @@ public class MockCard extends CardImpl { this.flipCard = card.isFlipCard(); - this.transformable = card.isDoubleFaced(); this.nightCard = card.isNightCard(); if (card.getSecondSideName() != null && !card.getSecondSideName().isEmpty()) { this.secondSideCard = new MockCard(CardRepository.instance.findCardWPreferredSet(card.getSecondSideName(), card.getSetCode(), false)); diff --git a/Mage/src/main/java/mage/cards/mock/MockSplitCard.java b/Mage/src/main/java/mage/cards/mock/MockSplitCard.java index d0b3b86113..de5e116b60 100644 --- a/Mage/src/main/java/mage/cards/mock/MockSplitCard.java +++ b/Mage/src/main/java/mage/cards/mock/MockSplitCard.java @@ -37,7 +37,6 @@ public class MockSplitCard extends SplitCard { this.color = card.getColor(); this.flipCard = card.isFlipCard(); - this.transformable = card.isDoubleFaced(); this.nightCard = card.isNightCard(); if (card.getSecondSideName() != null && !card.getSecondSideName().isEmpty()) { this.secondSideCard = new MockCard(CardRepository.instance.findCardWPreferredSet(card.getSecondSideName(), card.getSetCode(), false)); diff --git a/Mage/src/main/java/mage/game/Game.java b/Mage/src/main/java/mage/game/Game.java index 9cbdbf01d5..1ec9f2439f 100644 --- a/Mage/src/main/java/mage/game/Game.java +++ b/Mage/src/main/java/mage/game/Game.java @@ -386,6 +386,26 @@ public interface Game extends MageItem, Serializable, Copyable { void ventureIntoDungeon(UUID playerId); + /** + * Tells whether the current game has day or night, defaults to false + */ + boolean hasDayNight(); + + /** + * Sets game to day or night, sets hasDayNight to true + * + * @param daytime day is true, night is false + */ + void setDaytime(boolean daytime); + + /** + * Returns true if hasDayNight is true and parameter matches current day/night value + * Returns false if hasDayNight is false + * + * @param daytime day is true, night is false + */ + boolean checkDayNight(boolean daytime); + /** * Adds a permanent to the battlefield * diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index 71cb83352f..d21094e545 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -14,10 +14,7 @@ import mage.abilities.effects.Effect; import mage.abilities.effects.PreventionEffectData; import mage.abilities.effects.common.CopyEffect; import mage.abilities.effects.common.InfoEffect; -import mage.abilities.keyword.BestowAbility; -import mage.abilities.keyword.CompanionAbility; -import mage.abilities.keyword.MorphAbility; -import mage.abilities.keyword.TransformAbility; +import mage.abilities.keyword.*; import mage.abilities.mana.DelayedTriggeredManaAbility; import mage.abilities.mana.TriggeredManaAbility; import mage.actions.impl.MageAction; @@ -552,6 +549,35 @@ public abstract class GameImpl implements Game { fireEvent(GameEvent.getEvent(GameEvent.EventType.VENTURED, playerId, null, playerId)); } + @Override + public boolean hasDayNight() { + return state.isHasDayNight(); + } + + @Override + public void setDaytime(boolean daytime) { + if (!state.isHasDayNight()) { + informPlayers("It has become " + (daytime ? "day" : "night")); + } + if (!state.setDaytime(daytime)) { + return; + } + // TODO: add day/night sound effect + informPlayers("It has become " + (daytime ? "day" : "night")); + fireEvent(GameEvent.getEvent(GameEvent.EventType.BECOMES_DAY_NIGHT, null, null, null)); + for (Permanent permanent : state.getBattlefield().getAllPermanents()) { + if ((daytime && permanent.getAbilities(this).containsClass(NightboundAbility.class)) + || (!daytime && permanent.getAbilities(this).containsClass(DayboundAbility.class))) { + permanent.transform(null, this, true); + } + } + } + + @Override + public boolean checkDayNight(boolean daytime) { + return state.isHasDayNight() && state.isDaytime() == daytime; + } + @Override public UUID getOwnerId(UUID objectId) { return getOwnerId(getObject(objectId)); @@ -1933,6 +1959,9 @@ public abstract class GameImpl implements Game { if (newAbility.getSourceObjectZoneChangeCounter() == 0) { newAbility.setSourceObjectZoneChangeCounter(getState().getZoneChangeCounter(ability.getSourceId())); } + if (!(newAbility instanceof DelayedTriggeredAbility)) { + newAbility.setSourcePermanentTransformCount(this); + } newAbility.setTriggerEvent(triggeringEvent); state.addTriggeredAbility(newAbility); } @@ -1949,6 +1978,7 @@ public abstract class GameImpl implements Game { newAbility.newId(); if (source != null) { newAbility.setSourceObjectZoneChangeCounter(getState().getZoneChangeCounter(source.getSourceId())); + newAbility.setSourcePermanentTransformCount(this); } newAbility.initOnAdding(this); // ability.init is called as the ability triggeres not now. @@ -2585,6 +2615,17 @@ public abstract class GameImpl implements Game { } } + // Daybound/Nightbound permanents should be transformed according to day/night + // This is not a state-based action but it's unclear where else to put it + if (hasDayNight()) { + for (Permanent permanent : getBattlefield().getAllActivePermanents()) { + if ((permanent.getAbilities(this).containsClass(DayboundAbility.class) && !state.isDaytime()) + || (permanent.getAbilities(this).containsClass(NightboundAbility.class) && state.isDaytime())) { + somethingHappened = permanent.transform(null, this, true) || somethingHappened; + } + } + } + //TODO: implement the rest return somethingHappened; } @@ -2757,6 +2798,8 @@ public abstract class GameImpl implements Game { @Override public void informPlayers(String message) { + // Uncomment to print game messages + // System.out.println(message.replaceAll("\\<.*?\\>", "")); if (simulation) { return; } diff --git a/Mage/src/main/java/mage/game/GameState.java b/Mage/src/main/java/mage/game/GameState.java index 491c26b587..1bb704405f 100644 --- a/Mage/src/main/java/mage/game/GameState.java +++ b/Mage/src/main/java/mage/game/GameState.java @@ -105,6 +105,8 @@ public class GameState implements Serializable, Copyable { private final Map usePowerInsteadOfToughnessForDamageLethalityFilters = new HashMap<>(); private Set commandersToStay = new HashSet<>(); // commanders that do not go back to command zone private boolean manaBurn = false; + private boolean hasDayNight = false; + private boolean isDaytime = true; private int applyEffectsCounter; // Upcounting number of each applyEffects execution @@ -193,6 +195,8 @@ public class GameState implements Serializable, Copyable { state.usePowerInsteadOfToughnessForDamageLethalityFilters.forEach((uuid, filter) -> this.usePowerInsteadOfToughnessForDamageLethalityFilters.put(uuid, filter.copy())); this.commandersToStay.addAll(state.commandersToStay); + this.hasDayNight = state.hasDayNight; + this.isDaytime = state.isDaytime; } public void clearOnGameRestart() { @@ -280,6 +284,8 @@ public class GameState implements Serializable, Copyable { state.usePowerInsteadOfToughnessForDamageLethalityFilters.forEach((uuid, filter) -> this.usePowerInsteadOfToughnessForDamageLethalityFilters.put(uuid, filter.copy())); this.commandersToStay = state.commandersToStay; + this.hasDayNight = state.hasDayNight; + this.isDaytime = state.isDaytime; } @Override @@ -872,7 +878,7 @@ public class GameState implements Serializable, Copyable { for (Map.Entry> entry : eventsByKey.entrySet()) { Set movedCards = new LinkedHashSet<>(); Set movedTokens = new LinkedHashSet<>(); - for (Iterator it = entry.getValue().iterator(); it.hasNext();) { + for (Iterator it = entry.getValue().iterator(); it.hasNext(); ) { GameEvent event = it.next(); ZoneChangeEvent castEvent = (ZoneChangeEvent) event; UUID targetId = castEvent.getTargetId(); @@ -946,8 +952,8 @@ public class GameState implements Serializable, Copyable { * span * * @param ability - * @param sourceId - if source object can be moved between zones then you - * must set it here (each game cycle clear all source related triggers) + * @param sourceId - if source object can be moved between zones then you + * must set it here (each game cycle clear all source related triggers) * @param attachedTo */ public void addAbility(Ability ability, UUID sourceId, MageObject attachedTo) { @@ -1153,8 +1159,8 @@ public class GameState implements Serializable, Copyable { * @param attachedTo * @param ability * @param copyAbility copies non MageSingleton abilities before adding to - * state (allows to have multiple instances in one object, e.g. false param - * will simulate keyword/singleton) + * state (allows to have multiple instances in one object, e.g. false param + * will simulate keyword/singleton) */ public void addOtherAbility(Card attachedTo, Ability ability, boolean copyAbility) { checkWrongDynamicAbilityUsage(attachedTo, ability); @@ -1413,6 +1419,21 @@ public class GameState implements Serializable, Copyable { return manaBurn; } + boolean isHasDayNight() { + return hasDayNight; + } + + boolean setDaytime(boolean daytime) { + boolean flag = this.hasDayNight && this.isDaytime != daytime; + this.hasDayNight = true; + this.isDaytime = daytime; + return flag; + } + + boolean isDaytime() { + return isDaytime; + } + @Override public String toString() { return CardUtil.getTurnInfo(this); diff --git a/Mage/src/main/java/mage/game/events/GameEvent.java b/Mage/src/main/java/mage/game/events/GameEvent.java index 69c5415482..8a5f93b38f 100644 --- a/Mage/src/main/java/mage/game/events/GameEvent.java +++ b/Mage/src/main/java/mage/game/events/GameEvent.java @@ -334,7 +334,7 @@ public class GameEvent implements Serializable { UNTAP, UNTAPPED, FLIP, FLIPPED, UNFLIP, UNFLIPPED, - TRANSFORM, TRANSFORMED, + TRANSFORM, TRANSFORMING, TRANSFORMED, ADAPT, BECOMES_MONSTROUS, /* BECOMES_EXERTED @@ -356,6 +356,7 @@ public class GameEvent implements Serializable { */ BECOME_MONARCH, BECOMES_MONARCH, + BECOMES_DAY_NIGHT, MEDITATED, PHASE_OUT, PHASED_OUT, PHASE_IN, PHASED_IN, diff --git a/Mage/src/main/java/mage/game/permanent/Permanent.java b/Mage/src/main/java/mage/game/permanent/Permanent.java index 65b4704253..b91b9f740a 100644 --- a/Mage/src/main/java/mage/game/permanent/Permanent.java +++ b/Mage/src/main/java/mage/game/permanent/Permanent.java @@ -47,12 +47,16 @@ public interface Permanent extends Card, Controllable { boolean flip(Game game); - boolean transform(Game game); + boolean transform(Ability source, Game game); + + boolean transform(Ability source, Game game, boolean ignoreDayNight); boolean isTransformed(); void setTransformed(boolean value); + int getTransformCount(); + boolean isPhasedIn(); boolean isPhasedOutIndirectly(); @@ -289,15 +293,6 @@ public interface Permanent extends Card, Controllable { */ boolean canUseActivatedAbilities(Game game); - /** - * Checks by restriction effects if the permanent can transform - * - * @param ability the ability that causes the transform - * @param game - * @return true - permanent can transform - */ - boolean canTransform(Ability ability, Game game); - boolean removeFromCombat(Game game); boolean removeFromCombat(Game game, boolean withInfo); @@ -413,5 +408,4 @@ public interface Permanent extends Card, Controllable { } return getAttachedTo().equals(otherId); } - } diff --git a/Mage/src/main/java/mage/game/permanent/PermanentCard.java b/Mage/src/main/java/mage/game/permanent/PermanentCard.java index 8b813625aa..13c4dc60f5 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentCard.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentCard.java @@ -5,6 +5,7 @@ import mage.abilities.Abilities; import mage.abilities.Ability; import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCosts; +import mage.abilities.keyword.NightboundAbility; import mage.abilities.keyword.TransformAbility; import mage.cards.Card; import mage.cards.LevelerCard; @@ -70,7 +71,8 @@ public class PermanentCard extends PermanentImpl { maxLevelCounters = ((LevelerCard) card).getMaxLevelCounters(); } if (isTransformable()) { - if (game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + getId()) != null) { + if (game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + getId()) != null + || NightboundAbility.checkCard(this, game)) { game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + getId(), null); setTransformed(true); TransformAbility.transform(this, getSecondCardFace(), game, null); @@ -132,14 +134,10 @@ public class PermanentCard extends PermanentImpl { this.cardNumber = card.getCardNumber(); this.usesVariousArt = card.getUsesVariousArt(); - this.transformable = card.isTransformable(); - if (this.transformable) { - this.nightCard = card.isNightCard(); - if (!this.nightCard) { - this.secondSideCard = card.getSecondCardFace(); - this.secondSideCardClazz = this.secondSideCard.getClass(); - } + if (card.getSecondCardFace() != null) { + this.secondSideCardClazz = card.getSecondCardFace().getClass(); } + this.nightCard = card.isNightCard(); this.flipCard = card.isFlipCard(); this.flipCardName = card.getFlipCardName(); } diff --git a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java index 26b10e2d08..f27244bd08 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java @@ -103,6 +103,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { protected List markedDamage; protected int markedLifelink; protected int timesLoyaltyUsed = 0; + protected int transformCount = 0; protected Map info; protected int createOrder; @@ -168,6 +169,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { this.pairedPermanent = permanent.pairedPermanent; this.bandedCards.addAll(permanent.bandedCards); this.timesLoyaltyUsed = permanent.timesLoyaltyUsed; + this.transformCount = permanent.transformCount; this.morphed = permanent.morphed; this.manifested = permanent.manifested; @@ -562,16 +564,46 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { } @Override - public boolean transform(Game game) { - if (transformable) { - if (!replaceEvent(EventType.TRANSFORM, game)) { - setTransformed(!transformed); - game.applyEffects(); - game.addSimultaneousEvent(GameEvent.getEvent(GameEvent.EventType.TRANSFORMED, getId(), getControllerId())); - return true; - } + public boolean transform(Ability source, Game game) { + return this.transform(source, game, false); + } + + private boolean checkDayNightBound() { + return this.getAbilities().containsClass(DayboundAbility.class) + || this.getAbilities().containsClass(NightboundAbility.class); + } + + private Card getOtherFace() { + return transformed ? this.getMainCard() : this.getMainCard().getSecondCardFace(); + } + + @Override + public boolean transform(Ability source, Game game, boolean ignoreDayNight) { + if (!this.isTransformable() + || (!ignoreDayNight && this.checkDayNightBound()) + || this.getOtherFace().isInstantOrSorcery() + || (source != null && !source.checkTransformCount(this, game)) + || this.replaceEvent(EventType.TRANSFORM, game)) { + return false; } - return false; + if (this.transformed) { + Card orgCard = this.getMainCard(); + this.getPower().modifyBaseValue(orgCard.getPower().getValue()); + this.getToughness().modifyBaseValue(orgCard.getToughness().getValue()); + } + game.informPlayers(this.getLogName() + " transforms into " + this.getOtherFace().getLogName() + + CardUtil.getSourceLogName(game, source, this.getId())); + this.setTransformed(!this.transformed); + this.transformCount++; + game.applyEffects(); + this.replaceEvent(EventType.TRANSFORMING, game); + game.addSimultaneousEvent(GameEvent.getEvent(EventType.TRANSFORMED, this.getId(), this.getControllerId())); + return true; + } + + @Override + public int getTransformCount() { + return transformCount; } @Override @@ -1406,21 +1438,6 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { return true; } - @Override - public boolean canTransform(Ability source, Game game) { - if (transformable) { - for (Map.Entry> entry : game.getContinuousEffects().getApplicableRestrictionEffects(this, game).entrySet()) { - RestrictionEffect effect = entry.getKey(); - for (Ability ability : entry.getValue()) { - if (!effect.canTransform(this, ability, game, true)) { - return false; - } - } - } - } - return transformable; - } - @Override public void setAttacking(boolean attacking) { this.attacking = attacking; @@ -1750,5 +1767,4 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { detachAllAttachments(game); return successfullyMoved; } - } diff --git a/Mage/src/main/java/mage/game/stack/Spell.java b/Mage/src/main/java/mage/game/stack/Spell.java index 6738fd8f1a..cec9147374 100644 --- a/Mage/src/main/java/mage/game/stack/Spell.java +++ b/Mage/src/main/java/mage/game/stack/Spell.java @@ -907,11 +907,6 @@ public class Spell extends StackObjectImpl implements Card { throw new UnsupportedOperationException("Unsupported operation"); } - @Override - public void setTransformable(boolean value) { - throw new UnsupportedOperationException("Unsupported operation"); - } - @Override public int getZoneChangeCounter(Game game) { // spell's zcc can't be changed after put to stack diff --git a/Mage/src/main/java/mage/game/stack/StackAbility.java b/Mage/src/main/java/mage/game/stack/StackAbility.java index e9493bcb31..bfddba81ce 100644 --- a/Mage/src/main/java/mage/game/stack/StackAbility.java +++ b/Mage/src/main/java/mage/game/stack/StackAbility.java @@ -576,6 +576,16 @@ public class StackAbility extends StackObjectImpl implements Ability { return ability.getSourcePermanentOrLKI(game); } + @Override + public void setSourcePermanentTransformCount(Game game) { + ability.setSourcePermanentTransformCount(game); + } + + @Override + public boolean checkTransformCount(Permanent permanent, Game game) { + return ability.checkTransformCount(permanent, game); + } + @Override public int getZoneChangeCounter(Game game) { return game.getState().getZoneChangeCounter(getSourceId()); diff --git a/Mage/src/main/java/mage/game/turn/Turn.java b/Mage/src/main/java/mage/game/turn/Turn.java index 80410f1dba..577eb98824 100644 --- a/Mage/src/main/java/mage/game/turn/Turn.java +++ b/Mage/src/main/java/mage/game/turn/Turn.java @@ -1,10 +1,5 @@ package mage.game.turn; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.UUID; import mage.abilities.Ability; import mage.constants.PhaseStep; import mage.constants.TurnPhase; @@ -17,6 +12,12 @@ import mage.game.stack.StackObject; import mage.players.Player; import mage.util.ThreadLocalStringBuilder; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.UUID; + /** * @author BetaSteward_at_googlemail.com */ @@ -95,7 +96,7 @@ public class Turn implements Serializable { * @param activePlayer * @return true if turn is skipped */ - public boolean play(Game game, Player activePlayer) { + public boolean play(Game game, Player activePlayer) { // uncomment this to trace triggered abilities and/or continous effects // TraceUtil.traceTriggeredAbilities(game); // game.getState().getContinuousEffects().traceContinuousEffects(game); @@ -121,24 +122,25 @@ public class Turn implements Serializable { if (game.isPaused() || game.checkIfGameIsOver()) { return false; } - if (!isEndTurnRequested() || phase.getType() == TurnPhase.END) { - currentPhase = phase; - game.fireEvent(new PhaseChangedEvent(activePlayer.getId(), null)); - if (!game.getState().getTurnMods().skipPhase(activePlayer.getId(), currentPhase.getType())) { - if (phase.play(game, activePlayer.getId())) { - if (game.executingRollback()) { - return false; - } - //20091005 - 500.4/703.4n - game.emptyManaPools(null); - game.saveState(false); - - //20091005 - 500.8 - while (playExtraPhases(game, phase.getType())) { - } - } - } + if (isEndTurnRequested() && phase.getType() != TurnPhase.END) { + continue; } + currentPhase = phase; + game.fireEvent(new PhaseChangedEvent(activePlayer.getId(), null)); + if (game.getState().getTurnMods().skipPhase( + activePlayer.getId(), currentPhase.getType() + ) || !phase.play(game, activePlayer.getId())) { + continue; + } + if (game.executingRollback()) { + return false; + } + //20091005 - 500.4/703.4n + game.emptyManaPools(null); + game.saveState(false); + + //20091005 - 500.8 + while (playExtraPhases(game, phase.getType())) ; } return false; } diff --git a/Mage/src/main/java/mage/game/turn/UntapStep.java b/Mage/src/main/java/mage/game/turn/UntapStep.java index d9c0c28f38..658fba2190 100644 --- a/Mage/src/main/java/mage/game/turn/UntapStep.java +++ b/Mage/src/main/java/mage/game/turn/UntapStep.java @@ -2,14 +2,15 @@ package mage.game.turn; -import java.util.UUID; import mage.constants.PhaseStep; import mage.game.Game; import mage.game.events.GameEvent.EventType; import mage.players.Player; +import mage.watchers.common.CastSpellLastTurnWatcher; + +import java.util.UUID; /** - * * @author BetaSteward_at_googlemail.com */ public class UntapStep extends Step { @@ -28,6 +29,7 @@ public class UntapStep extends Step { @Override public void beginStep(Game game, UUID activePlayerId) { super.beginStep(game, activePlayerId); + handleDayNight(game); Player activePlayer = game.getPlayer(activePlayerId); //20091005 - 502.1/703.4a activePlayer.phasing(game); @@ -41,4 +43,18 @@ public class UntapStep extends Step { return new UntapStep(this); } + private void handleDayNight(Game game) { + if (!game.hasDayNight() || game.getTurnNum() <= 1) { + return; + } + int previousSpells = game + .getState() + .getWatcher(CastSpellLastTurnWatcher.class) + .getActivePlayerPrevTurnCount(); + if (game.checkDayNight(true) && previousSpells == 0) { + game.setDaytime(false); + } else if (game.checkDayNight(false) && previousSpells >= 2) { + game.setDaytime(true); + } + } } diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index 4b626d74db..1d4cbe1560 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -2063,11 +2063,11 @@ public abstract class PlayerImpl implements Player, Serializable { game.informPlayers(this.getLogName() + " loses " + event.getAmount() + " life" + (atCombat ? " at combat" : "") + CardUtil.getSourceLogName(game, " from ", needId, "", "")); } - if (amount > 0) { + if (event.getAmount() > 0) { game.fireEvent(new GameEvent(GameEvent.EventType.LOST_LIFE, - playerId, source, playerId, amount, atCombat)); + playerId, source, playerId, event.getAmount(), atCombat)); } - return amount; + return event.getAmount(); } return 0; } diff --git a/Mage/src/main/java/mage/util/CardUtil.java b/Mage/src/main/java/mage/util/CardUtil.java index 402ecd4419..02c273d532 100644 --- a/Mage/src/main/java/mage/util/CardUtil.java +++ b/Mage/src/main/java/mage/util/CardUtil.java @@ -1408,5 +1408,4 @@ public final class CardUtil { effect.apply(game, source); return true; } - } diff --git a/Mage/src/main/java/mage/watchers/common/CastSpellLastTurnWatcher.java b/Mage/src/main/java/mage/watchers/common/CastSpellLastTurnWatcher.java index c2fe4644a8..5a6ec9fbec 100644 --- a/Mage/src/main/java/mage/watchers/common/CastSpellLastTurnWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/CastSpellLastTurnWatcher.java @@ -16,6 +16,8 @@ public class CastSpellLastTurnWatcher extends Watcher { private final Map amountOfSpellsCastOnPrevTurn = new HashMap<>(); private final Map amountOfSpellsCastOnCurrentTurn = new HashMap<>(); private final List spellsCastThisTurnInOrder = new ArrayList<>(); + private int activePlayerPrevTurnCount = 0; + private int activePlayerThisTurnCount = 0; public CastSpellLastTurnWatcher() { super(WatcherScope.GAME); @@ -29,7 +31,9 @@ public class CastSpellLastTurnWatcher extends Watcher { if (playerId != null) { amountOfSpellsCastOnCurrentTurn.putIfAbsent(playerId, 0); amountOfSpellsCastOnCurrentTurn.compute(playerId, (k, a) -> a + 1); - + } + if (game.isActivePlayer(playerId)) { + activePlayerThisTurnCount++; } } } @@ -41,6 +45,8 @@ public class CastSpellLastTurnWatcher extends Watcher { amountOfSpellsCastOnPrevTurn.putAll(amountOfSpellsCastOnCurrentTurn); amountOfSpellsCastOnCurrentTurn.clear(); spellsCastThisTurnInOrder.clear(); + activePlayerPrevTurnCount = activePlayerThisTurnCount; + activePlayerThisTurnCount = 0; } public Map getAmountOfSpellsCastOnPrevTurn() { @@ -69,4 +75,12 @@ public class CastSpellLastTurnWatcher extends Watcher { } return 0; } + + public int getActivePlayerPrevTurnCount() { + return activePlayerPrevTurnCount; + } + + public int getActivePlayerThisTurnCount() { + return activePlayerThisTurnCount; + } }