diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..2c61027
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+# always normalise line endings
+* text=auto
diff --git a/DeluxeGrabber.sln b/DeluxeGrabber.sln
index b56f252..5016e5b 100644
--- a/DeluxeGrabber.sln
+++ b/DeluxeGrabber.sln
@@ -1,26 +1,27 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.27703.2035
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29123.88
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeluxeGrabber", "DeluxeGrabber\DeluxeGrabber.csproj", "{46A2FEC7-F9EB-4A12-A43F-92906F884961}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "root", "root", "{EDB8B326-C681-41B3-ACA6-653A156FAD38}"
+ ProjectSection(SolutionItems) = preProject
+ .gitattributes = .gitattributes
+ .gitignore = .gitignore
+ LICENSE = LICENSE
+ EndProjectSection
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeluxeGrabber", "DeluxeGrabber\DeluxeGrabber.csproj", "{58E63D8A-EB9B-4488-A191-61F66229A5BE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
Debug|x86 = Debug|x86
- Release|Any CPU = Release|Any CPU
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {46A2FEC7-F9EB-4A12-A43F-92906F884961}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {46A2FEC7-F9EB-4A12-A43F-92906F884961}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {46A2FEC7-F9EB-4A12-A43F-92906F884961}.Debug|x86.ActiveCfg = Debug|x86
- {46A2FEC7-F9EB-4A12-A43F-92906F884961}.Debug|x86.Build.0 = Debug|x86
- {46A2FEC7-F9EB-4A12-A43F-92906F884961}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {46A2FEC7-F9EB-4A12-A43F-92906F884961}.Release|Any CPU.Build.0 = Release|Any CPU
- {46A2FEC7-F9EB-4A12-A43F-92906F884961}.Release|x86.ActiveCfg = Release|x86
- {46A2FEC7-F9EB-4A12-A43F-92906F884961}.Release|x86.Build.0 = Release|x86
+ {58E63D8A-EB9B-4488-A191-61F66229A5BE}.Debug|x86.ActiveCfg = Debug|x86
+ {58E63D8A-EB9B-4488-A191-61F66229A5BE}.Debug|x86.Build.0 = Debug|x86
+ {58E63D8A-EB9B-4488-A191-61F66229A5BE}.Release|x86.ActiveCfg = Release|x86
+ {58E63D8A-EB9B-4488-A191-61F66229A5BE}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/DeluxeGrabber/DeluxeGrabber.csproj b/DeluxeGrabber/DeluxeGrabber.csproj
index 0f44f8d..586bc04 100644
--- a/DeluxeGrabber/DeluxeGrabber.csproj
+++ b/DeluxeGrabber/DeluxeGrabber.csproj
@@ -1,83 +1,16 @@
-
-
-
+
+
- Debug
- AnyCPU
- {46A2FEC7-F9EB-4A12-A43F-92906F884961}
- Library
- Properties
- DeluxeGrabber
DeluxeGrabber
- v4.5
- 512
-
-
-
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
- true
- bin\x86\Debug\
- DEBUG;TRACE
- full
- x86
- prompt
- MinimumRecommendedRules.ruleset
-
-
- bin\x86\Release\
- TRACE
- true
- pdbonly
+ DeluxeGrabber
+ 2.5.1
+ net452
+ x86
x86
- prompt
- MinimumRecommendedRules.ruleset
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
- This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
-
-
-
\ No newline at end of file
+
+
diff --git a/DeluxeGrabber/ModAPI.cs b/DeluxeGrabber/ModAPI.cs
index 8717ac6..cfc8165 100644
--- a/DeluxeGrabber/ModAPI.cs
+++ b/DeluxeGrabber/ModAPI.cs
@@ -2,9 +2,10 @@
using System.Collections.Generic;
namespace DeluxeGrabber {
- public class PrismaticAPI {
- private ModConfig config = new ModConfig();
- public int GrabberRange { get { return config.GrabberRange; } }
+ public class ModAPI {
+ private readonly ModConfig Config;
+
+ public int GrabberRange { get { return this.Config.GrabberRange; } }
public IEnumerable GetGrabberCoverage(Vector2 origin) {
for (int x = -GrabberRange; x <= GrabberRange; x++) {
@@ -13,5 +14,9 @@ public IEnumerable GetGrabberCoverage(Vector2 origin) {
}
}
}
+
+ internal ModAPI(ModConfig config) {
+ this.Config = config;
+ }
}
}
diff --git a/DeluxeGrabber/ModEntry.cs b/DeluxeGrabber/ModEntry.cs
index 08e7c86..5968f9c 100644
--- a/DeluxeGrabber/ModEntry.cs
+++ b/DeluxeGrabber/ModEntry.cs
@@ -7,6 +7,7 @@
using StardewValley.Objects;
using StardewValley.TerrainFeatures;
using System.Collections.Generic;
+using SObject = StardewValley.Object;
namespace DeluxeGrabber
{
@@ -17,6 +18,8 @@ public class ModEntry : Mod {
private readonly int FARMING = 0;
private readonly int FORAGING = 2;
+ /// The mod entry point, called after the mod is first loaded.
+ /// Provides simplified APIs for writing mods.
public override void Entry(IModHelper helper) {
Config = Helper.ReadConfig();
@@ -24,8 +27,14 @@ public override void Entry(IModHelper helper) {
Helper.ConsoleCommands.Add("printLocation", "Print current map and tile location", PrintLocation);
Helper.ConsoleCommands.Add("setForagerLocation", "Set current location as global grabber location", SetForagerLocation);
- TimeEvents.AfterDayStarted += TimeEvents_AfterDayStarted;
- LocationEvents.ObjectsChanged += LocationEvents_ObjectsChanged;
+ helper.Events.GameLoop.DayStarted += OnDayStarted;
+ helper.Events.World.ObjectListChanged += OnObjectListChanged;
+ }
+
+ /// Get an API that other mods can access. This is always called after .
+ public override object GetApi()
+ {
+ return new ModAPI(this.Config);
}
private void SetForagerLocation(string arg1, string[] arg2) {
@@ -46,36 +55,42 @@ private void PrintLocation(string arg1, string[] arg2) {
Monitor.Log($"Tile: {Game1.player.getTileLocation()}");
}
- private void LocationEvents_ObjectsChanged(object sender, EventArgsLocationObjectsChanged e) {
+ /// Raised after objects are added or removed in a location.
+ /// The event sender.
+ /// The event data.
+ private void OnObjectListChanged(object sender, ObjectListChangedEventArgs e) {
if (!Config.DoHarvestTruffles) {
return;
}
- GameLocation foragerMap;
- foragerMap = Game1.getLocationFromName(Config.GlobalForageMap);
+ GameLocation foragerMap = Game1.getLocationFromName(Config.GlobalForageMap);
if (foragerMap == null) {
return;
}
- foragerMap.Objects.TryGetValue(new Vector2(Config.GlobalForageTileX, Config.GlobalForageTileY), out Object grabber);
+ foragerMap.Objects.TryGetValue(new Vector2(Config.GlobalForageTileX, Config.GlobalForageTileY), out SObject grabber);
if (grabber == null || !grabber.Name.Contains("Grabber")) {
return;
}
-
+
System.Random random = new System.Random();
- foreach (KeyValuePair pair in e.Added) {
+ foreach (KeyValuePair pair in e.Added) {
if (pair.Value.ParentSheetIndex != 430 || pair.Value.bigCraftable.Value) {
continue;
}
- if ((grabber.heldObject.Value as Chest).items.Count >= 36) {
+ if ((grabber.heldObject.Value as Chest).items.CountIgnoreNull() >= (grabber.heldObject.Value as Chest).GetActualCapacity()) {
+ return;
+ }
+
+ if (pair.Value.ParentSheetIndex == 73) { //Ignore Golden Walnuts
return;
}
- Object obj = pair.Value;
+ SObject obj = pair.Value;
if (obj.Stack == 0) {
obj.Stack = 1;
}
@@ -84,15 +99,15 @@ private void LocationEvents_ObjectsChanged(object sender, EventArgsLocationObjec
continue;
}
- if (Game1.player.professions.Contains(16)) {
- obj.Quality = 4;
+ if (Game1.player.professions.Contains(Farmer.botanist)) {
+ obj.Quality = SObject.bestQuality;
} else if (random.NextDouble() < Game1.player.ForagingLevel / 30.0) {
- obj.Quality = 2;
+ obj.Quality = SObject.highQuality;
} else if (random.NextDouble() < Game1.player.ForagingLevel / 15.0) {
- obj.Quality = 1;
+ obj.Quality = SObject.medQuality;
}
- if (Game1.player.professions.Contains(13)) {
+ if (Game1.player.professions.Contains(Farmer.gatherer)) {
while (random.NextDouble() < 0.2) {
obj.Stack += 1;
}
@@ -107,12 +122,15 @@ private void LocationEvents_ObjectsChanged(object sender, EventArgsLocationObjec
}
}
- if ((grabber.heldObject.Value as Chest).items.Count > 0) {
+ if ((grabber.heldObject.Value as Chest).items.CountIgnoreNull() > 0) {
grabber.showNextIndex.Value = true;
}
}
- private void TimeEvents_AfterDayStarted(object sender, System.EventArgs e) {
+ /// Raised after the game begins a new day (including when the player loads a save).
+ /// The event sender.
+ /// The event data.
+ private void OnDayStarted(object sender, DayStartedEventArgs e) {
AutograbBuildings();
AutograbCrops();
@@ -120,7 +138,7 @@ private void TimeEvents_AfterDayStarted(object sender, System.EventArgs e) {
}
private void AutograbBuildings() {
- Object grabber = null; // stores a reference to the autograbber
+ SObject grabber = null; // stores a reference to the autograbber
List grabbables = new List(); // stores a list of all items which can be grabbed
Dictionary itemsAdded = new Dictionary();
GameLocation location;
@@ -139,7 +157,7 @@ private void AutograbBuildings() {
if (location != null) {
// populate list of objects which are grabbable, and find an autograbber
- foreach (KeyValuePair pair in location.Objects.Pairs) {
+ foreach (KeyValuePair pair in location.Objects.Pairs) {
if (pair.Value.Name.Contains("Grabber")) {
Monitor.Log($" Grabber found at {pair.Key}", LogLevel.Trace);
grabber = pair.Value;
@@ -159,7 +177,7 @@ private void AutograbBuildings() {
bool full = false;
foreach (Vector2 tile in grabbables) {
- if ((grabber.heldObject.Value as Chest).items.Count >= 36) {
+ if ((grabber.heldObject.Value as Chest).items.CountIgnoreNull() >= (grabber.heldObject.Value as Chest).GetActualCapacity()) {
Monitor.Log($" Grabber is full", LogLevel.Trace);
full = true;
break;
@@ -203,7 +221,7 @@ private void AutograbBuildings() {
}
// update sprite if grabber has items in it
- if (grabber != null && (grabber.heldObject.Value as Chest).items.Count > 0) {
+ if (grabber != null && (grabber.heldObject.Value as Chest).items.CountIgnoreNull() > 0) {
grabber.showNextIndex.Value = true;
}
}
@@ -217,19 +235,19 @@ private void AutograbCrops() {
int range = Config.GrabberRange;
foreach (GameLocation location in Game1.locations) {
- foreach (KeyValuePair pair in location.Objects.Pairs) {
+ foreach (KeyValuePair pair in location.Objects.Pairs) {
if (pair.Value.Name.Contains("Grabber")) {
- Object grabber = pair.Value;
- if ((grabber.heldObject.Value == null) || (grabber.heldObject.Value as Chest).items.Count >= 36) {
+ SObject grabber = pair.Value;
+ if ((grabber.heldObject.Value == null) || (grabber.heldObject.Value as Chest).items.CountIgnoreNull() >= (grabber.heldObject.Value as Chest).GetActualCapacity()) {
continue;
}
- bool full = (grabber.heldObject.Value as Chest).items.Count >= 36;
+ bool full = (grabber.heldObject.Value as Chest).items.CountIgnoreNull() >= (grabber.heldObject.Value as Chest).GetActualCapacity();
for (int x = (int)pair.Key.X - range; x < pair.Key.X + range + 1; x ++) {
for (int y = (int)pair.Key.Y - range; y < pair.Key.Y + range + 1 && !full; y++) {
Vector2 tile = new Vector2(x, y);
if (location.terrainFeatures.ContainsKey(tile) && location.terrainFeatures[tile] is HoeDirt dirt)
{
- Object harvest = GetHarvest(dirt, tile, location);
+ SObject harvest = GetHarvest(dirt, tile, location);
if (harvest != null)
{
(grabber.heldObject.Value as Chest).addItem(harvest);
@@ -241,7 +259,7 @@ private void AutograbCrops() {
}
else if (location.Objects.ContainsKey(tile) && location.Objects[tile] is IndoorPot pot)
{
- Object harvest = GetHarvest(pot.hoeDirt.Value, tile, location);
+ SObject harvest = GetHarvest(pot.hoeDirt.Value, tile, location);
if (harvest != null)
{
(grabber.heldObject.Value as Chest).addItem(harvest);
@@ -253,7 +271,7 @@ private void AutograbCrops() {
}
else if (location.terrainFeatures.ContainsKey(tile) && location.terrainFeatures[tile] is FruitTree fruitTree)
{
- Object fruit = GetFruit(fruitTree, tile, location);
+ SObject fruit = GetFruit(fruitTree, tile, location);
if (fruit != null)
{
(grabber.heldObject.Value as Chest).addItem(fruit);
@@ -263,10 +281,10 @@ private void AutograbCrops() {
}
}
}
- full = (grabber.heldObject.Value as Chest).items.Count >= 36;
+ full = (grabber.heldObject.Value as Chest).items.CountIgnoreNull() >= (grabber.heldObject.Value as Chest).GetActualCapacity();
}
}
- if (grabber != null && (grabber.heldObject.Value as Chest).items.Count > 0) {
+ if (grabber != null && (grabber.heldObject.Value as Chest).items.CountIgnoreNull() > 0) {
grabber.showNextIndex.Value = true;
}
}
@@ -274,10 +292,10 @@ private void AutograbCrops() {
}
}
- private Object GetHarvest(HoeDirt dirt, Vector2 tile, GameLocation location) {
+ private SObject GetHarvest(HoeDirt dirt, Vector2 tile, GameLocation location) {
Crop crop = dirt.crop;
- Object harvest;
+ SObject harvest;
int stack = 0;
if (crop is null) {
@@ -285,7 +303,7 @@ private Object GetHarvest(HoeDirt dirt, Vector2 tile, GameLocation location) {
}
if (!Config.DoHarvestFlowers) {
- switch(crop.indexOfHarvest.Value) {
+ switch (crop.indexOfHarvest.Value) {
case 421: return null; // sunflower
case 593: return null; // summer spangle
case 595: return null; // fairy rose
@@ -295,7 +313,8 @@ private Object GetHarvest(HoeDirt dirt, Vector2 tile, GameLocation location) {
}
}
- if (crop != null && crop.currentPhase.Value >= crop.phaseDays.Count - 1 && (!crop.fullyGrown.Value || crop.dayOfCurrentPhase.Value <= 0)) {
+ //Ignore Golden Walnuts even if they spawn on crops
+ if (crop != null && crop.indexOfHarvest.Value != 73 && crop.currentPhase.Value >= crop.phaseDays.Count - 1 && (!crop.fullyGrown.Value || crop.dayOfCurrentPhase.Value <= 0)) {
int num1 = 1;
int num2 = 0;
int num3 = 0;
@@ -317,7 +336,7 @@ private Object GetHarvest(HoeDirt dirt, Vector2 tile, GameLocation location) {
else if (random.NextDouble() < num5)
num2 = 1;
if ((crop.minHarvest.Value) > 1 || (crop.maxHarvest.Value) > 1)
- num1 = random.Next(crop.minHarvest.Value, System.Math.Min(crop.minHarvest.Value + 1, crop.maxHarvest.Value + 1 + Game1.player.FarmingLevel / crop.maxHarvestIncreasePerFarmingLevel.Value));
+ num1 = random.Next(crop.minHarvest.Value, System.Math.Min(crop.maxHarvest.Value + 1, crop.minHarvest.Value + 1 + ( Game1.player.FarmingLevel / (crop.maxHarvestIncreasePerFarmingLevel.Value > 0 ? crop.maxHarvestIncreasePerFarmingLevel.Value : 1 ) ))); //Updated: This will return from 1 to the max possible harvest, depending on the farmer level
if (crop.chanceForExtraCrops.Value > 0.0) {
while (random.NextDouble() < System.Math.Min(0.9, crop.chanceForExtraCrops.Value))
++num1;
@@ -332,10 +351,10 @@ private Object GetHarvest(HoeDirt dirt, Vector2 tile, GameLocation location) {
} else {
dirt.crop = null;
}
- return new Object(crop.indexOfHarvest.Value, stack, false, -1, num2);
+ return new SObject(crop.indexOfHarvest.Value, stack, false, -1, num2);
} else {
if (!crop.programColored.Value) {
- harvest = new Object(crop.indexOfHarvest.Value, 1, false, -1, num2);
+ harvest = new SObject(crop.indexOfHarvest.Value, 1, false, -1, num2);
} else {
harvest = new ColoredObject(crop.indexOfHarvest.Value, 1, crop.tintColor.Value) { Quality = num2 };
}
@@ -351,10 +370,10 @@ private Object GetHarvest(HoeDirt dirt, Vector2 tile, GameLocation location) {
return null;
}
- private Object GetFruit(FruitTree fruitTree, Vector2 tile, GameLocation location)
+ private SObject GetFruit(FruitTree fruitTree, Vector2 tile, GameLocation location)
{
- Object fruit = null;
+ SObject fruit = null;
int quality = 0;
if (fruitTree is null)
@@ -376,7 +395,7 @@ private Object GetFruit(FruitTree fruitTree, Vector2 tile, GameLocation location
if (fruitTree.daysUntilMature.Value <= -336) { quality = 4; }
if (fruitTree.struckByLightningCountdown.Value > 0) { quality = 0; }
- fruit = new Object(fruitTree.indexOfFruit.Value, fruitTree.fruitsOnTree.Value, false, -1, quality);
+ fruit = new SObject(fruitTree.indexOfFruit.Value, fruitTree.fruitsOnTree.Value, false, -1, quality);
fruitTree.fruitsOnTree.Value = 0;
return fruit;
}
@@ -402,7 +421,7 @@ private void AutograbWorld() {
return;
}
- foragerMap.Objects.TryGetValue(new Vector2(Config.GlobalForageTileX, Config.GlobalForageTileY), out Object grabber);
+ foragerMap.Objects.TryGetValue(new Vector2(Config.GlobalForageTileX, Config.GlobalForageTileY), out SObject grabber);
if (grabber == null || !grabber.Name.Contains("Grabber")) {
Monitor.Log($"No auto-grabber at {Config.GlobalForageMap}: <{Config.GlobalForageTileX}, {Config.GlobalForageTileY}>", LogLevel.Trace);
@@ -412,20 +431,65 @@ private void AutograbWorld() {
foreach (GameLocation location in Game1.locations) {
grabbables.Clear();
itemsAdded.Clear();
- foreach (KeyValuePair pair in location.Objects.Pairs) {
+ foreach (KeyValuePair pair in location.Objects.Pairs) {
if (pair.Value.bigCraftable.Value) {
continue;
}
- if (IsGrabbableWorld(pair.Value) || pair.Value.isForage(null)) {
+ if ((IsGrabbableWorld(pair.Value) || pair.Value.isForage(null)) && pair.Value.ParentSheetIndex != 73 ) { //Never atempt to grab Golden Walnuts
grabbables.Add(pair.Key);
}
}
+ // Check for Ginger crops on Island Locations
+ if (IsIslandLocation(location)) {
+ foreach (TerrainFeature feature in location.terrainFeatures.Values) {
+ if ((grabber.heldObject.Value as Chest).items.CountIgnoreNull() >= (grabber.heldObject.Value as Chest).GetActualCapacity()) {
+ Monitor.Log("Global grabber full", LogLevel.Info);
+ return;
+ }
+
+ if (feature is HoeDirt dirt) {
+ if (dirt.crop != null) {
+ if (dirt.crop.forageCrop.Value && dirt.crop.whichForageCrop.Value == 2) { // Ginger
+ SObject ginger = new SObject(829, 1, false, -1, 0);
+
+ if (Game1.player.professions.Contains(Farmer.botanist)) {
+ ginger.Quality = 4;
+ } else if (random.NextDouble() < Game1.player.ForagingLevel / 30.0) {
+ ginger.Quality = 2;
+ } else if (random.NextDouble() < Game1.player.ForagingLevel / 15.0) {
+ ginger.Quality = 1;
+ }
+
+ if (Game1.player.professions.Contains(Farmer.gatherer)) {
+ while (random.NextDouble() < 0.2) {
+ ginger.Stack += 1;
+ }
+ }
+
+ (grabber.heldObject.Value as Chest).addItem(ginger);
+ if (!itemsAdded.ContainsKey("Ginger")) {
+ itemsAdded.Add("Ginger", 1);
+ } else {
+ itemsAdded["Ginger"] += 1;
+ }
+
+ dirt.crop = null;
+
+ if (Config.DoGainExperience) {
+ gainExperience(FORAGING, 3);
+ }
+ }
+ }
+ }
+ }
+ }
+
// Check for spring onions
if (location.Name.Equals("Forest")) {
foreach (TerrainFeature feature in location.terrainFeatures.Values) {
- if ((grabber.heldObject.Value as Chest).items.Count >= 36) {
+ if ((grabber.heldObject.Value as Chest).items.CountIgnoreNull() >= (grabber.heldObject.Value as Chest).GetActualCapacity()) {
Monitor.Log("Global grabber full", LogLevel.Info);
return;
}
@@ -433,9 +497,9 @@ private void AutograbWorld() {
if (feature is HoeDirt dirt) {
if (dirt.crop != null) {
if (dirt.crop.forageCrop.Value && dirt.crop.whichForageCrop.Value == 1) { // spring onion
- Object onion = new Object(399, 1, false, -1, 0);
+ SObject onion = new SObject(399, 1, false, -1, 0);
- if (Game1.player.professions.Contains(16)) {
+ if (Game1.player.professions.Contains(Farmer.botanist)) {
onion.Quality = 4;
} else if (random.NextDouble() < Game1.player.ForagingLevel / 30.0) {
onion.Quality = 2;
@@ -443,7 +507,7 @@ private void AutograbWorld() {
onion.Quality = 1;
}
- if (Game1.player.professions.Contains(13)) {
+ if (Game1.player.professions.Contains(Farmer.gatherer)) {
while (random.NextDouble() < 0.2) {
onion.Stack += 1;
}
@@ -467,44 +531,44 @@ private void AutograbWorld() {
}
}
- // Check for berry bushes
- int berryIndex;
- string berryType;
-
- foreach (LargeTerrainFeature feature in location.largeTerrainFeatures) {
-
- if (Game1.currentSeason == "spring") {
- berryType = "Salmon Berry";
- berryIndex = 296;
- } else if (Game1.currentSeason == "fall") {
- berryType = "Blackberry";
- berryIndex = 410;
- } else {
- break;
- }
+ // Check for berry bushes - Except on Island Locations, avoiding Golden Walnuts
+ if (!IsIslandLocation(location)) {
+ foreach (LargeTerrainFeature feature in location.largeTerrainFeatures) {
+ int berryIndex;
+ string berryType;
+
+ if (Game1.currentSeason == "spring") {
+ berryType = "Salmon Berry";
+ berryIndex = 296;
+ } else if (Game1.currentSeason == "fall") {
+ berryType = "Blackberry";
+ berryIndex = 410;
+ } else {
+ break;
+ }
- if ((grabber.heldObject.Value as Chest).items.Count >= 36) {
- Monitor.Log("Global grabber full", LogLevel.Info);
- return;
- }
+ if ((grabber.heldObject.Value as Chest).items.CountIgnoreNull() >= (grabber.heldObject.Value as Chest).GetActualCapacity()) {
+ Monitor.Log("Global grabber full", LogLevel.Info);
+ return;
+ }
- if (feature is Bush bush) {
- if (bush.inBloom(Game1.currentSeason, Game1.dayOfMonth) && bush.tileSheetOffset.Value == 1) {
-
- Object berry = new Object(berryIndex, 1 + Game1.player.FarmingLevel / 4, false, -1, 0);
-
- if (Game1.player.professions.Contains(16)) {
- berry.Quality = 4;
- }
+ if (feature is Bush bush) {
+ if (bush.inBloom(Game1.currentSeason, Game1.dayOfMonth) && bush.tileSheetOffset.Value == 1) {
+ SObject berry = new SObject(berryIndex, 1 + Game1.player.FarmingLevel / 4, false, -1, 0);
+
+ if (Game1.player.professions.Contains(Farmer.botanist)) {
+ berry.Quality = 4;
+ }
- bush.tileSheetOffset.Value = 0;
- bush.setUpSourceRect();
+ bush.tileSheetOffset.Value = 0;
+ bush.setUpSourceRect();
- Item item = (grabber.heldObject.Value as Chest).addItem(berry);
- if (!itemsAdded.ContainsKey(berryType)) {
- itemsAdded.Add(berryType, 1);
- } else {
- itemsAdded[berryType] += 1;
+ Item item = (grabber.heldObject.Value as Chest).addItem(berry);
+ if (!itemsAdded.ContainsKey(berryType)) {
+ itemsAdded.Add(berryType, 1);
+ } else {
+ itemsAdded[berryType] += 1;
+ }
}
}
}
@@ -513,14 +577,14 @@ private void AutograbWorld() {
// add items to grabber and remove from floor
foreach (Vector2 tile in grabbables) {
- if ((grabber.heldObject.Value as Chest).items.Count >= 36) {
+ if ((grabber.heldObject.Value as Chest).items.CountIgnoreNull() >= (grabber.heldObject.Value as Chest).GetActualCapacity()) {
Monitor.Log("Global grabber full", LogLevel.Info);
return;
}
- Object obj = location.Objects[tile];
+ SObject obj = location.Objects[tile];
- if (Game1.player.professions.Contains(16)) {
+ if (Game1.player.professions.Contains(Farmer.botanist)) {
obj.Quality = 4;
} else if (random.NextDouble() < Game1.player.ForagingLevel / 30.0) {
obj.Quality = 2;
@@ -528,7 +592,7 @@ private void AutograbWorld() {
obj.Quality = 1;
}
- if (Game1.player.professions.Contains(13)) {
+ if (Game1.player.professions.Contains(Farmer.gatherer)) {
while (random.NextDouble() < 0.2) {
obj.Stack += 1;
}
@@ -553,10 +617,10 @@ private void AutograbWorld() {
{
if (location is FarmCave)
{
- foreach (Object obj in location.Objects.Values)
+ foreach (SObject obj in location.Objects.Values)
{
- if ((grabber.heldObject.Value as Chest).items.Count >= 36)
+ if ((grabber.heldObject.Value as Chest).items.CountIgnoreNull() >= (grabber.heldObject.Value as Chest).GetActualCapacity())
{
Monitor.Log("Global grabber full", LogLevel.Info);
return;
@@ -589,7 +653,7 @@ private void AutograbWorld() {
Monitor.Log($" {location} - found {pair.Value} {pair.Key}{plural}", LogLevel.Trace);
}
- if ((grabber.heldObject.Value as Chest).items.Count > 0) {
+ if ((grabber.heldObject.Value as Chest).items.CountIgnoreNull() > 0) {
grabber.showNextIndex.Value = true;
}
}
@@ -606,7 +670,7 @@ private bool IsGrabbableCoop(Object obj) {
return false;
}
- private bool IsGrabbableWorld(Object obj) {
+ private bool IsGrabbableWorld(SObject obj) {
if (obj.bigCraftable.Value) {
return false;
}
@@ -650,6 +714,14 @@ private bool IsGrabbableWorld(Object obj) {
return false;
}
+ private bool IsIslandLocation(GameLocation location) {
+ return
+ location.Name.Contains("Island")
+ || location.Name.Contains("Volcano")
+ || location.Name.Contains("Caldera")
+ || location.Name.Contains("CaptainRoom");
+ }
+
private void gainExperience(int skill, int xp) {
Game1.player.gainExperience(skill, xp);
}
diff --git a/DeluxeGrabber/NetListExtend.cs b/DeluxeGrabber/NetListExtend.cs
new file mode 100644
index 0000000..0bbe710
--- /dev/null
+++ b/DeluxeGrabber/NetListExtend.cs
@@ -0,0 +1,13 @@
+using Netcode;
+using System.Linq;
+
+namespace DeluxeGrabber
+{
+ public static class NetListExtend
+ {
+ public static int CountIgnoreNull(this NetObjectList list) where T : class, INetObject
+ {
+ return list.Count(item => item != null);
+ }
+ }
+}
diff --git a/DeluxeGrabber/Properties/AssemblyInfo.cs b/DeluxeGrabber/Properties/AssemblyInfo.cs
deleted file mode 100644
index 7e05ba7..0000000
--- a/DeluxeGrabber/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("CoopGrabber")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("CoopGrabber")]
-[assembly: AssemblyCopyright("Copyright © 2018")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("46a2fec7-f9eb-4a12-a43f-92906f884961")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/DeluxeGrabber/manifest.json b/DeluxeGrabber/manifest.json
index a8659f3..15dcfe7 100644
--- a/DeluxeGrabber/manifest.json
+++ b/DeluxeGrabber/manifest.json
@@ -1,10 +1,10 @@
{
- "Name": "DeluxeGrabber",
- "Author": "stokastic",
- "Version": "2.5.1",
- "Description": "Allows use of autograbber for coops, crops, and forage",
- "UniqueID": "stokastic.DeluxeGrabber",
- "EntryDll": "DeluxeGrabber.dll",
- "MinimumApiVersion": "2.7",
- "UpdateKeys": [ "Nexus:2462" ]
-}
\ No newline at end of file
+ "Name": "Deluxe Auto-Grabber",
+ "Author": "stokastic",
+ "Version": "2.5.1",
+ "Description": "Allows use of autograbber for coops, crops, and forage",
+ "UniqueID": "stokastic.DeluxeGrabber",
+ "EntryDll": "DeluxeGrabber.dll",
+ "MinimumApiVersion": "3.0.0",
+ "UpdateKeys": [ "Nexus:2462" ]
+}
diff --git a/DeluxeGrabber/packages.config b/DeluxeGrabber/packages.config
deleted file mode 100644
index 98c7e68..0000000
--- a/DeluxeGrabber/packages.config
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file