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);
},
};
}
}
}