From 5cf021133948fa2287d5264843249853a35d7b37 Mon Sep 17 00:00:00 2001 From: JoshuaNavarro Date: Tue, 13 Aug 2019 23:06:51 -0700 Subject: [PATCH] Updated ore spawning to use better handling for floor ranges and easier to add in more varieties. --- .../OreResourceInformation.cs | 126 ++++++++++++++++++ .../InformationFiles/ResourceInformaton.cs | 76 +++++++++-- .../Framework/Objects/ResourceManager.cs | 42 +++++- .../Objects/Resources/OreVeins/OreVeinObj.cs | 13 ++ .../Objects/Resources/OreVeins/OreVeinTile.cs | 3 +- .../Framework/Utilities/IntRange.cs | 89 +++++++++++++ .../Framework/Utilities/LocationUtilities.cs | 2 +- GeneralMods/Revitalize/ModCore.cs | 2 +- GeneralMods/Revitalize/Revitalize.csproj | 2 + 9 files changed, 332 insertions(+), 23 deletions(-) create mode 100644 GeneralMods/Revitalize/Framework/Objects/InformationFiles/OreResourceInformation.cs create mode 100644 GeneralMods/Revitalize/Framework/Utilities/IntRange.cs diff --git a/GeneralMods/Revitalize/Framework/Objects/InformationFiles/OreResourceInformation.cs b/GeneralMods/Revitalize/Framework/Objects/InformationFiles/OreResourceInformation.cs new file mode 100644 index 00000000..dbac704f --- /dev/null +++ b/GeneralMods/Revitalize/Framework/Objects/InformationFiles/OreResourceInformation.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Revitalize.Framework.Utilities; +using StardewValley; + +namespace Revitalize.Framework.Objects.InformationFiles +{ + public class OreResourceInformation:ResourceInformaton + { + + + + public List floorsToSpawnOn; + /// + /// The list of floors to exclude spawning on in the mine. + /// + public List floorsToExclude; + + /// + /// + /// + public List minesToSpawnIn; + + public bool spawnInRegularMine; + public bool spawnInSkullCavern; + public bool spawnsOnFarm; + public bool spawnsInQuarry; + + public OreResourceInformation() : base() + { + + } + + public OreResourceInformation(Item I, int MinDropAmount, int MaxDropAmount, int MinNumberOfNodes, int MaxNumberOfNodes,bool SpawnsOnFarm, bool SpawnsInQuarry,List FloorsToSpawnOn, List FloorsToExclude,bool SpawnInRegularMine,bool SpawnInSkullCave,float SpawnLuckFactor=0f,float DropLuckFactor=0f) : base(I, MinDropAmount, MaxDropAmount, MinNumberOfNodes, MaxNumberOfNodes,SpawnLuckFactor,DropLuckFactor) + { + this.spawnsOnFarm = SpawnsOnFarm; + this.spawnsInQuarry = SpawnsInQuarry; + this.floorsToSpawnOn = FloorsToSpawnOn; + this.floorsToExclude = FloorsToExclude!=null? FloorsToExclude: new List(); + this.spawnInRegularMine = SpawnInRegularMine; + this.spawnInSkullCavern = SpawnInSkullCave; + } + + public override int getNumberOfDropsToSpawn(bool limitToMax = true) + { + return base.getNumberOfDropsToSpawn(limitToMax); + } + + public override int getNumberOfNodesToSpawn(bool limitToMax = true) + { + return base.getNumberOfNodesToSpawn(limitToMax); + } + + public override bool canSpawnAtLocation() + { + if (this.spawnsOnFarm && Game1.player.currentLocation is StardewValley.Farm) + { + return true; + } + if (this.spawnsInQuarry && Game1.player.currentLocation is StardewValley.Locations.Mountain) + { + return true; + } + if (this.spawnInRegularMine && LocationUtilities.IsPlayerInMine()) + { + return true; + } + if (this.spawnInSkullCavern && LocationUtilities.IsPlayerInSkullCave()) + { + return true; + } + return false; + } + + /// + /// Checks to see if the resource can spawn at the given game location. + /// + /// + /// + public override bool canSpawnAtLocation(GameLocation Location) + { + if(this.spawnsOnFarm && Location is StardewValley.Farm) + { + return true; + } + if(this.spawnsInQuarry && Location is StardewValley.Locations.Mountain) + { + return true; + } + if(this.spawnInRegularMine && LocationUtilities.IsPlayerInMine()) + { + return true; + } + if(this.spawnInSkullCavern && LocationUtilities.IsPlayerInSkullCave()) + { + return true; + } + return false; + } + + /// + /// Checks to see if this ore can be spawned on the current mine level. + /// + /// + public bool canSpawnOnCurrentMineLevel() + { + int level=LocationUtilities.CurrentMineLevel(); + foreach(IntRange range in this.floorsToSpawnOn) + { + if (range.ContainsInclusive(level)) + { + foreach(IntRange exclude in this.floorsToExclude) + { + if (exclude.ContainsInclusive(level)) return false; + } + return true; + } + } + return false; + } + + } +} diff --git a/GeneralMods/Revitalize/Framework/Objects/InformationFiles/ResourceInformaton.cs b/GeneralMods/Revitalize/Framework/Objects/InformationFiles/ResourceInformaton.cs index b3b5cff4..aa832739 100644 --- a/GeneralMods/Revitalize/Framework/Objects/InformationFiles/ResourceInformaton.cs +++ b/GeneralMods/Revitalize/Framework/Objects/InformationFiles/ResourceInformaton.cs @@ -16,14 +16,13 @@ namespace Revitalize.Framework.Objects.InformationFiles /// The item to drop. /// public Item droppedItem; - /// - /// The min amount to drop. - /// - public int minDropAmount; - /// - /// The max amount to drop. - /// - public int maxDropAmount; + + public int minResourcePerDrop; + public int maxResourcePerDrop; + public int minNumberOfNodesSpawned; + public int maxNumberOfNodesSpawned; + public float spawnLuckFactor; + public float dropLuckFactor; /// /// Empty constructor. @@ -37,13 +36,64 @@ namespace Revitalize.Framework.Objects.InformationFiles /// Constructor. /// /// The item to drop. - /// The min amount to drop. - /// The max amount to drop. - public ResourceInformaton(Item I, int Min, int Max) + /// The min amount to drop. + /// The max amount to drop. + public ResourceInformaton(Item I, int MinDropAmount, int MaxDropAmount, int MinNumberOfNodes, int MaxNumberOfNodes, float SpawnLuckFactor = 0f, float DropLuckFactor=0f) { this.droppedItem = I; - this.minDropAmount = Min; - this.maxDropAmount = Max; + this.minResourcePerDrop = MinDropAmount; + this.maxResourcePerDrop = MaxDropAmount; + this.minNumberOfNodesSpawned = MinNumberOfNodes; + this.maxNumberOfNodesSpawned = MaxNumberOfNodes; + this.spawnLuckFactor = SpawnLuckFactor; + this.dropLuckFactor = DropLuckFactor; + } + + + /// + /// Gets the number of drops to spawn for the given resource; + /// + /// + public virtual int getNumberOfDropsToSpawn(bool limitToMax = true) + { + int amount = Game1.random.Next(this.minResourcePerDrop, this.maxResourcePerDrop + 1); + + if (limitToMax) + { + amount = (int)Math.Min(amount + (this.dropLuckFactor * (Game1.player.LuckLevel + Game1.player.addedLuckLevel.Value)), this.maxResourcePerDrop); + } + else + { + amount = (int)(amount + (this.dropLuckFactor * (Game1.player.LuckLevel + Game1.player.addedLuckLevel.Value))); + } + return amount; + } + + /// + /// Gets the number of resource nodes to spawn when spawning multiple clusters. + /// + /// + public virtual int getNumberOfNodesToSpawn(bool limitToMax = true) + { + int amount = Game1.random.Next(this.minNumberOfNodesSpawned, this.maxNumberOfNodesSpawned + 1); + if (limitToMax) + { + amount = (int)Math.Min(amount + (this.spawnLuckFactor * (Game1.player.LuckLevel + Game1.player.addedLuckLevel.Value)), this.maxNumberOfNodesSpawned); + } + else + { + amount = (int)(amount + (this.spawnLuckFactor * (Game1.player.LuckLevel + Game1.player.addedLuckLevel.Value))); + } + return amount; + } + + public virtual bool canSpawnAtLocation() + { + return true; + } + public virtual bool canSpawnAtLocation(GameLocation location) + { + return true; } } } diff --git a/GeneralMods/Revitalize/Framework/Objects/ResourceManager.cs b/GeneralMods/Revitalize/Framework/Objects/ResourceManager.cs index bcd10b3e..99653b20 100644 --- a/GeneralMods/Revitalize/Framework/Objects/ResourceManager.cs +++ b/GeneralMods/Revitalize/Framework/Objects/ResourceManager.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.Xna.Framework; +using Revitalize.Framework.Objects.InformationFiles; using Revitalize.Framework.Objects.Resources.OreVeins; using Revitalize.Framework.Utilities; using StardewValley; @@ -43,8 +44,11 @@ namespace Revitalize.Framework.Objects OreVeinObj testOre = new OreVeinObj(PyTKHelper.CreateOBJData("Omegasis.Revitalize.Resources.Ore.Test", TextureManager.GetTexture(ModCore.Manifest, "Resources.Ore", "Test"), typeof(OreVeinTile), Color.White), new BasicItemInformation("Test Ore Vein", "Omegasis.Revitalize.Resources.Ore.Test", "A ore vein that is used for testing purposes.", "Revitalize.Ore", Color.Black, -300, 0, false, 350, Vector2.Zero, true, true, TextureManager.GetTexture(ModCore.Manifest, "Resources.Ore", "Test"), new AnimationManager(TextureManager.GetExtendedTexture(ModCore.Manifest, "Resources.Ore", "Test"), new Animation(0, 0, 16, 16)), Color.White, false, null, null)); - testOre.addComponent(new Vector2(0, 0), new OreVeinTile(PyTKHelper.CreateOBJData("Omegasis.Revitalize.Resources.Ore.Test", TextureManager.GetTexture(ModCore.Manifest, "Resources.Ore", "Test"), typeof(OreVeinTile), Color.White), new BasicItemInformation("Test Ore Vein", "Omegasis.Revitalize.Resources.Ore.Test", "A ore vein that is used for testing purposes.", "Revitalize.Ore", Color.Black, -300, 0, false, 350, Vector2.Zero, true, true, TextureManager.GetTexture(ModCore.Manifest, "Resources.Ore", "Test"), new AnimationManager(TextureManager.GetExtendedTexture(ModCore.Manifest, "Resources.Ore", "Test"), new Animation(0, 0, 16, 16)), Color.White, false, null, null), new InformationFiles.ResourceInformaton(new StardewValley.Object(211, 1), 1, 10))); - this.ores.Add("Test",testOre); + testOre.addComponent(new Vector2(0, 0), new OreVeinTile(PyTKHelper.CreateOBJData("Omegasis.Revitalize.Resources.Ore.Test", TextureManager.GetTexture(ModCore.Manifest, "Resources.Ore", "Test"), typeof(OreVeinTile), Color.White), new BasicItemInformation("Test Ore Vein", "Omegasis.Revitalize.Resources.Ore.Test", "A ore vein that is used for testing purposes.", "Revitalize.Ore", Color.Black, -300, 0, false, 350, Vector2.Zero, true, true, TextureManager.GetTexture(ModCore.Manifest, "Resources.Ore", "Test"), new AnimationManager(TextureManager.GetExtendedTexture(ModCore.Manifest, "Resources.Ore", "Test"), new Animation(0, 0, 16, 16)), Color.White, false, null, null), new InformationFiles.OreResourceInformation(new StardewValley.Object(211, 1), 1, 10,1,20,false,false,new List() + { + new IntRange(1,9) + },null,true,true,0,0))); + this.ores.Add("Omegasis.Revitalize.Resources.Ore.Test", testOre); } /// @@ -65,7 +69,6 @@ namespace Revitalize.Framework.Objects { //ModCore.log("Location is: " + Location.Name); spawn.placementAction(Location, (int)TilePosition.X*Game1.tileSize, (int)TilePosition.Y*Game1.tileSize,Game1.player); - ModCore.log("This works!"); } else { @@ -101,7 +104,7 @@ namespace Revitalize.Framework.Objects /// public bool canResourceBeSpawnedHere(MultiTiledObject OBJ,GameLocation Location, Vector2 TilePosition) { - return OBJ.canBePlacedHere(Location, TilePosition); + return OBJ.canBePlacedHere(Location, TilePosition) && Location.isTileLocationTotallyClearAndPlaceable(TilePosition); } @@ -113,18 +116,43 @@ namespace Revitalize.Framework.Objects public void spawnOreInMine() { int floorLevel = LocationUtilities.CurrentMineLevel(); + + List spawnableOreVeins = new List(); + //Get a list of all of the ores that can spawn on this mine level. + foreach(KeyValuePair pair in this.ores) + { + if (pair.Value.resourceInfo.canSpawnAtLocation() && (pair.Value.resourceInfo as OreResourceInformation).canSpawnOnCurrentMineLevel()) + { + spawnableOreVeins.Add(pair.Value); + } + } + + foreach(OreVeinObj ore in spawnableOreVeins) + { + int amount = ore.resourceInfo.getNumberOfNodesToSpawn(); + List openTiles = LocationUtilities.GetOpenObjectTiles(Game1.player.currentLocation, (OreVeinObj)ore.getOne()); + for (int i = 0; i < amount; i++) + { + int position = Game1.random.Next(openTiles.Count); + this.spawnOreVein(ore.info.id, openTiles[position]); + } + ModCore.log("Spawned :" + amount + " pancake test ores!"); + } + + /* if(floorLevel>=1 && floorLevel <= 9) { int amount = Game1.random.Next(1, 10); //Change this to be a frequency table or something. - List openTiles = LocationUtilities.GetOpenObjectTiles(Game1.player.currentLocation, (OreVeinObj)this.ores["Test"].getOne()); + List openTiles = LocationUtilities.GetOpenObjectTiles(Game1.player.currentLocation, (OreVeinObj)this.ores["Omegasis.Revitalize.Resources.Ore.Test"].getOne()); for(int i = 0; i <= amount; i++) { int position = Game1.random.Next(openTiles.Count); - this.spawnOreVein("Test", openTiles[position]); + this.spawnOreVein("Omegasis.Revitalize.Resources.Ore.Test", openTiles[position]); } - ModCore.log("Spawned :" + amount + " pancake test ores!"); + } + */ } public void OnPlayerLocationChanged(object o,EventArgs playerWarped) diff --git a/GeneralMods/Revitalize/Framework/Objects/Resources/OreVeins/OreVeinObj.cs b/GeneralMods/Revitalize/Framework/Objects/Resources/OreVeins/OreVeinObj.cs index 59d74088..55c0d4dc 100644 --- a/GeneralMods/Revitalize/Framework/Objects/Resources/OreVeins/OreVeinObj.cs +++ b/GeneralMods/Revitalize/Framework/Objects/Resources/OreVeins/OreVeinObj.cs @@ -6,12 +6,25 @@ using System.Threading.Tasks; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using PyTK.CustomElementHandler; +using Revitalize.Framework.Objects.InformationFiles; using StardewValley; namespace Revitalize.Framework.Objects.Resources.OreVeins { public class OreVeinObj:MultiTiledObject { + public ResourceInformaton resourceInfo + { + get + { + foreach(OreVeinTile ore in this.objects.Values) + { + return ore.resourceInfo; + } + return null; + } + } + public OreVeinObj() : base() { diff --git a/GeneralMods/Revitalize/Framework/Objects/Resources/OreVeins/OreVeinTile.cs b/GeneralMods/Revitalize/Framework/Objects/Resources/OreVeins/OreVeinTile.cs index d4c3e09a..5fc24f2b 100644 --- a/GeneralMods/Revitalize/Framework/Objects/Resources/OreVeins/OreVeinTile.cs +++ b/GeneralMods/Revitalize/Framework/Objects/Resources/OreVeins/OreVeinTile.cs @@ -127,7 +127,7 @@ namespace Revitalize.Framework.Objects.Resources.OreVeins /// public void destoryVein() { - int amount = Game1.random.Next(this.resourceInfo.minDropAmount, this.resourceInfo.maxDropAmount); + int amount = Game1.random.Next(this.resourceInfo.minResourcePerDrop, this.resourceInfo.maxResourcePerDrop); Item newItem = this.resourceInfo.droppedItem.getOne(); for(int i = 0; i < amount; i++) { @@ -137,6 +137,7 @@ namespace Revitalize.Framework.Objects.Resources.OreVeins { this.location.playSound("stoneCrack"); this.location.removeObject(this.TileLocation, false); + this.containerObject.removeComponent(this.offsetKey); } } diff --git a/GeneralMods/Revitalize/Framework/Utilities/IntRange.cs b/GeneralMods/Revitalize/Framework/Utilities/IntRange.cs new file mode 100644 index 00000000..e425e2df --- /dev/null +++ b/GeneralMods/Revitalize/Framework/Utilities/IntRange.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Revitalize.Framework.Utilities +{ + /// + /// A class for dealing with integer value ranges. + /// + public class IntRange + { + /// + /// The min value for the range. + /// + public int min; + /// + /// The max value for the range. + /// + public int max; + + public IntRange() + { + + } + /// + /// Constructor. + /// + /// The single value to be tested on for min and max. Note that this will fail every test except for ContainsInclusive. + public IntRange(int SingleValue) + { + this.min = this.max = SingleValue; + } + + /// + /// Constructor. + /// + /// The min value. + /// The max value. + public IntRange(int Min, int Max) + { + this.min = Min; + this.max = Max; + } + + /// + /// Checks to see if the value is inside the range. + /// + /// + /// + public bool ContainsInclusive(int value) + { + if (value >= this.min && value <= this.max) return true; + else return false; + } + + /// + /// Checks to see if the value is greater/equal than the min but less than the max. + /// + /// + /// + public bool ContainsExclusiveCeil(int value) + { + if (value >= this.min && value < this.max) return true; + else return false; + } + /// + /// Checks to see if the value is greater than the min and less/equal to the max. + /// + /// + /// + public bool ContainsExclusiveFloor(int value) + { + if (value >= this.min && value < this.max) return true; + else return false; + } + /// + /// Checks to see if the value is inside of the range but not equal to min or max. + /// + /// + /// + public bool ContainsExclusive(int value) + { + if (value > this.min && value < this.max) return true; + else return false; + } + } +} diff --git a/GeneralMods/Revitalize/Framework/Utilities/LocationUtilities.cs b/GeneralMods/Revitalize/Framework/Utilities/LocationUtilities.cs index a1133c33..12c1fc0b 100644 --- a/GeneralMods/Revitalize/Framework/Utilities/LocationUtilities.cs +++ b/GeneralMods/Revitalize/Framework/Utilities/LocationUtilities.cs @@ -60,7 +60,7 @@ namespace Revitalize.Framework.Utilities public static Vector2 GetLocationTileDimensions(GameLocation location) { Vector2 dimensions = new Vector2(location.Map.GetLayer("Back").LayerWidth, location.Map.GetLayer("Back").LayerHeight); - ModCore.log("Dimensions of map is: " + dimensions); + //ModCore.log("Dimensions of map is: " + dimensions); return dimensions; } diff --git a/GeneralMods/Revitalize/ModCore.cs b/GeneralMods/Revitalize/ModCore.cs index aa1326c6..de492af2 100644 --- a/GeneralMods/Revitalize/ModCore.cs +++ b/GeneralMods/Revitalize/ModCore.cs @@ -386,7 +386,7 @@ namespace Revitalize */ //Game1.player.addItemToInventory(ObjectManager.resources.ores["Test"].getOne()); - ObjectManager.resources.spawnOreVein("Test", new Vector2(8, 7)); + ObjectManager.resources.spawnOreVein("Omegasis.Revitalize.Resources.Ore.Test", new Vector2(8, 7)); } /* diff --git a/GeneralMods/Revitalize/Revitalize.csproj b/GeneralMods/Revitalize/Revitalize.csproj index 9c7ea4fe..42d5a3d7 100644 --- a/GeneralMods/Revitalize/Revitalize.csproj +++ b/GeneralMods/Revitalize/Revitalize.csproj @@ -128,6 +128,7 @@ + @@ -135,6 +136,7 @@ +