using Vanguard.Rules.Cards; namespace Vanguard.Rules.Engine.Abilities; /// Скрипты карт первого сета, подключённые к движку. public static class CardScripts { public static IReadOnlyDictionary Default { get; } = new Dictionary(StringComparer.Ordinal) { ["barcgal"] = new BarcgalScript(), ["wingal"] = new WingalScript(), ["king-of-knights-alfred"] = new AlfredScript(), ["blaster-blade"] = new BlasterBladeScript(), ["lake-maiden-lien"] = new DrawOneScript("lake-maiden-lien"), ["dragon-monk-gojo"] = new DrawOneScript("dragon-monk-gojo"), ["screamin-and-dancin-announcer-shout"] = new DrawOneScript("screamin-and-dancin-announcer-shout"), ["lizard-soldier-conroe"] = new ConroeScript(), ["battle-sister-cocoa"] = new CocoaScript(), ["tyrant-deathrex"] = new DeathrexScript(), ["demon-eater"] = new DemonEaterScript(), ["maiden-of-libra"] = new MaidenOfLibraScript(), ["knight-of-rose-morgana"] = new MorganaScript(), ["battle-sister-mocha"] = new BattleSisterMochaScript(), ["covenant-knight-randolf"] = new MoreHandsPowerScript("covenant-knight-randolf"), ["stealth-beast-chigasumi"] = new MoreHandsPowerScript("stealth-beast-chigasumi"), ["queen-of-heart"] = new NamedBoostScript("queen-of-heart", "king-of-sword"), ["wyvern-strike-jarran"] = new NamedBoostScript("wyvern-strike-jarran", "wyvern-strike-tejas"), ["nightmare-baby"] = new NamedBoostScript("nightmare-baby", "blue-dust"), ["weather-girl-milk"] = new WeatherGirlMilkScript(), ["hungry-dumpty"] = new FlipDamageOnPlaceScript("hungry-dumpty", Clan.NovaGrappler), ["clay-doll-mechanic"] = new FlipDamageOnPlaceScript("clay-doll-mechanic", Clan.NovaGrappler), ["blue-dust"] = new BlueDustScript(), ["karma-queen"] = new KarmaQueenScript(), ["hell-spider"] = new HellSpiderScript(), ["dragonic-overlord"] = new DragonicOverlordScript(), ["solitary-knight-gancelot"] = new GancelotScript(), ["embodiment-of-victory-aleph"] = new AlephScript(), ["oracle-guardian-apollon"] = new ApollonScript(), ["demon-slaying-knight-lohengrin"] = new LohengrinScript(), ["vortex-dragon"] = new VortexDragonScript(), ["ceo-amaterasu"] = new CeoAmaterasuScript(), ["mr-invincible"] = new MrInvincibleScript(), ["brutal-jack"] = new BrutalJackScript(), ["asura-kaiser"] = new AsuraKaiserScript(), ["juggernaut-maximum"] = new ReturnToDeckOnAttackScript("juggernaut-maximum"), ["highspeed-brakki"] = new ReturnToDeckOnAttackScript("highspeed-brakki"), ["lozenge-magus"] = new ReturnToDeckOnBoostScript("lozenge-magus", Clan.OracleThinkTank), ["battleraizer"] = new ReturnToDeckOnBoostScript("battleraizer", Clan.NovaGrappler), ["rock-the-wall"] = new DropToSoulFromGuardianScript("rock-the-wall"), ["redshoe-milly"] = new DropToSoulFromGuardianScript("redshoe-milly"), ["guiding-zombie"] = new GuidingZombieScript(), ["stealth-dragon-voidmaster"] = new VoidmasterScript(), ["stealth-beast-hagakure"] = new HagakureScript(), ["stealth-dragon-dreadmaster"] = new DreadmasterScript(), ["monster-frank"] = new MonsterFrankScript(), ["assault-dragon-blightops"] = new BlightopsScript(), ["future-knight-llew"] = new LlewScript(), ["dragon-knight-aleph"] = new DragonKnightAlephScript(), ["crimson-butterfly-brigitte"] = new DriveCheckGradeScript("crimson-butterfly-brigitte", Clan.RoyalPaladin), ["knight-of-the-harp-tristan"] = new DriveCheckGradeScript("knight-of-the-harp-tristan", Clan.RoyalPaladin), ["knight-of-conviction-bors"] = new BorsScript(), ["starlight-unicorn"] = new StarlightUnicornScript(), ["dragon-monk-goku"] = new GokuScript(), ["berserk-dragon"] = new BerserkDragonScript(), ["flame-of-hope-aermo"] = new AermoScript(), ["demonic-dragon-madonna-joka"] = new OpponentRetireBonusScript("demonic-dragon-madonna-joka"), ["demonic-dragon-mage-rakshasa"] = new OpponentRetireBonusScript("demonic-dragon-mage-rakshasa"), }; } /// /// Knight of Rose, Morgana: при атаке можно сбросить карту из руки и получить +4000 до конца хода. /// public sealed class MorganaScript : CardScript { public override string NameId => "knight-of-rose-morgana"; public override IEnumerable Abilities { get { yield return new AbilityDefinition { Trigger = AbilityTrigger.OnAttackDeclared, Optional = true, CanPay = ctx => ctx.State.Players[ctx.Owner].Hand.Count > 0, Resolve = ctx => ctx.Engine.AskHandCardChoice( ctx.Owner, "Сбросьте карту из руки", null, card => { var p = ctx.State.Players[ctx.Owner]; p.Hand.Remove(card); p.Drop.Add(card); ctx.Engine.AddPower( ctx.Source, 4000, ctx.Source, "morgana", ModifierDuration.UntilEndOfTurn); }), }; } } } /// Tyrant, Deathrex: когда эта карта атакует, получает +5000 до конца боя. public sealed class DeathrexScript : CardScript { public override string NameId => "tyrant-deathrex"; public override IEnumerable Abilities { get { yield return new AbilityDefinition { Trigger = AbilityTrigger.OnAttackDeclared, Resolve = ctx => ctx.Engine.AddBattlePower(ctx.Source, 5000), }; yield return new AbilityDefinition { Trigger = AbilityTrigger.OnAttackHit, Condition = ctx => ctx.Engine.IsVanguardOf(ctx.Source, ctx.Owner), Resolve = ctx => { var slots = ctx.Engine.RearGuardSlots(ctx.Owner, _ => true); if (slots.Count == 0) return; ctx.Engine.AskUnitChoice( ctx.Owner, ctx.Owner, "Выберите свой Арьергард и уничтожьте его", slots, slot => ctx.Engine.RetireRearGuard(ctx.Owner, slot)); }, }; } } } /// Demon Eater: в начале Основной фазы Soul Charge 1 и +2000 до конца хода. public sealed class DemonEaterScript : CardScript { public override string NameId => "demon-eater"; public override IEnumerable Abilities { get { yield return new AbilityDefinition { Trigger = AbilityTrigger.OnPhaseStart, Resolve = ctx => { ctx.Engine.SoulCharge(ctx.Owner, 1); ctx.Engine.AddPower( ctx.Source, 2000, ctx.Source, "demon-eater", ModifierDuration.UntilEndOfTurn); }, }; yield return Bt01Abilities.RetireAllOnHit(); } } } /// Maiden of Libra: когда атака попадает, Counter Blast 2 и взять карту. public sealed class MaidenOfLibraScript : CardScript { public override string NameId => "maiden-of-libra"; public override IEnumerable Abilities { get { yield return new AbilityDefinition { Trigger = AbilityTrigger.OnAttackHit, Optional = true, CanPay = ctx => ctx.Engine.CanCounterBlast(ctx.Owner, 2), Pay = ctx => ctx.Engine.CounterBlast(ctx.Owner, 2), Resolve = ctx => ctx.Engine.DrawCards(ctx.Owner, 1), }; } } } /// /// Battle Sister, Cocoa: при размещении на VC/RC, если Авангард Oracle Think Tank, /// посмотреть верхнюю карту и оставить её на верху или отправить в низ. /// public sealed class CocoaScript : CardScript { public override string NameId => "battle-sister-cocoa"; public override IEnumerable Abilities { get { yield return new AbilityDefinition { Trigger = AbilityTrigger.OnPlace, Condition = ctx => ctx.Engine.VanguardClan(ctx.Owner) == Clan.OracleThinkTank, Resolve = ctx => ctx.Engine.LookTopAndReorder(ctx.Owner, "Верхняя карта колоды"), }; } } } /// /// Lizard Soldier, Conroe: [ACT](RC): Counter Blast 1 и уничтожить эту карту → /// найти в колоде Kagero 1 ранга или ниже и добавить в руку. /// public sealed class ConroeScript : CardScript { public override string NameId => "lizard-soldier-conroe"; public override IEnumerable Activated { get { yield return new ActivatedAbility { CanActivate = ctx => ctx.Engine.CanCounterBlast(ctx.Owner, 1), RetiresSelf = true, Resolve = ctx => { ctx.Engine.CounterBlast(ctx.Owner, 1); ctx.Engine.SearchDeckToHand( ctx.Owner, "Найдите Kagero 1 ранга или ниже", d => d.Clan == Clan.Kagero && d.Grade <= 1); }, }; } } } /// /// «[ACT]: повернуть эту карту и сбросить карту из руки → взять карту». /// Общий скрипт для Lake Maiden, Lien, Dragon Monk, Gojo и Shout. /// public sealed class DrawOneScript : CardScript { public DrawOneScript(string nameId) => NameId = nameId; public override string NameId { get; } public override IEnumerable Activated { get { yield return new ActivatedAbility { CanActivate = _ => true, RestsSelf = true, RequiresDiscard = true, Resolve = ctx => ctx.Engine.DrawCards(ctx.Owner, 1), }; } } } /// /// Blaster Blade: при размещении оплатить Counter Blast 2 и уничтожить Арьергард противника. /// На Авангарде — любой, на Арьергарде — только 2 ранга или выше и при Авангарде Royal Paladin. /// public sealed class BlasterBladeScript : CardScript { public override string NameId => "blaster-blade"; public override IEnumerable Abilities { get { yield return new AbilityDefinition { Trigger = AbilityTrigger.OnPlace, Optional = true, Condition = ctx => ctx.Engine.IsVanguardOf(ctx.Source, ctx.Owner), CanPay = ctx => ctx.Engine.CanCounterBlast(ctx.Owner, 2), Pay = ctx => ctx.Engine.CounterBlast(ctx.Owner, 2), Resolve = ctx => { var opponent = 1 - ctx.Owner; var slots = ctx.Engine.RearGuardSlots(opponent, _ => true); if (slots.Count == 0) return; ctx.Engine.AskUnitChoice( ctx.Owner, opponent, "Выберите Арьергард противника", slots, slot => ctx.Engine.RetireRearGuard(opponent, slot)); }, }; yield return new AbilityDefinition { Trigger = AbilityTrigger.OnPlace, Optional = true, Condition = ctx => !ctx.Engine.IsVanguardOf(ctx.Source, ctx.Owner) && ctx.Engine.VanguardClan(ctx.Owner) == Clan.RoyalPaladin, CanPay = ctx => ctx.Engine.CanCounterBlast(ctx.Owner, 2), Pay = ctx => ctx.Engine.CounterBlast(ctx.Owner, 2), Resolve = ctx => { var opponent = 1 - ctx.Owner; var slots = ctx.Engine.RearGuardSlots(opponent, d => d.Grade >= 2); if (slots.Count == 0) return; ctx.Engine.AskUnitChoice( ctx.Owner, opponent, "Выберите Арьергард противника 2 ранга или выше", slots, slot => ctx.Engine.RetireRearGuard(opponent, slot)); }, }; } } } /// /// Barcgal: когда другой Royal Paladin сменяет эту карту, вы можете призвать её в круг Арьергарда. /// public sealed class BarcgalScript : CardScript { public override string NameId => "barcgal"; public override IEnumerable Abilities { get { yield return new AbilityDefinition { Trigger = AbilityTrigger.OnRideOver, Optional = true, Condition = ctx => ctx.Other is not null && ctx.Catalog.CardOf(ctx.Other.PrintingId).Clan == Clan.RoyalPaladin, Resolve = ctx => ctx.Engine.CallFromSoul(ctx.Source, ctx.Owner), }; } } } /// /// Wingal: когда эта карта поддерживает Blaster Blade, усиленная карта получает +4000 до конца боя. /// public sealed class WingalScript : CardScript { private const string BlasterBlade = "blaster-blade"; public override string NameId => "wingal"; public override IEnumerable Abilities { get { yield return new AbilityDefinition { Trigger = AbilityTrigger.OnBoost, Condition = ctx => ctx.Other is not null && ctx.Catalog.CardOf(ctx.Other.PrintingId).NameId == BlasterBlade, Resolve = ctx => ctx.Engine.AddBattlePower(ctx.Other!, 4000, ctx.Source), }; } } } /// /// King of Knights, Alfred: в свой ход на круге Авангарда получает +2000 /// за каждый свой Арьергард Royal Paladin. /// public sealed class AlfredScript : CardScript { public override string NameId => "king-of-knights-alfred"; public override IEnumerable Continuous { get { yield return new ContinuousAbility { Applies = ctx => ctx.Engine.IsVanguardOf(ctx.Source, ctx.Owner) && ctx.State.ActivePlayer == ctx.Owner, PowerBonus = ctx => 2000 * ctx.Engine.CountRearGuards(ctx.Owner, Clan.RoyalPaladin), }; } } public override IEnumerable Activated { get { yield return new ActivatedAbility { CanActivate = ctx => ctx.Engine.CanCounterBlast(ctx.Owner, 3) && ctx.Engine.HasEmptyRearGuard(ctx.Owner), Resolve = ctx => { ctx.Engine.CounterBlast(ctx.Owner, 3); ctx.Engine.SearchDeckToCall( ctx.Owner, "Найдите Royal Paladin 2 ранга или ниже", d => d.Clan == Clan.RoyalPaladin && d.Grade <= 2); }, }; } } }