MatchTutorialLesson.cs

Static data for the match tutorial: lesson and chapter records with English and Russian titles, body text and hints, plus a Reload method to rebuild the lists after a hotload.

using System.Collections.Generic;
namespace Socer;

public sealed record MatchTutorialLesson(string Key,bool IsTask,string EnglishTitle,string RussianTitle,
    string EnglishBody,string RussianBody,string EnglishHint,string RussianHint)
{
    public string Title(bool russian)=>russian?RussianTitle:EnglishTitle;
    public string Body(bool russian)=>russian?RussianBody:EnglishBody;
    public string Hint(bool russian)=>russian?RussianHint:EnglishHint;
    static IReadOnlyList<MatchTutorialChapter> chapters=CreateChapters();
    static IReadOnlyList<MatchTutorialLesson> lessons=CreateLessons();
    public static IReadOnlyList<MatchTutorialChapter> Chapters=>chapters;
    public static IReadOnlyList<MatchTutorialLesson> All=>lessons;
    // Definitions can survive s&box hotload. A newly started course always
    // receives the current lesson order rather than a retained old array.
    public static void Reload(){chapters=CreateChapters();lessons=CreateLessons();}
    static IReadOnlyList<MatchTutorialChapter> CreateChapters()=>new MatchTutorialChapter[]
    {
        new("basics","welcome","Pitch commands","Команды на поле"),
        new("defence","mark","Defending","Защита"),
        new("team","plan","Team and skills","Команда и скиллы"),
        new("set-pieces","penalty","Penalties and free kicks","Пенальти и штрафные"),
        new("roster","substitution","Substitutions and injuries","Замены и травмы"),
        new("practice","freeplay","Free practice","Свободная практика")
    };
    static IReadOnlyList<MatchTutorialLesson> CreateLessons()=>new MatchTutorialLesson[]
    {
        new("welcome",false,"You are the coach","Вы — тренер",
            "This is a separate practice match. Each moment pauses for your instruction, then the players perform it. Your club, rewards and season are unchanged.",
            "Это отдельный учебный матч. Эпизод ждёт вашей команды, затем игроки выполняют её. Состав клуба, награды и сезон сохраняются.",
            "Your team attacks to the right. The minimap and team settings are at the bottom left.","Ваша команда атакует вправо. Внизу слева — миникарта и настройки команды."),
        new("select",true,"Choose your player","Выберите игрока",
            "A selected teammate receives your personal instructions. Clicking an opponent asks your player to mark them; it does not control the opponent.",
            "Выбранный футболист вашей команды получает личные приказы. Клик по сопернику просит вашего игрока взять его в опеку, но не управляет соперником.",
            "Click the highlighted teammate #10.","Нажмите на отмеченного игрока вашей команды №10."),
        new("run",true,"Make a run","Открыться под пас",
            "Move an off-ball teammate into open space. The ball carrier can use that opening. A run is a request, not an automatic pass.",
            "Отправьте игрока без мяча в свободную зону. Владелец мяча сможет воспользоваться открыванием. Забегание не означает автоматический пас.",
            "Drag #10 to the marked point, or right-click him, choose Make a run, then click the point.","Перетащите №10 к отмеченной точке. Или нажмите на него правой кнопкой, выберите «Забегание», затем нажмите на точку."),
        new("pass",true,"Ask for a pass","Попросить передачу",
            "A pass command asks the current ball carrier to play to a teammate. Accuracy, space and interception still matter.",
            "Приказ на пас просит владельца мяча отдать передачу партнёру. Точность, свободная линия и перехваты по-прежнему влияют на исход.",
            "Right-click highlighted #10, then choose Pass here in the command wheel.","Нажмите правой кнопкой на отмеченного №10 и выберите «Пас сюда» в колесе команд."),
        new("attack",true,"Build an attack","Развивать атаку",
            "Clicking the opponent's goal encourages the team to advance and look for a good finish. Players can still pass instead of shooting through a defender.",
            "Пинг ворот соперника направляет команду в атаку и на поиск хорошего завершения. Игроки могут отдать пас, если удар перекрыт защитником.",
            "Click the opponent's goal on the right.","Нажмите на ворота соперника справа."),
        new("shoot",true,"Take the shot","Пробить сейчас",
            "Shoot requests an immediate attempt by the ball carrier. It is useful in an open chance, but a rushed or blocked attempt can fail.",
            "Команда «Удар» просит владельца мяча пробить сразу. Она полезна при открытом моменте, но поспешный или перекрытый удар может не удаться.",
            "Right-click the right goal and choose Shoot!.","Нажмите правой кнопкой на правые ворота и выберите «Бить!»."),
        new("mark",true,"Stay with an opponent","Персональная опека",
            "Mark follows a particular opponent and blocks their route to goal. It keeps your defender near a threat instead of chasing every ball.",
            "Опека удерживает защитника рядом с конкретным соперником и перекрывает путь к воротам. Он не бросается за каждым перемещением мяча.",
            "Select your #5, then click the highlighted opposing #10.","Выберите своего №5 и нажмите на отмеченного №10 соперника."),
        new("press",true,"Close down the ball","Прессинг",
            "Press sends a defender into a challenge. It costs stamina and can open space behind them, so another defender should provide cover.",
            "Прессинг отправляет защитника сближаться и бороться за мяч. Он расходует силы и может открыть зону за спиной — нужна подстраховка.",
            "With your #5 selected, right-click opposing #10 and choose Press.","Выбрав своего №5, нажмите правой кнопкой на №10 соперника и выберите «Прессинг»."),
        new("zone",true,"Protect a zone","Защита зоны",
            "Without possession, a movement instruction protects the selected area. Use it to close a passing lane or restore your defensive shape.",
            "Без владения мячом приказ на перемещение защищает выбранную зону. Так можно перекрыть передачу или вернуть защитника на нужную позицию.",
            "Drag your #5 to the marked point, or right-click the point and choose Hold zone.","Перетащите своего №5 к отмеченной точке. Или нажмите на точку правой кнопкой и выберите «Держать зону»."),
        new("clear",true,"Return to team tactics","Вернуть командную игру",
            "Personal instructions expire, but you can cancel one sooner. The player then resumes the team's normal tactics.",
            "Личные приказы действуют временно, но их можно снять раньше. После отмены игрок снова следует обычной тактике команды.",
            "Right-click your #5 and choose Clear order.","Нажмите правой кнопкой на своего №5 и выберите «Снять приказ»."),
        new("plan",true,"Set the team's intensity","Настроить игру команды",
            "Tempo controls the pace of decisions and movement. Approach controls defensive depth, pressure and attacking commitment. High settings spend more stamina and leave more space behind.",
            "Темп задаёт скорость решений и движения. Настрой меняет глубину обороны, прессинг и участие в атаке. Высокая интенсивность расходует больше сил и оставляет пространство за спиной.",
            "At the bottom left, raise both Tempo and Approach to at least three quarters.","Внизу слева поднимите «Темп» и «Настрой» минимум до трёх четвертей шкалы."),
        new("stamina",false,"Watch the energy bar","Следите за силами",
            "The bar below a player's number appears when they spend stamina. Sprints, challenges and active skills use energy; calmer movement allows recovery. Tired players cannot repeat their strongest actions as often.",
            "Полоска под номером появляется при расходе стамины. Рывки, отборы и активные скиллы тратят силы; спокойное движение помогает восстановиться. Уставший игрок реже повторяет сильные действия.",
            "Watch #10 run. In career matches, use Substitutions to replace tired players: up to five changes, with no return for players taken off.","Посмотрите на рывок №10. В матчах карьеры меняйте уставших через кнопку «Замены»: до пяти замен, без возврата ушедших с поля."),
        new("links",false,"Neighbours work together","Связи соседей",
            "Compatible skills cooperate only between neighbours in your formation. Passing and movement skills help create a run; cover and pressure help a defensive pair. Changing the lineup changes its links. Skills still need a suitable situation.",
            "Совместимые скиллы взаимодействуют только у соседей в расстановке. Передача и открывание помогают организовать забегание, подстраховка и прессинг — защитную пару. Перестановка игроков меняет связи. Для срабатывания нужна подходящая ситуация.",
            "Here #7 has Thread Needle and #10 has Space Hunter. Watch their opening and pass. Your squad screen shows compatible neighbour links.","Здесь у №7 — «Разрезающая передача», у №10 — «Поиск пространства». Следите за открыванием и передачей. В составе клуба линии показывают совместимых соседей."),
        new("penalty",true,"Take a penalty","Пробейте пенальти",
            "Manual set pieces use your aim and power. Click a point inside the goal, start the power bar, then click again to take the kick. Scoring is not required to complete this lesson.",
            "На ручном стандарте вы выбираете цель и силу. Нажмите на точку внутри ворот, запустите шкалу силы и вторым нажатием выполните удар. Для прохождения не обязательно забивать.",
            "Click inside the goal. Press POWER, then SHOOT when the bar is in the middle. Repeat lets you try again without spending anything.",
            "Нажмите внутри ворот. Нажмите «СИЛА», затем «УДАР», когда шкала около середины. Кнопка «Повторить» бесплатно начинает эпизод заново."),
        new("free-kick",true,"Beat the wall","Пробейте штрафной",
            "The wall can block a free kick. Aim at the open part of the goal and choose a height by clicking higher or lower. More power is not always more accurate; the taker's ability also matters.",
            "Стенка может перекрыть штрафной. Цельтесь в открытую часть ворот; высота выбирается нажатием выше или ниже. Большая сила не всегда точнее — важен и навык исполнителя.",
            "Choose your own point in goal, then press POWER and SHOOT. In a live match the referee allows 20 seconds before an automatic kick.",
            "Выберите свою точку в воротах, затем нажмите «СИЛА» и «УДАР». В обычном матче через 20 секунд стандарт разыграется автоматически."),
        new("substitution",true,"Replace a tired player","Замените уставшего игрока",
            "Your #10 is tired. The substitution screen pauses the match while you choose who leaves and who comes on. Five changes are allowed; a player taken off cannot return in the same match.",
            "Ваш №10 устал. Экран замен приостанавливает матч: выберите, кто уйдёт и кто выйдет. Можно сделать пять замен; ушедший с поля не может вернуться в том же матче.",
            "Open Substitutions below, select #10 on the left and an outfield reserve on the right, then confirm. This practice squad is separate from your club.",
            "Откройте «Замены» ниже, выберите №10 слева и полевого запасного справа, затем подтвердите. Учебный состав отделён от вашего клуба."),
        new("injury",true,"Respond to an injury","Замените травмированного",
            "A serious injury stops play. Let the medical staff carry the player off, then choose a replacement in the compulsory substitution screen. This still uses one of your five changes.",
            "Серьёзная травма останавливает игру. Дождитесь, пока медики унесут игрока, затем выберите замену в обязательном окне. Она тоже расходует одну из пяти замен.",
            "After the stretcher leaves, choose an outfield reserve and press Bring on. With no eligible reserve or changes left, a real team must continue short-handed.",
            "Когда носилки покинут поле, выберите полевого запасного и нажмите «Выпустить». Без подходящего запасного или оставшихся замен команда продолжает в меньшинстве."),
        new("freeplay",false,"Try it yourself","Свободная практика",
            "Now combine the commands in a normal practice match. Orders influence decisions; they do not guarantee a goal or a clean tackle. Right-click opens the command wheel; dragging with the right button moves the camera.",
            "Теперь сочетайте команды в обычном учебном матче. Приказы влияют на решения, но не гарантируют гол или чистый отбор. Правая кнопка открывает колесо команд, перетаскивание правой кнопкой двигает камеру.",
            "Practice for as long as you like, then Finish to return to your club.","Практикуйтесь сколько хотите, затем нажмите «Завершить», чтобы вернуться в клуб.")
    };
}

public sealed record MatchTutorialChapter(string Key,string FirstLesson,string EnglishTitle,string RussianTitle)
{
    public string Title(bool russian)=>russian?RussianTitle:EnglishTitle;
}