Updated ore spawning to use better handling for floor ranges and easier to add in more varieties.

This commit is contained in:
JoshuaNavarro 2019-08-13 23:06:51 -07:00
parent 768e09cf43
commit 5cf0211339
9 changed files with 332 additions and 23 deletions

View File

@ -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<IntRange> floorsToSpawnOn;
/// <summary>
/// The list of floors to exclude spawning on in the mine.
/// </summary>
public List<IntRange> floorsToExclude;
/// <summary>
///
/// </summary>
public List<string> 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<IntRange> FloorsToSpawnOn, List<IntRange> 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<IntRange>();
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;
}
/// <summary>
/// Checks to see if the resource can spawn at the given game location.
/// </summary>
/// <param name="Location"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Checks to see if this ore can be spawned on the current mine level.
/// </summary>
/// <returns></returns>
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;
}
}
}

View File

@ -16,14 +16,13 @@ namespace Revitalize.Framework.Objects.InformationFiles
/// The item to drop.
/// </summary>
public Item droppedItem;
/// <summary>
/// The min amount to drop.
/// </summary>
public int minDropAmount;
/// <summary>
/// The max amount to drop.
/// </summary>
public int maxDropAmount;
public int minResourcePerDrop;
public int maxResourcePerDrop;
public int minNumberOfNodesSpawned;
public int maxNumberOfNodesSpawned;
public float spawnLuckFactor;
public float dropLuckFactor;
/// <summary>
/// Empty constructor.
@ -37,13 +36,64 @@ namespace Revitalize.Framework.Objects.InformationFiles
/// Constructor.
/// </summary>
/// <param name="I">The item to drop.</param>
/// <param name="Min">The min amount to drop.</param>
/// <param name="Max">The max amount to drop.</param>
public ResourceInformaton(Item I, int Min, int Max)
/// <param name="MinDropAmount">The min amount to drop.</param>
/// <param name="MaxDropAmount">The max amount to drop.</param>
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;
}
/// <summary>
/// Gets the number of drops to spawn for the given resource;
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// Gets the number of resource nodes to spawn when spawning multiple clusters.
/// </summary>
/// <returns></returns>
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;
}
}
}

View File

@ -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<IntRange>()
{
new IntRange(1,9)
},null,true,true,0,0)));
this.ores.Add("Omegasis.Revitalize.Resources.Ore.Test", testOre);
}
/// <summary>
@ -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
/// <returns></returns>
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<OreVeinObj> spawnableOreVeins = new List<OreVeinObj>();
//Get a list of all of the ores that can spawn on this mine level.
foreach(KeyValuePair<string,OreVeinObj> 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<Vector2> 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<Vector2> openTiles = LocationUtilities.GetOpenObjectTiles(Game1.player.currentLocation, (OreVeinObj)this.ores["Test"].getOne());
List<Vector2> 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)

View File

@ -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()
{

View File

@ -127,7 +127,7 @@ namespace Revitalize.Framework.Objects.Resources.OreVeins
/// </summary>
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);
}
}

View File

@ -0,0 +1,89 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Revitalize.Framework.Utilities
{
/// <summary>
/// A class for dealing with integer value ranges.
/// </summary>
public class IntRange
{
/// <summary>
/// The min value for the range.
/// </summary>
public int min;
/// <summary>
/// The max value for the range.
/// </summary>
public int max;
public IntRange()
{
}
/// <summary>
/// Constructor.
/// </summary>
/// <param name="SingleValue">The single value to be tested on for min and max. Note that this will fail every test except for ContainsInclusive.</param>
public IntRange(int SingleValue)
{
this.min = this.max = SingleValue;
}
/// <summary>
/// Constructor.
/// </summary>
/// <param name="Min">The min value.</param>
/// <param name="Max">The max value.</param>
public IntRange(int Min, int Max)
{
this.min = Min;
this.max = Max;
}
/// <summary>
/// Checks to see if the value is inside the range.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public bool ContainsInclusive(int value)
{
if (value >= this.min && value <= this.max) return true;
else return false;
}
/// <summary>
/// Checks to see if the value is greater/equal than the min but less than the max.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public bool ContainsExclusiveCeil(int value)
{
if (value >= this.min && value < this.max) return true;
else return false;
}
/// <summary>
/// Checks to see if the value is greater than the min and less/equal to the max.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public bool ContainsExclusiveFloor(int value)
{
if (value >= this.min && value < this.max) return true;
else return false;
}
/// <summary>
/// Checks to see if the value is inside of the range but not equal to min or max.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public bool ContainsExclusive(int value)
{
if (value > this.min && value < this.max) return true;
else return false;
}
}
}

View File

@ -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;
}

View File

@ -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));
}
/*

View File

@ -128,6 +128,7 @@
<Compile Include="Framework\Objects\MultiTiledComponent.cs" />
<Compile Include="Framework\Objects\MultiTiledObject.cs" />
<Compile Include="Framework\Objects\ObjectManager.cs" />
<Compile Include="Framework\Objects\InformationFiles\OreResourceInformation.cs" />
<Compile Include="Framework\Objects\ResourceManager.cs" />
<Compile Include="Framework\Objects\Resources\OreVeins\OreVeinObj.cs" />
<Compile Include="Framework\Objects\Resources\OreVeins\OreVeinTile.cs" />
@ -135,6 +136,7 @@
<Compile Include="Framework\Player\Managers\SittingInfo.cs" />
<Compile Include="Framework\Player\PlayerInfo.cs" />
<Compile Include="Framework\Utilities\BoundingBoxInfo.cs" />
<Compile Include="Framework\Utilities\IntRange.cs" />
<Compile Include="Framework\Utilities\InventoryManager.cs" />
<Compile Include="Framework\Utilities\LocationUtilities.cs" />
<Compile Include="Framework\Utilities\PyTKHelper.cs" />