Пример #1
0
        public static GameSpec ForGame(FromGame game)
        {
            GameSpec spec = Games.TryGetValue(game, out GameSpec baseSpec) ? baseSpec.Clone() : new GameSpec();

            spec.Game = game;
            return(spec);
        }
Пример #2
0
        public ItemReader.Result Randomize(RandomizerOptions opt, FromGame game, string gameDir, string outDir)
        {
            Console.WriteLine($"Seed: {opt.DisplaySeed}. Options: {string.Join(" ", opt.GetEnabled())}");

            string file = game == FromGame.DS3 ? @"fogdist\fog.txt" : @"dist\fog.txt";

            IDeserializer  deserializer = new DeserializerBuilder().Build();
            AnnotationData ann;

            using (var f = File.OpenText(file)) ann = deserializer.Deserialize <AnnotationData>(f);
            ann.SetGame(game);

            Events events = null;

            if (game == FromGame.DS3)
            {
                using (var f = File.OpenText(@"fogdist\locations.txt")) ann.Locations = deserializer.Deserialize <AnnotationData.FogLocations>(f);
                events = new Events(@"fogdist\Base\ds3-common.emedf.json");
            }

            Graph g = new Graph();

            g.Construct(opt, ann);

            ItemReader.Result item = new ItemReader().FindItems(opt, ann, g, events, gameDir, game);
            Console.WriteLine(item.Randomized ? $"Key item hash: {item.ItemHash}" : "No key items randomized");
            Console.WriteLine();

            new GraphConnector().Connect(opt, g, ann);

            // Actual dryruns stop short of writing modified files
            if (opt["bonedryrun"])
            {
                return(item);
            }

            Console.WriteLine();
            if (game == FromGame.DS3)
            {
                EventConfig eventConfig;
                using (var f = File.OpenText(@"fogdist\events.txt")) eventConfig = deserializer.Deserialize <EventConfig>(f);

                if (opt["eventsyaml"] || opt["events"])
                {
                    new GenerateConfig().WriteEventConfig(ann, events, opt);
                    return(item);
                }
                new GameDataWriter3().Write(opt, ann, g, gameDir, outDir, events, eventConfig);
            }
            else
            {
                if (opt["dryrun"])
                {
                    Console.WriteLine("Success (dry run)");
                    return(item);
                }
                new GameDataWriter().Write(opt, ann, g, gameDir, game);
            }
            return(item);
        }
Пример #3
0
        public void SetGame(FromGame game)
        {
            List <MapSpec> allSpecs = game == FromGame.DS3 ? DS3Specs : DS1Specs;

            Specs     = allSpecs.ToDictionary(s => s.Map, s => s);
            NameSpecs = allSpecs.ToDictionary(s => s.Name, s => s);
        }
Пример #4
0
        static void Main(string[] args)
        {
            if (args.Length > 0 && !args.Contains("/gui"))
            {
                AttachConsole(-1);
                RandomizerOptions opt = new RandomizerOptions {
                    Seed = new Random().Next()
                };
                foreach (string arg in args)
                {
                    if (uint.TryParse(arg, out uint s))
                    {
                        opt.Seed = (int)s;
                    }
                    else
                    {
                        opt[arg] = true;
                    }
                }
                FromGame game = args.Contains("ptde") ? FromGame.DS1 : FromGame.DS1R;
                game     = FromGame.DS3;
                opt.Game = game;
                string gameDir = ForGame(game).GameDir;
                if (game == FromGame.DS3)
                {
                    new Randomizer().Randomize(opt, game, opt["mergemods"] ? gameDir + @"\randomizer" : null, gameDir + @"\fog");
                }
                else
                {
                    new Randomizer().Randomize(opt, game, gameDir, gameDir);
                }
            }
            else
            {
#if DEBUG
                AttachConsole(-1);
#endif
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                // Application.Run(new MainForm());
                Application.Run(new MainForm3());
            }
        }
Пример #5
0
 public static CmdType GetCmdType(string esd, FromGame game = FromGame.UNKNOWN)
 {
     if (esd.StartsWith("talk") || esd.StartsWith("event"))
     {
         return(CmdType.Event);
     }
     if (esd.StartsWith("ai"))
     {
         return(CmdType.AI);
     }
     if (esd.StartsWith("t"))
     {
         return(CmdType.Talk);
     }
     if (esd.StartsWith("dummy") || exactChr.Contains(esd))
     {
         return(CmdType.Chr);
     }
     if (defaultCmds.TryGetValue(game, out CmdType type))
     {
         return(type);
     }
     return(CmdType.None);
 }
Пример #6
0
        private void UpdateExePath()
        {
            bool   valid    = true;
            string gamePath = null;

            try
            {
                gamePath = Path.GetDirectoryName(exe.Text);
                if (exe.Text.Trim() == "" || !Directory.Exists(gamePath))
                {
                    valid = false;
                }
                string exeName = Path.GetFileName(exe.Text).ToLower();
                if (exeName == "darksoulsremastered.exe")
                {
                    game = FromGame.DS1R;
                }
                else if (exeName == "darksouls.exe")
                {
                    game = FromGame.DS1;
                }
                else
                {
                    valid = false;
                }
            }
            catch (ArgumentException)
            {
                valid = false;
            }
            if (!valid)
            {
                game = FromGame.UNKNOWN;
                restoreButton.Enabled = false;
                restoreL.Text         = "";
                language.DataSource   = defaultLang;
                language.Enabled      = false;
                return;
            }
            Properties.Settings.Default.Exe = exe.Text;
            Properties.Settings.Default.Save();
            List <string> languages = game == FromGame.DS1R ? ds1rLang : ptdeLang;

            language.DataSource = languages;
            language.Enabled    = true;
            if (languageToSet != null && languages.Contains(languageToSet))
            {
                language.SelectedIndex = languages.IndexOf(languageToSet);
                languageToSet          = null;
            }
            List <string> files = GameDataWriter.GetAllBaseFiles(game);

            if (files.Count == 0)
            {
                randb.Enabled = false;
                setStatus($@"Error: FogMod dist\{game} subdirectory is missing", true);
            }
            List <string> times = new List <string>();

            foreach (string file in files)
            {
                string path = $@"{gamePath}\{file}";
                string bak  = path + ".bak";
                if (File.Exists(bak))
                {
                    times.Add(File.GetLastWriteTime(bak).ToString("yyyy-MM-dd HH:mm:ss"));
                }
            }
            if (times.Count == 0)
            {
                restoreL.Text         = "Backups will be created with randomization";
                restoreButton.Enabled = false;
            }
            else
            {
                restoreL.Text         = $"{(files.Count == times.Count ? "Backups" : "Partial backups")} from {times.Max()}";
                restoreButton.Enabled = true;
            }
        }
Пример #7
0
 public GameEditor(FromGame game)
 {
     this.Spec = ForGame(game);
 }
Пример #8
0
        public Result FindItems(RandomizerOptions opt, AnnotationData ann, Graph g, Events events, string gameDir, FromGame game)
        {
            Dictionary <string, string>         itemsById = ann.KeyItems.ToDictionary(item => item.ID, item => item.Name);
            Dictionary <string, List <string> > itemAreas = g.ItemAreas;

            if (ann.LotLocations != null)
            {
                GameEditor editor = new GameEditor(game);
                editor.Spec.GameDir = gameDir;
                Dictionary <string, PARAM.Layout> layouts = editor.LoadLayouts();
                Dictionary <string, PARAM>        Params  = editor.LoadParams(layouts);

                Dictionary <int, PARAM.Row> lots = Params["ItemLotParam"].Rows.ToDictionary(r => (int)r.ID, r => r);
                foreach (KeyValuePair <int, string> entry in ann.LotLocations)
                {
                    int lot = entry.Key;
                    if (!g.Areas.ContainsKey(entry.Value))
                    {
                        throw new Exception($"Internal error in lot config for {entry.Key}: {entry.Value} does not exist");
                    }
                    while (true)
                    {
                        // It's also fine to not have a lot defined as long as all key items are found
                        if (!lots.TryGetValue(lot, out PARAM.Row row))
                        {
                            break;
                        }
                        for (int i = 1; i <= 8; i++)
                        {
                            int item = (int)row[$"lotItemId0{i}"].Value;
                            if (item == 0)
                            {
                                continue;
                            }
                            int category = (int)row[$"lotItemCategory0{i}"].Value;
                            category = Universe.LotTypes.TryGetValue((uint)category, out int value) ? value : -1;
                            if (category == -1)
                            {
                                continue;
                            }
                            string id = $"{category}:{item}";
                            if (opt["debuglots"])
                            {
                                Console.WriteLine($"{entry.Key} in {entry.Value} has {id}");
                            }
                            if (itemsById.TryGetValue(id, out string name))
                            {
                                if (itemAreas[name].Count > 0 && itemAreas[name][0] != entry.Value)
                                {
                                    throw new Exception($"Item {name} found in both {itemAreas[name][0]} and {entry.Value}");
                                }
                                itemAreas[name] = new List <string> {
                                    entry.Value
                                };
                            }
                        }
                        lot++;
                    }
                }
            }
            if (ann.Locations != null)
            {
                // It's a bit hacky, but should work from anywhere, probably
                GameEditor editor = new GameEditor(game);
                editor.Spec.GameDir   = $@"fogdist";
                editor.Spec.LayoutDir = $@"fogdist\Layouts";
                editor.Spec.NameDir   = $@"fogdist\Names";

                Dictionary <string, PARAM.Layout> layouts = editor.LoadLayouts();

                int dragonFlag = -1;
                Dictionary <string, PARAM> Params = editor.LoadParams(@"fogdist\Base\Data0.bdt", layouts, true);
                if (gameDir != null)
                {
                    string paramPath = $@"{gameDir}\Data0.bdt";
                    if (File.Exists(paramPath))
                    {
                        Params = editor.LoadParams(paramPath, layouts, true);
                    }

                    string commonEmevdPath = $@"{gameDir}\event\common.emevd.dcx";
                    if (File.Exists(commonEmevdPath))
                    {
                        EMEVD       commonEmevd = EMEVD.Read(commonEmevdPath);
                        EMEVD.Event flagEvent   = commonEmevd.Events.Find(e => e.ID == 13000904);
                        if (flagEvent != null)
                        {
                            Events.Instr check = events.Parse(flagEvent.Instructions[1]);
                            dragonFlag = (int)check[3];
                            if (opt["debuglots"])
                            {
                                Console.WriteLine($"Dragon flag: {dragonFlag}");
                            }
                        }
                    }
                }

                Dictionary <int, PARAM.Row> lots  = Params["ItemLotParam"].Rows.ToDictionary(r => (int)r.ID, r => r);
                Dictionary <int, PARAM.Row> shops = Params["ShopLineupParam"].Rows.ToDictionary(r => (int)r.ID, r => r);

                void setArea(string itemName, List <string> areas)
                {
                    if (opt["debuglots"])
                    {
                        Console.WriteLine($"-- name: {itemName}");
                    }
                    if (itemAreas[itemName].Count > 0 && !itemAreas[itemName].SequenceEqual(areas))
                    {
                        throw new Exception($"Item {itemName} found in both {string.Join(",", itemAreas[itemName])} and {string.Join(",", areas)}");
                    }
                    itemAreas[itemName] = areas;
                }

                foreach (KeyItemLoc loc in ann.Locations.Items)
                {
                    List <string> areas = loc.Area.Split(' ').ToList();
                    if (!areas.All(a => g.Areas.ContainsKey(a) || itemAreas.ContainsKey(a)))
                    {
                        // Currently happens with multi-area intersection lots/shops
                        throw new Exception($"Warning: Areas not found for {loc.Area} - {loc.DebugText[0]}");
                    }
                    List <int> lotIds = loc.Lots == null ? new List <int>() : loc.Lots.Split(' ').Select(i => int.Parse(i)).ToList();
                    foreach (int baseLot in lotIds)
                    {
                        int lot = baseLot;
                        while (true)
                        {
                            // It's also fine to not have a lot defined as long as all key items are found
                            if (!lots.TryGetValue(lot, out PARAM.Row row))
                            {
                                break;
                            }
                            for (int i = 1; i <= 8; i++)
                            {
                                int item = (int)row[$"ItemLotId{i}"].Value;
                                if (item == 0)
                                {
                                    continue;
                                }
                                uint category = (uint)row[$"LotItemCategory0{i}"].Value;
                                if (!Universe.LotTypes.TryGetValue(category, out int catVal))
                                {
                                    continue;
                                }
                                string id = $"{catVal}:{item}";
                                if (opt["debuglots"])
                                {
                                    Console.WriteLine($"lot {lot} in {loc.Area} has {id}");
                                }
                                if (itemsById.TryGetValue(id, out string name))
                                {
                                    setArea(name, areas);
                                }
                            }
                            if (dragonFlag > 0 && (int)row["getItemFlagId"].Value == dragonFlag)
                            {
                                setArea("pathofthedragon", areas);
                            }
                            lot++;
                        }
                    }
                    List <int> shopIds = loc.Shops == null ? new List <int>() : loc.Shops.Split(' ').Select(i => int.Parse(i)).ToList();
                    foreach (int shopId in shopIds)
                    {
                        // Not as fine for a shop to be missing, but also whatever
                        if (!shops.TryGetValue(shopId, out PARAM.Row row))
                        {
                            continue;
                        }
                        int    item   = (int)row["EquipId"].Value;
                        int    catVal = (byte)row["equipType"].Value;
                        string id     = $"{catVal}:{item}";
                        if (opt["debuglots"])
                        {
                            Console.WriteLine($"shop {shopId} in {loc.Area} has {id}");
                        }
                        if (itemsById.TryGetValue(id, out string name))
                        {
                            setArea(name, areas);
                        }
                        if (dragonFlag > 0 && (int)row["EventFlag"].Value == dragonFlag)
                        {
                            setArea("pathofthedragon", areas);
                        }
                    }
                }
            }
            // lots:.*[1-9]\r
            // Iterative approach for items which depend simply on other items
            // Recursion would look a lot nicer but lazy
            bool itemExpanded;

            do
            {
                itemExpanded = false;
                foreach (KeyValuePair <string, List <string> > entry in itemAreas)
                {
                    foreach (string dep in entry.Value.ToList())
                    {
                        if (itemAreas.TryGetValue(dep, out List <string> deps))
                        {
                            entry.Value.Remove(dep);
                            entry.Value.AddRange(deps);
                            itemExpanded = true;
                        }
                    }
                }
            }while (itemExpanded);

            if (opt["explain"] || opt["debuglots"])
            {
                foreach (Item item in ann.KeyItems)
                {
                    Console.WriteLine($"{item.Name} {item.ID}: default {item.Area}, found [{string.Join(", ", itemAreas[item.Name])}]");
                }
            }
            // Collect items in graph
            SortedSet <string> itemRecord = new SortedSet <string>();
            bool randomized = false;

            foreach (Item item in ann.KeyItems)
            {
                if (itemAreas[item.Name].Count == 0)
                {
                    if (item.HasTag("randomonly"))
                    {
                        itemAreas[item.Name] = new List <string> {
                            item.Area
                        };
                    }
                    else if (item.HasTag("hard") && !opt["hard"])
                    {
                        continue;
                    }
                    else
                    {
                        throw new Exception($"Couldn't find {item.Name} in item lots");
                    }
                }
                List <string> areas = itemAreas[item.Name];
                foreach (string area in areas)
                {
                    g.Nodes[area].Items.Add(item.Name);
                }
                if (!item.HasTag("randomonly"))
                {
                    if (areas.Count > 1 || areas[0] != item.Area)
                    {
                        randomized = true;
                    }
                    itemRecord.Add($"{item.Name}={string.Join(",", areas)}");
                }
            }
            return(new Result
            {
                Randomized = randomized,
                ItemHash = (RandomizerOptions.JavaStringHash($"{string.Join(";", itemRecord)}") % 99999).ToString().PadLeft(5, '0')
            });
        }