/// <summary>Calculates the final number of objects to spawn today in the current spawning process, based on config settings and player levels in a relevant skill.</summary>
            /// <param name="min">Minimum number of objects to spawn today (before skill multiplier).</param>
            /// <param name="max">Maximum number of objects to spawn today (before skill multiplier).</param>
            /// <param name="percent">Additive multiplier for each of the player's levels in the relevant skill (e.g. 10 would represent +10% objects per level).</param>
            /// <param name="skill">Enumerator for the skill on which the "percent" additive multiplier is based.</param>
            /// <returns>The final number of objects to spawn today in the current spawning process.</returns>
            public static int AdjustedSpawnCount(int min, int max, int percent, Utility.Skills skill)
            {
                int spawnCount = RNG.Next(min, max + 1); //random number from min to max (higher number is exclusive, so +1 to adjust for it)

                //calculate skill multiplier bonus
                double skillMultiplier = percent;

                skillMultiplier = (skillMultiplier / 100); //converted to percent, e.g. default config is "10" (10% per level) so it converts to "0.1"
                int highestSkillLevel = 0;                 //highest skill level among all existing farmers, not just the host

                foreach (Farmer farmer in Game1.getAllFarmers())
                {
                    highestSkillLevel = Math.Max(highestSkillLevel, farmer.getEffectiveSkillLevel((int)skill)); //record the new level if it's higher than before
                }
                skillMultiplier = 1.0 + (skillMultiplier * highestSkillLevel);                                  //final multiplier; e.g. with default config: "1.0" at level 0, "1.7" at level 7, etc

                //calculate final forage amount
                skillMultiplier *= spawnCount;                             //multiply the initial random spawn count by the skill multiplier
                spawnCount       = (int)skillMultiplier;                   //store the integer portion of the current multiplied value (e.g. this is "1" if the multiplier is "1.7")
                double remainder = skillMultiplier - (int)skillMultiplier; //store the decimal portion of the multiplied value (e.g. this is "0.7" if the multiplier is "1.7")

                if (RNG.NextDouble() < remainder)                          //use remainder as a % chance to spawn one extra object (e.g. if the final count would be "1.7", there's a 70% chance of spawning 2 objects)
                {
                    spawnCount++;
                }

                return(spawnCount);
            }
            /// <summary>Produces a dictionary containing the final, adjusted spawn chance of each object in the provided dictionaries. (Part of the convoluted object spawning process for ore.)</summary>
            /// <param name="skill">The player skill that affects spawn chances (e.g. Mining for ore spawn chances).</param>
            /// <param name="levelRequired">A dictionary of object names and the skill level required to spawn them.</param>
            /// <param name="startChances">A dictionary of object names and their weighted chances to spawn at their lowest required skill level (e.g. chance of spawning stone if you're level 0).</param>
            /// <param name="maxChances">A dictionary of object names and their weighted chances to spawn at skill level 10.</param>
            /// <returns></returns>
            public static Dictionary <string, int> AdjustedSpawnChances(Utility.Skills skill, Dictionary <string, int> levelRequired, Dictionary <string, int> startChances, Dictionary <string, int> maxChances)
            {
                Dictionary <string, int> adjustedChances = new Dictionary <string, int>();

                int skillLevel = 0; //highest skill level among all existing farmers, not just the host

                foreach (Farmer farmer in Game1.getAllFarmers())
                {
                    skillLevel = Math.Max(skillLevel, farmer.getEffectiveSkillLevel((int)skill)); //record the new level if it's higher than before
                }

                foreach (KeyValuePair <string, int> objType in levelRequired)
                {
                    int chance = 0; //chance of spawning this object
                    if (objType.Value > skillLevel)
                    {
                        //skill is too low to spawn this object; leave it at 0%
                    }
                    else if (skillLevel >= 10)
                    {
                        chance = maxChances[objType.Key]; //level 10 skill; use the max level chance
                    }
                    else if (objType.Value == skillLevel)
                    {
                        chance = startChances[objType.Key]; //skill is the minimum required; use the starting chance
                    }
                    else //skill is somewhere in between "starting" and "level 10", so do math to set the chance somewhere in between them (i forgot the term for this kind of averaging, sry)
                    {
                        int  count      = 0;
                        long chanceMath = 0;                     //used in case the chances are very large numbers for some reason
                        for (int x = objType.Value; x < 10; x++) //loop from [minimum skill level for this object] to [max level - 1], for vague math reasons
                        {
                            if (skillLevel > x)
                            {
                                chanceMath += maxChances[objType.Key]; //add level 10 chance
                            }
                            else
                            {
                                chanceMath += startChances[objType.Key]; //add starting chance
                            }
                            count++;
                        }
                        chanceMath = (long)Math.Round((double)chanceMath / (double)count); //divide to get the average
                        chance     = Convert.ToInt32(chanceMath);                          //convert back to a reasonable number range once the math is done
                    }

                    if (chance > 0)                               //don't bother adding any objects with 0% or negative spawn chance
                    {
                        adjustedChances.Add(objType.Key, chance); //add the object name & chance to the list of adjusted chances
                    }
                }

                return(adjustedChances);
            }
예제 #3
0
            /// <summary>Apply any provided non-type-specific settings to a monster.</summary>
            /// <param name="monster">The monster to be customized. This will be modified by reference.</param>
            /// <param name="settings">A dictionary of setting names and values. If null, this method will do nothing.</param>
            /// <param name="areaID">The UniqueAreaID of the related SpawnArea. Required for log messages.</param>
            public static void ApplyMonsterSettings(Monster monster, Dictionary <string, object> settings, string areaID = "")
            {
                if (settings == null) //if no settings were provided
                {
                    return;           //do nothing
                }

                //set max HP
                if (settings.ContainsKey("HP"))
                {
                    monster.MaxHealth = Convert.ToInt32(settings["HP"]);
                }

                //set damage
                if (settings.ContainsKey("Damage"))
                {
                    monster.DamageToFarmer = Convert.ToInt32(settings["Damage"]); //set DamageToFarmer

                    if (monster is ICustomDamage cd)                              //if this monster type uses the custom damage interface
                    {
                        cd.CustomDamage = Convert.ToInt32(settings["Damage"]);    //set CustomDamage as well
                    }
                }

                //set defense
                if (settings.ContainsKey("Defense"))
                {
                    monster.resilience.Value = Convert.ToInt32(settings["Defense"]);
                }

                //set dodge chance
                if (settings.ContainsKey("DodgeChance"))
                {
                    monster.missChance.Value = ((double)Convert.ToInt32(settings["DodgeChance"])) / 100;
                }

                //set experience points
                if (settings.ContainsKey("EXP"))
                {
                    monster.ExperienceGained = Convert.ToInt32(settings["EXP"]);
                }

                //multiply HP and/or damage based on players' highest level in a skill
                if (settings.ContainsKey("RelatedSkill"))
                {
                    //parse the provided skill into an enum
                    Utility.Skills skill = (Utility.Skills)Enum.Parse(typeof(Utility.Skills), ((string)settings["RelatedSkill"]).Trim(), true); //parse while trimming whitespace and ignoring case

                    //multiply HP
                    if (settings.ContainsKey("PercentExtraHPPerSkillLevel"))
                    {
                        //calculate HP multiplier based on skill level
                        double skillMultiplier = Convert.ToInt32(settings["PercentExtraHPPerSkillLevel"]);
                        skillMultiplier = (skillMultiplier / 100); //converted to percent, e.g. "10" (10% per level) converts to "0.1"
                        int highestSkillLevel = 0;                 //highest skill level among all existing farmers, not just the host
                        foreach (Farmer farmer in Game1.getAllFarmers())
                        {
                            highestSkillLevel = Math.Max(highestSkillLevel, farmer.getEffectiveSkillLevel((int)skill)); //record the new level if it's higher than before
                        }
                        skillMultiplier = 1.0 + (skillMultiplier * highestSkillLevel);                                  //final multiplier; e.g. if the setting is "10", this is "1.0" at level 0, "1.7" at level 7, etc

                        //apply the multiplier to the monster's max HP
                        skillMultiplier  *= monster.MaxHealth;                 //multiply the current max HP by the skill multiplier
                        monster.MaxHealth = Math.Max((int)skillMultiplier, 1); //set the monster's new max HP (rounded down to the nearest integer & minimum 1)
                    }

                    //multiply damage
                    if (settings.ContainsKey("PercentExtraDamagePerSkillLevel"))
                    {
                        //calculate damage multiplier based on skill level
                        double skillMultiplier = Convert.ToInt32(settings["PercentExtraDamagePerSkillLevel"]);
                        skillMultiplier = (skillMultiplier / 100); //converted to percent, e.g. "10" (10% per level) converts to "0.1"
                        int highestSkillLevel = 0;                 //highest skill level among all existing farmers, not just the host
                        foreach (Farmer farmer in Game1.getAllFarmers())
                        {
                            highestSkillLevel = Math.Max(highestSkillLevel, farmer.getEffectiveSkillLevel((int)skill)); //record the new level if it's higher than before
                        }
                        skillMultiplier = 1.0 + (skillMultiplier * highestSkillLevel);                                  //final multiplier; e.g. if the setting is "10", this is "1.0" at level 0, "1.7" at level 7, etc

                        //apply the multiplier to the monster's damage
                        skillMultiplier       *= monster.DamageToFarmer;            //multiply the current damage by the skill multiplier
                        monster.DamageToFarmer = Math.Max((int)skillMultiplier, 0); //set the monster's new damage (rounded down to the nearest integer & minimum 0)
                    }

                    //multiply defense
                    if (settings.ContainsKey("PercentExtraDefensePerSkillLevel"))
                    {
                        //calculate defense multiplier based on skill level
                        double skillMultiplier = Convert.ToInt32(settings["PercentExtraDefensePerSkillLevel"]);
                        skillMultiplier = (skillMultiplier / 100); //converted to percent, e.g. "10" (10% per level) converts to "0.1"
                        int highestSkillLevel = 0;                 //highest skill level among all existing farmers, not just the host
                        foreach (Farmer farmer in Game1.getAllFarmers())
                        {
                            highestSkillLevel = Math.Max(highestSkillLevel, farmer.getEffectiveSkillLevel((int)skill)); //record the new level if it's higher than before
                        }
                        skillMultiplier = 1.0 + (skillMultiplier * highestSkillLevel);                                  //final multiplier; e.g. if the setting is "10", this is "1.0" at level 0, "1.7" at level 7, etc

                        //apply the multiplier to the monster's defense
                        skillMultiplier         *= monster.resilience.Value;          //multiply the current damage by the skill multiplier
                        monster.resilience.Value = Math.Max((int)skillMultiplier, 0); //set the monster's new defense (rounded down to the nearest integer & minimum 0)
                    }

                    //multiply dodge chance
                    if (settings.ContainsKey("PercentExtraDodgeChancePerSkillLevel"))
                    {
                        //calculate dodge chance multiplier based on skill level
                        double skillMultiplier = Convert.ToInt32(settings["PercentExtraDodgeChancePerSkillLevel"]);
                        skillMultiplier = (skillMultiplier / 100); //converted to percent, e.g. "10" (10% per level) converts to "0.1"
                        int highestSkillLevel = 0;                 //highest skill level among all existing farmers, not just the host
                        foreach (Farmer farmer in Game1.getAllFarmers())
                        {
                            highestSkillLevel = Math.Max(highestSkillLevel, farmer.getEffectiveSkillLevel((int)skill)); //record the new level if it's higher than before
                        }
                        skillMultiplier = 1.0 + (skillMultiplier * highestSkillLevel);                                  //final multiplier; e.g. if the setting is "10", this is "1.0" at level 0, "1.7" at level 7, etc

                        //apply the multiplier to the monster's dodge chance
                        skillMultiplier         *= monster.missChance.Value;          //multiply the current damage by the skill multiplier
                        monster.missChance.Value = Math.Max((int)skillMultiplier, 0); //set the monster's new dodge chance (rounded down to the nearest integer & minimum 0)
                    }

                    //multiply experience points
                    if (settings.ContainsKey("PercentExtraEXPPerSkillLevel"))
                    {
                        //calculate exp multiplier based on skill level
                        double skillMultiplier = Convert.ToInt32(settings["PercentExtraEXPPerSkillLevel"]);
                        skillMultiplier = (skillMultiplier / 100); //converted to percent, e.g. "10" (10% per level) converts to "0.1"
                        int highestSkillLevel = 0;                 //highest skill level among all existing farmers, not just the host
                        foreach (Farmer farmer in Game1.getAllFarmers())
                        {
                            highestSkillLevel = Math.Max(highestSkillLevel, farmer.getEffectiveSkillLevel((int)skill)); //record the new level if it's higher than before
                        }
                        skillMultiplier = 1.0 + (skillMultiplier * highestSkillLevel);                                  //final multiplier; e.g. if the setting is "10", this is "1.0" at level 0, "1.7" at level 7, etc

                        //apply the multiplier to the monster's exp
                        skillMultiplier         *= monster.ExperienceGained;          //multiply the current exp by the skill multiplier
                        monster.ExperienceGained = Math.Max((int)skillMultiplier, 0); //set the monster's new exp (rounded down to the nearest integer & minimum 0)
                    }
                }

                //set loot (i.e. items dropped on death by the monster)
                if (settings.ContainsKey("Loot"))
                {
                    List <SavedObject> loot = ((JArray)settings["Loot"]).ToObject <List <SavedObject> >(); //cast this list of saved objects (already validated and parsed elsewhere)
                    MonsterTracker.SetLoot(monster, loot);                                                 //set the monster's loot in the monster tracker
                    monster.objectsToDrop.Clear();                                                         //clear any "default" loot the monster might've had
                }

                //set current HP
                //NOTE: do this after any max HP changes, because it may be contingent on max HP)
                if (settings.ContainsKey("CurrentHP"))
                {
                    monster.Health = Convert.ToInt32(settings["CurrentHP"]);
                }
                else //if no current HP setting was provided
                {
                    monster.Health = monster.MaxHealth; //set it to max HP
                }

                //set whether the monster automatically sees players at spawn
                if (settings.ContainsKey("SeesPlayersAtSpawn"))
                {
                    if ((bool)settings["SeesPlayersAtSpawn"]) //if the setting is true (note: supposedly, some monsters behave incorrectly if focusedOnFarmers is set to false)
                    {
                        monster.focusedOnFarmers = true;      //set the monster focus
                    }
                }

                //set sprite
                if (settings.ContainsKey("Sprite"))
                {
                    //replace the monster's sprite, using its existing settings where possible
                    monster.Sprite = new AnimatedSprite((string)settings["Sprite"], monster.Sprite.CurrentFrame, monster.Sprite.SpriteWidth, monster.Sprite.SpriteHeight);
                }
            }
예제 #4
0
            /// <summary>Apply any provided non-type-specific settings to a monster.</summary>
            /// <param name="monster">The monster to be customized. This will be modified by reference.</param>
            /// <param name="settings">A dictionary of setting names and values. If null, this method will do nothing.</param>
            /// <param name="areaID">The UniqueAreaID of the related SpawnArea. Required for log messages.</param>
            public static void ApplyMonsterSettings(Monster monster, Dictionary <string, object> settings, string areaID = "")
            {
                if (settings == null) //if no settings were provided
                {
                    return;           //do nothing
                }

                //set max HP
                if (settings.ContainsKey("HP"))
                {
                    monster.MaxHealth = Convert.ToInt32(settings["HP"]);
                }

                //set damage
                if (settings.ContainsKey("Damage"))
                {
                    monster.DamageToFarmer = Convert.ToInt32(settings["Damage"]); //set DamageToFarmer

                    if (monster is ICustomDamage cd)                              //if this monster type uses the custom damage interface
                    {
                        cd.CustomDamage = Convert.ToInt32(settings["Damage"]);    //set CustomDamage as well
                    }
                }

                //set defense
                if (settings.ContainsKey("Defense"))
                {
                    monster.resilience.Value = Convert.ToInt32(settings["Defense"]);
                }

                //set dodge chance
                if (settings.ContainsKey("DodgeChance"))
                {
                    monster.missChance.Value = ((double)Convert.ToInt32(settings["DodgeChance"])) / 100;
                }

                //set experience points
                if (settings.ContainsKey("EXP"))
                {
                    monster.ExperienceGained = Convert.ToInt32(settings["EXP"]);
                }

                //multiply HP and/or damage based on players' highest level in a skill
                if (settings.ContainsKey("RelatedSkill"))
                {
                    //parse the provided skill into an enum
                    Utility.Skills skill = (Utility.Skills)Enum.Parse(typeof(Utility.Skills), ((string)settings["RelatedSkill"]).Trim(), true); //parse while trimming whitespace and ignoring case

                    //multiply HP
                    if (settings.ContainsKey("PercentExtraHPPerSkillLevel"))
                    {
                        //calculate HP multiplier based on skill level
                        double skillMultiplier = Convert.ToInt32(settings["PercentExtraHPPerSkillLevel"]);
                        skillMultiplier = (skillMultiplier / 100); //converted to percent, e.g. "10" (10% per level) converts to "0.1"
                        int highestSkillLevel = 0;                 //highest skill level among all existing farmers, not just the host
                        foreach (Farmer farmer in Game1.getAllFarmers())
                        {
                            highestSkillLevel = Math.Max(highestSkillLevel, farmer.getEffectiveSkillLevel((int)skill)); //record the new level if it's higher than before
                        }
                        skillMultiplier = 1.0 + (skillMultiplier * highestSkillLevel);                                  //final multiplier; e.g. if the setting is "10", this is "1.0" at level 0, "1.7" at level 7, etc

                        //apply the multiplier to the monster's max HP
                        skillMultiplier  *= monster.MaxHealth;                 //multiply the current max HP by the skill multiplier
                        monster.MaxHealth = Math.Max((int)skillMultiplier, 1); //set the monster's new max HP (rounded down to the nearest integer & minimum 1)
                    }

                    //multiply damage
                    if (settings.ContainsKey("PercentExtraDamagePerSkillLevel"))
                    {
                        //calculate damage multiplier based on skill level
                        double skillMultiplier = Convert.ToInt32(settings["PercentExtraDamagePerSkillLevel"]);
                        skillMultiplier = (skillMultiplier / 100); //converted to percent, e.g. "10" (10% per level) converts to "0.1"
                        int highestSkillLevel = 0;                 //highest skill level among all existing farmers, not just the host
                        foreach (Farmer farmer in Game1.getAllFarmers())
                        {
                            highestSkillLevel = Math.Max(highestSkillLevel, farmer.getEffectiveSkillLevel((int)skill)); //record the new level if it's higher than before
                        }
                        skillMultiplier = 1.0 + (skillMultiplier * highestSkillLevel);                                  //final multiplier; e.g. if the setting is "10", this is "1.0" at level 0, "1.7" at level 7, etc

                        //apply the multiplier to the monster's damage
                        skillMultiplier       *= monster.DamageToFarmer;            //multiply the current damage by the skill multiplier
                        monster.DamageToFarmer = Math.Max((int)skillMultiplier, 0); //set the monster's new damage (rounded down to the nearest integer & minimum 0)
                    }

                    //multiply defense
                    if (settings.ContainsKey("PercentExtraDefensePerSkillLevel"))
                    {
                        //calculate defense multiplier based on skill level
                        double skillMultiplier = Convert.ToInt32(settings["PercentExtraDefensePerSkillLevel"]);
                        skillMultiplier = (skillMultiplier / 100); //converted to percent, e.g. "10" (10% per level) converts to "0.1"
                        int highestSkillLevel = 0;                 //highest skill level among all existing farmers, not just the host
                        foreach (Farmer farmer in Game1.getAllFarmers())
                        {
                            highestSkillLevel = Math.Max(highestSkillLevel, farmer.getEffectiveSkillLevel((int)skill)); //record the new level if it's higher than before
                        }
                        skillMultiplier = 1.0 + (skillMultiplier * highestSkillLevel);                                  //final multiplier; e.g. if the setting is "10", this is "1.0" at level 0, "1.7" at level 7, etc

                        //apply the multiplier to the monster's defense
                        skillMultiplier         *= monster.resilience.Value;          //multiply the current damage by the skill multiplier
                        monster.resilience.Value = Math.Max((int)skillMultiplier, 0); //set the monster's new defense (rounded down to the nearest integer & minimum 0)
                    }

                    //multiply dodge chance
                    if (settings.ContainsKey("PercentExtraDodgeChancePerSkillLevel"))
                    {
                        //calculate dodge chance multiplier based on skill level
                        double skillMultiplier = Convert.ToInt32(settings["PercentExtraDodgeChancePerSkillLevel"]);
                        skillMultiplier = (skillMultiplier / 100); //converted to percent, e.g. "10" (10% per level) converts to "0.1"
                        int highestSkillLevel = 0;                 //highest skill level among all existing farmers, not just the host
                        foreach (Farmer farmer in Game1.getAllFarmers())
                        {
                            highestSkillLevel = Math.Max(highestSkillLevel, farmer.getEffectiveSkillLevel((int)skill)); //record the new level if it's higher than before
                        }
                        skillMultiplier = 1.0 + (skillMultiplier * highestSkillLevel);                                  //final multiplier; e.g. if the setting is "10", this is "1.0" at level 0, "1.7" at level 7, etc

                        //apply the multiplier to the monster's dodge chance
                        skillMultiplier         *= monster.missChance.Value;          //multiply the current damage by the skill multiplier
                        monster.missChance.Value = Math.Max((int)skillMultiplier, 0); //set the monster's new dodge chance (rounded down to the nearest integer & minimum 0)
                    }

                    //multiply experience points
                    if (settings.ContainsKey("PercentExtraEXPPerSkillLevel"))
                    {
                        //calculate exp multiplier based on skill level
                        double skillMultiplier = Convert.ToInt32(settings["PercentExtraEXPPerSkillLevel"]);
                        skillMultiplier = (skillMultiplier / 100); //converted to percent, e.g. "10" (10% per level) converts to "0.1"
                        int highestSkillLevel = 0;                 //highest skill level among all existing farmers, not just the host
                        foreach (Farmer farmer in Game1.getAllFarmers())
                        {
                            highestSkillLevel = Math.Max(highestSkillLevel, farmer.getEffectiveSkillLevel((int)skill)); //record the new level if it's higher than before
                        }
                        skillMultiplier = 1.0 + (skillMultiplier * highestSkillLevel);                                  //final multiplier; e.g. if the setting is "10", this is "1.0" at level 0, "1.7" at level 7, etc

                        //apply the multiplier to the monster's exp
                        skillMultiplier         *= monster.ExperienceGained;          //multiply the current exp by the skill multiplier
                        monster.ExperienceGained = Math.Max((int)skillMultiplier, 0); //set the monster's new exp (rounded down to the nearest integer & minimum 0)
                    }
                }

                //set loot (i.e. items dropped on death by the monster)
                if (settings.ContainsKey("Loot"))
                {
                    List <SavedObject> loot = ((JArray)settings["Loot"]).ToObject <List <SavedObject> >(); //cast this list of saved objects (already validated and parsed elsewhere)
                    MonsterTracker.SetLoot(monster, loot);                                                 //set the monster's loot in the monster tracker
                    monster.objectsToDrop.Clear();                                                         //clear any "default" loot the monster might've had
                }

                //set current HP
                //NOTE: do this after any max HP changes, because it may be contingent on max HP)
                if (settings.ContainsKey("CurrentHP"))
                {
                    monster.Health = Convert.ToInt32(settings["CurrentHP"]);
                }
                else //if no current HP setting was provided
                {
                    monster.Health = monster.MaxHealth; //set it to max HP
                }

                //set whether the monster automatically sees players at spawn
                if (settings.ContainsKey("SeesPlayersAtSpawn"))
                {
                    if ((bool)settings["SeesPlayersAtSpawn"]) //if the setting is true (note: supposedly, some monsters behave incorrectly if focusedOnFarmers is set to false)
                    {
                        monster.focusedOnFarmers = true;      //set the monster focus
                    }
                }

                //set sprite
                if (settings.ContainsKey("Sprite"))
                {
                    //replace the monster's sprite, using its existing settings where possible
                    monster.Sprite = new AnimatedSprite((string)settings["Sprite"], monster.Sprite.CurrentFrame, monster.Sprite.SpriteWidth, monster.Sprite.SpriteHeight);
                }

                //set facing direction
                if (settings.ContainsKey("FacingDirection"))
                {
                    int    facingDirection = 2;
                    string directionString = (string)settings["FacingDirection"]; //get the provided setting
                    switch (directionString.Trim().ToLower())
                    {
                    //get an integer representing the provided direction
                    case "up":
                        facingDirection = 0;
                        break;

                    case "right":
                        facingDirection = 1;
                        break;

                    case "down":
                        facingDirection = 2;
                        break;

                    case "left":
                        facingDirection = 3;
                        break;
                    }
                    monster.faceDirection(facingDirection); //set monster direction
                }

                //set segments
                if (settings.ContainsKey("Segments"))
                {
                    int segments = Convert.ToInt32(settings["Segments"]);

                    if (monster is GreenSlime slime)          //if this monster is a type of slime
                    {
                        segments = Math.Max(0, segments);     //minimum = 0

                        slime.stackedSlimes.Value = segments; //set the number of additional slimes stacked on top of this slime
                    }
                    else if (monster is Serpent serpent)      //if this monster is a type of serpent
                    {
                        if (segments < 2)
                        {
                            segments = 0;                      //minimum 0, but treat 1 as 0 (to avoid potential issues with royal/non-royal serpent distinctions)
                        }
                        serpent.segmentCount.Value = segments; //set the number of additional body segments this serpent has
                    }
                }

                //set sight range
                if (settings.ContainsKey("SightRange"))
                {
                    monster.moveTowardPlayer(Convert.ToInt32(settings["SightRange"])); //set "moveTowardPlayerThreshold" value and "isWalkingTowardPlayer" flag
                }

                //set extra loot
                if (settings.ContainsKey("ExtraLoot"))
                {
                    if (settings["ExtraLoot"] is bool extraLoot && extraLoot == false)      //if this setting is false
                    {
                        monster.modData[HarmonyPatch_ToggleExtraLoot.ModDataKey] = "false"; //flag this in the monster's mod data
                    }
                }
            }