Esempio n. 1
0
        //Adds data to the randomizer dictionaries
        public static void AddEntry(XmlNode node)
        {
            RandomizerEntry entry = new RandomizerEntry(node);

            foreach (RandomizerVar var in entry.entries)
            {
                if (typeof(PlayerData).GetField(var.name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static) == null)
                {
                    return;
                }
            }

            if (!entries.ContainsKey(entry.name))
            {
                entries.Add(entry.name, entry);

                //Build reverse lookup list for quickly finding pickup name from attributes
                for (int i = 0; i < entry.entries.Length; i++)
                {
                    string val = entry.entries[i].value == null ? "" : entry.entries[i].value.ToString();

                    reverseLookup.Add(entry.entries[i].name + val, entry.name);
                }

                for (int i = 0; i < entry.localeNames.Length; i++)
                {
                    if (i != 1 && i != 2)
                    {
                        reverseLookup.Add(entry.localeNames[i], entry.name);
                    }
                }
            }
        }
Esempio n. 2
0
        //Load entry from XML
        //TODO: Add error checking for malformatted XML
        public RandomizerEntry(XmlNode xml)
        {
            this.name = xml.SelectSingleNode("name").InnerText;
            XmlNodeList entriesXml  = xml.SelectSingleNode("vars").ChildNodes;
            XmlNode     requiresXml = xml.SelectSingleNode("requirements");

            this.type = RandomizerEntry.GetTypeFromString(xml.SelectSingleNode("type").InnerText);
            XmlNodeList localesXml = xml.SelectNodes("locales/locale");

            this.entries = new RandomizerVar[entriesXml.Count];
            for (int i = 0; i < entriesXml.Count; i++)
            {
                string value = entriesXml[i].Attributes["value"] == null ? "" : entriesXml[i].Attributes["value"].Value;

                this.entries[i] = new RandomizerVar(entriesXml[i].InnerText, entriesXml[i].Name, value);
            }

            this.reqString = requiresXml.InnerText;

            this.localeNames = new string[localesXml.Count];
            for (int i = 0; i < localesXml.Count; i++)
            {
                this.localeNames[i] = localesXml[i].InnerText;
            }

            GC.Collect();
        }
Esempio n. 3
0
        //Randomization algorithm
        public static void Randomize(System.Random random)
        {
            RandomizerMod.instance.Log("----------------------------------------------------------");
            RandomizerMod.instance.Log("Beginning randomization with seed " + NewGameSettings.seed);
            RandomizerMod.instance.Settings.StringValues.Clear();

            List <RandomizerEntry> unsorted  = new List <RandomizerEntry>();
            List <RandomizerEntry> sorted    = new List <RandomizerEntry>();
            List <RandomizerEntry> reachable = (from entry in entries.Values.AsEnumerable() where (entry.IsReachable(sorted)) select entry).ToList();
            List <RandomizerEntry> replaced  = new List <RandomizerEntry>();

            unsorted.AddRange(entries.Values);

            foreach (RandomizerEntry entry in reachable)
            {
                RandomizerMod.instance.Log("" + entry.name + " is reachable");
            }

            //Loop until we've run out of places to put things at
            while (reachable.Count > 0)
            {
                RandomizerEntry newItem = default(RandomizerEntry);

                //Need to select an item that isn't a dead end if we're almost out of options
                if (reachable.Count == 1 && unsorted.Count > 1)
                {
                    List <RandomizerEntry> candidates = new List <RandomizerEntry>();
                    List <float>           weights    = new List <float>();
                    float totalWeights = 0;
                    foreach (RandomizerEntry entry in unsorted)
                    {
                        int leadCount = entry.LeadsTo(entries.Values.ToList(), sorted, reachable.Union(replaced).ToList()).Count;
                        if (leadCount > 0)
                        {
                            totalWeights += (float)1.0 + Mathf.Log(leadCount);
                            weights.Add(totalWeights);
                            candidates.Add(entry);
                        }
                    }

                    if (candidates.Count > 0)
                    {
                        bool  itemAssigned = false;
                        float weight       = (float)random.NextDouble() * totalWeights;

                        for (int i = 0; i < weights.Count; i++)
                        {
                            if (weight <= weights.ElementAt(i))
                            {
                                newItem      = candidates.ElementAt(i);
                                itemAssigned = true;
                                break;
                            }
                        }

                        if (!itemAssigned)
                        {
                            RandomizerMod.instance.LogWarn("Weighted randomness has failed, picking full random value");
                            newItem = candidates.ElementAt(random.Next(candidates.Count));
                        }
                        RandomizerMod.instance.Log("Running out of options, " + newItem.name + " should prevent hard lock");
                    }
                    else
                    {
                        newItem = unsorted.ElementAt(random.Next(unsorted.Count));
                        RandomizerMod.instance.LogWarn("Running out of options, " + newItem.name + " will probably not help anything");
                    }
                }
                else
                {
                    if (RandomizerMod.instance.Settings.hardMode)
                    {
                        List <RandomizerEntry> candidates = new List <RandomizerEntry>();
                        foreach (RandomizerEntry entry in unsorted)
                        {
                            if (random.Next(100) < 35 || entry.LeadsTo(entries.Values.ToList(), sorted, reachable.Union(replaced).ToList()).Count == 0)
                            {
                                candidates.Add(entry);
                            }
                        }

                        if (candidates.Count > 0)
                        {
                            newItem = candidates.ElementAt(random.Next(candidates.Count));
                        }
                        else
                        {
                            newItem = unsorted.ElementAt(random.Next(unsorted.Count));
                        }
                    }
                    else
                    {
                        newItem = unsorted.ElementAt(random.Next(unsorted.Count));
                    }
                }

                //Update list of items that need to be placed still
                sorted.Add(newItem);
                unsorted.Remove(newItem);

                //Randomly place the chosen item among the reachable elements
                //No need to check requirements, we can assume the new item isn't required for the replace location since it's already reachable
                RandomizerEntry replaceAt = reachable.ElementAt(random.Next(reachable.Count));
                replaced.Add(replaceAt);
                reachable.Remove(replaceAt);

                RandomizerMod.instance.Log("Adding permutation: " + replaceAt.name + " = " + newItem.name);

                RandomizerMod.instance.Settings.StringValues.Add(replaceAt.name, newItem.name);
                reachable.AddRange(GetNewReachableItems(reachable, replaced, sorted));
            }

            //Restart if the algorithm fails
            //Hopefully it never does
            if (unsorted.Count != 0)
            {
                RandomizerMod.instance.LogWarn("Randomization has somehow failed");
                foreach (RandomizerEntry entry in entries.Values.ToList().FindAll(item => !replaced.Contains(item)))
                {
                    RandomizerMod.instance.Log(entry.name + " is unreachable");
                }
                Randomize(new System.Random(random.Next()));
            }
        }
Esempio n. 4
0
        //Override for PlayerData.GetBool
        public static bool GetPlayerDataBool(string name)
        {
            PlayerData pd = PlayerData.instance;

            //Don't run randomizer code in non-randomizer saves
            if (!RandomizerMod.instance.Settings.randomizer)
            {
                return(pd.GetBoolInternal(name));
            }

            if (GameManager.instance.GetSceneNameString() != "RestingGrounds_07" && GameManager.instance.GetSceneNameString() != "RestingGrounds_04")
            {
                if (name == "hasDreamGate" || name == "dreamNailUpgraded" || name == "hasDreamNail")
                {
                    return(pd.GetBoolInternal(name));
                }
            }

            if (string.IsNullOrEmpty(name))
            {
                return(false);
            }

            if (name == "_true")
            {
                return(true);
            }
            else if (name == "_false")
            {
                return(false);
            }
            else if (name == "hasAcidArmour")
            {
                return(GameManager.instance.GetSceneNameString() == "Waterways_13" ? false : PlayerData.instance.hasAcidArmour);
            }

            //Check stack trace to see if player is in a menu
            string stack = new StackTrace().ToString();

            //Split into multiple ifs because this looks horrible otherwise
            //TODO: Cleaner way of checking than stack trace
            if (!stack.Contains("at ShopMenuStock.BuildItemList()"))
            {
                if (stack.Contains("at HutongGames.PlayMaker.Fsm.Start()"))
                {
                    return(pd.GetBoolInternal(name));
                }

                if (name.Contains("gotCharm_") && (stack.Contains("at HutongGames.PlayMaker.Fsm.DoTransition(HutongGames.PlayMaker.FsmTransition transition, Boolean isGlobal)") || InInventory()))
                {
                    return(pd.GetBoolInternal(name));
                }
            }

            string key;
            string key2;

            //Don't run randomizer if bool is not in the loaded data
            if (!reverseLookup.TryGetValue(name, out key) || !RandomizerMod.instance.Settings.StringValues.TryGetValue(key, out key2))
            {
                return(pd.GetBoolInternal(name));
            }
            else
            {
                int             index           = entries[key].GetIndex(name);
                RandomizerEntry randomizerEntry = entries[key2];

                RandomizerVar var;

                //Return the matching bool or the first one if there is no matching index
                if (randomizerEntry.entries.Length > index)
                {
                    var = randomizerEntry.entries[index];
                }
                else
                {
                    var = randomizerEntry.entries[0];
                }

                if (var.type == typeof(bool))
                {
                    return(pd.GetBoolInternal(var.name));
                }
                else
                {
                    if (key2 == "Vengeful Spirit")
                    {
                        return(RandomizerMod.instance.Settings.fireball1);
                    }
                    else if (key2 == "Shade Soul")
                    {
                        return(RandomizerMod.instance.Settings.fireball2);
                    }
                    else if (key2 == "Desolate Dive")
                    {
                        return(RandomizerMod.instance.Settings.quake1);
                    }
                    else if (key2 == "Descending Dark")
                    {
                        return(RandomizerMod.instance.Settings.quake2);
                    }
                    else if (key2 == "Howling Wraiths")
                    {
                        return(RandomizerMod.instance.Settings.scream1);
                    }
                    else if (key2 == "Abyss Shriek")
                    {
                        return(RandomizerMod.instance.Settings.scream2);
                    }
                    return(pd.GetIntInternal(var.name) >= (int)var.value);
                }
            }
        }
Esempio n. 5
0
        public static int GetPlayerDataInt(string name)
        {
            PlayerData pd = PlayerData.instance;

            //Don't run randomizer code in non-randomizer saves
            if (!RandomizerMod.instance.Settings.randomizer)
            {
                if (name.StartsWith("_"))
                {
                    name = name.Substring(1);
                }
                return(pd.GetIntInternal(name));
            }

            if (string.IsNullOrEmpty(name))
            {
                return(0);
            }
            if (name == "_true")
            {
                return(2);
            }
            else if (name == "_fireballLevel")
            {
                return(RandomizerMod.instance.Settings.FireballLevel());
            }
            else if (name == "_quakeLevel")
            {
                return(RandomizerMod.instance.Settings.QuakeLevel());
            }
            else if (name == "_screamLevel")
            {
                return(RandomizerMod.instance.Settings.ScreamLevel());
            }

            string key;
            string key2;

            //Don't run randomizer if int is not in the loaded data
            if (!reverseLookup.TryGetValue(name, out key) || !RandomizerMod.instance.Settings.StringValues.TryGetValue(key, out key2))
            {
                return(pd.GetIntInternal(name));
            }
            else
            {
                int             index           = entries[key].GetIndex(name);
                RandomizerEntry randomizerEntry = entries[key2];

                RandomizerVar var;

                //Return the matching var or the first one if there is no matching index
                if (randomizerEntry.entries.Length > index)
                {
                    var = randomizerEntry.entries[index];
                }
                else
                {
                    var = randomizerEntry.entries[0];
                }

                if (var.type == typeof(bool))
                {
                    return(pd.GetBoolInternal(var.name) ? 2 : 0);
                }
                else
                {
                    if (key2 == "Vengeful Spirit")
                    {
                        return(Convert.ToInt32(RandomizerMod.instance.Settings.fireball1) * 2);
                    }
                    else if (key2 == "Shade Soul")
                    {
                        return(Convert.ToInt32(RandomizerMod.instance.Settings.fireball2) * 2);
                    }
                    else if (key2 == "Desolate Dive")
                    {
                        return(Convert.ToInt32(RandomizerMod.instance.Settings.quake1) * 2);
                    }
                    else if (key2 == "Descending Dark")
                    {
                        return(Convert.ToInt32(RandomizerMod.instance.Settings.quake2) * 2);
                    }
                    else if (key2 == "Howling Wraiths")
                    {
                        return(Convert.ToInt32(RandomizerMod.instance.Settings.scream1) * 2);
                    }
                    else if (key2 == "Abyss Shriek")
                    {
                        return(Convert.ToInt32(RandomizerMod.instance.Settings.scream2) * 2);
                    }

                    return(pd.GetIntInternal(var.name) >= (int)var.value ? 2 : 0);
                }
            }
        }