// Crafted with the loving help of https://github.com/just-ero

state("MusketeerGame-Win64-Shipping") {
}

startup {
    Assembly.Load(File.ReadAllBytes("Components/asl-help")).CreateInstance("Basic");

    settings.Add("tutorial_split", true, "Split tutorial separately");
    settings.SetToolTip("tutorial_split", "Split the timer when entering the first level after the tutorial. \n" +
                        "If not selected, the timer will continue to run until the first real level is completed.");

    settings.Add("load_removal", true, "Load Removal");
    settings.SetToolTip("load_removal", "Stop the timer when the game is paused or loading");

    settings.Add("combat_deductions", true, "Combat Deductions", "load_removal");
    settings.SetToolTip("combat_deductions", "Take combat deductions into account when timing the game");

    settings.Add("deaths_per_run", false, "Track Deaths per Run");
    settings.SetToolTip("deaths_per_run", "Tracks the amount of times you died this run. Resets when you go to the main menu. \n" +
                        "The necessary text component is added to your layout automatically when you restart LiveSplit or die for the first time.");

    settings.Add("deaths_per_level", false, "Track Deaths per Level");
    settings.SetToolTip("deaths_per_level", "Tracks the amount of times you died this level. Resets when you exit any given level. \n" +
                        "The necessary text component is added to your layout automatically when you restart LiveSplit or die for the first time.");

    vars.combinedGameTime = 0;

    if (timer.CurrentTimingMethod == TimingMethod.RealTime){
        var message = MessageBox.Show(
            "Would you like to change the current timing method to\nGame Time instead of Real Time?",
            "LiveSplit | Sacre Bleu Auto Splitter", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

        if (message == DialogResult.Yes){
            timer.CurrentTimingMethod = TimingMethod.GameTime;
        }
    }
}

init {
    if (settings["deaths_per_run"]) {
        vars.Helper.Texts["deaths_per_run"] = vars.Helper.Texts.Find("Deaths this Run:");
        vars.Helper.Texts["deaths_per_run"].Left = "Deaths this Run:";
        vars.Helper.Texts["deaths_per_run"].Right = 0;
    }

    if (settings["deaths_per_level"]) {
        vars.Helper.Texts["deaths_per_level"] = vars.Helper.Texts.Find("Deaths this Level:");
        vars.Helper.Texts["deaths_per_level"].Left = "Deaths this Level:";
        vars.Helper.Texts["deaths_per_level"].Right = 0;
    }

    print("[Sacre Bleu Autosplitter] Scanning memory");

    var magic = BitConverter.GetBytes(211111111ul);
    var trg = new SigScanTarget(0, magic);

    IntPtr lsTracker = IntPtr.Zero;
    foreach (var page in game.MemoryPages(true)) {
        var scn = new SignatureScanner(game, page.BaseAddress, (int)page.RegionSize);
        lsTracker = scn.Scan(trg);

        if (lsTracker != IntPtr.Zero) {
            break;
        }
    }

    if (lsTracker == IntPtr.Zero) {
        throw new Exception("Magic number not found.");
    }

    print("[Sacre Bleu Autosplitter] Scanning successful");

    vars.Helper["gameTime"] = vars.Helper.Make<int>(lsTracker + 0x08);
    vars.Helper["levelId"] = vars.Helper.Make<int>(lsTracker + 0x28);
    vars.Helper["levelFinishedLoading"] = vars.Helper.Make<int>(lsTracker + 0x2C);
    vars.Helper["deathsThisRun"] = vars.Helper.Make<int>(lsTracker + 0x128);
    vars.Helper["deathsThisLevel"] = vars.Helper.Make<int>(lsTracker + 0x12C);
    vars.Helper["levelsCompletedOnCurrentSave"] = vars.Helper.Make<int>(lsTracker + 0x140);
}

update {
    vars.Helper.Update();
    vars.Helper.MapPointers();

    if(vars.Helper["levelFinishedLoading"].Old == 0 && vars.Helper["levelFinishedLoading"].Current == 1) {
        vars.combinedGameTime += vars.Helper["gameTime"].Old;
    }

    if(settings["deaths_per_run"]) {
        if(vars.Helper["deathsThisRun"].Old != vars.Helper["deathsThisRun"].Current) {
            vars.Helper.Texts["deaths_per_run"].Right = vars.Helper["deathsThisRun"].Current;
        }
    }

    if(settings["deaths_per_level"]) {
        if(vars.Helper["deathsThisLevel"].Old != vars.Helper["deathsThisLevel"].Current) {
            vars.Helper.Texts["deaths_per_level"].Right = vars.Helper["deathsThisLevel"].Current;
        }
    }
}

start {
    if(vars.Helper["levelId"].Old == 22 && vars.Helper["levelId"].Current == 21 && vars.Helper["levelsCompletedOnCurrentSave"].Current == 0) {
        return true;
    }
}

split {
    if(settings["tutorial_split"] &&
       vars.Helper["levelsCompletedOnCurrentSave"].Current == 0 &&
       vars.Helper["levelId"].Old == 21 &&
       vars.Helper["levelId"].Current == 0) {
        return true;
      }

    if(vars.Helper["levelsCompletedOnCurrentSave"].Current > vars.Helper["levelsCompletedOnCurrentSave"].Old) {
        return true;
    }
}

isLoading {
    if(settings["load_removal"]) {
        return vars.Helper["gameTime"].Old == vars.Helper["gameTime"].Current;
    }
}

gameTime {
    if(settings["combat_deductions"]) {
        return (TimeSpan.FromMilliseconds(vars.combinedGameTime + vars.Helper["gameTime"].Current));
    }
}

onStart {
    vars.combinedGameTime = 0;
}

onReset {
    vars.combinedGameTime = 0;
}