public void ActionItemAddedRemoved(object sender, ObjectListChangedEventArgs e) { if (!IsAllowed || !(bool)Value || Grabber.IsChestFull) { return; } //Utilities.Monitor.Log($" {Grabber.InstanceName} Attempting to forage truffle items", StardewModdingAPI.LogLevel.Trace); System.Random random = new System.Random(); Vector2[] nearbyTiles = Grabber.RangeEntireMap ? Utilities.GetLocationObjectTiles(Grabber.Location).ToArray() : Grabber.NearbyTilesRange; foreach (KeyValuePair <Vector2, SVObject> pair in e.Added) { if (pair.Value.ParentSheetIndex != 430 || pair.Value.bigCraftable.Value || !nearbyTiles.Contains(pair.Key)) { continue; } SVObject obj = pair.Value; if (obj.Stack == 0) { obj.Stack = 1; } //make sure its a forageable and grabable if (!obj.isForage(null) && !Utilities.IsGrabbableWorld(obj)) { continue; } if (Game1.player.professions.Contains(16)) { obj.Quality = 4; } else if (random.NextDouble() < Game1.player.ForagingLevel / 30.0) { obj.Quality = 2; } else if (random.NextDouble() < Game1.player.ForagingLevel / 15.0) { obj.Quality = 1; } if (Game1.player.professions.Contains(13)) { while (random.NextDouble() < 0.2) { obj.Stack += 1; } } //Utilities.Monitor.Log($" {Grabber.InstanceName} foraged: {obj.Name} {obj.Stack} {pair.Key.X},{pair.Key.Y}", StardewModdingAPI.LogLevel.Trace); Grabber.GrabberChest.addItem(obj); e.Location.Objects.Remove(pair.Key); if (Grabber.GainExperience) { Utilities.GainExperience(Grabber.FORAGING, 7); } } }
private bool IsFish(int which) { SVObject @object = new SVObject(which, 1); if (@object.Category == -20 || @object.ParentSheetIndex == 152 || @object.ParentSheetIndex == 153 || @object.parentSheetIndex == 157) { return(false); } return(true); }
private void FruitTrees() { var nearbyTiles = (Grabber.RangeEntireMap ? Utilities.GetLocationObjectTiles(Grabber.Location) : Grabber.NearbyTilesRange) .Where(t => Grabber.Location.terrainFeatures.ContainsKey(t) && Grabber.Location.terrainFeatures[t] is FruitTree) .GroupBy(t => t).Select(g => g.First()) .ToDictionary(t => t, t => Grabber.Location.terrainFeatures[t] as FruitTree); foreach (var pair in nearbyTiles) { if (Grabber.IsChestFull) { break; } FruitTree tree = pair.Value; if (tree.growthStage.Value >= FruitTree.treeStage && tree.fruitsOnTree.Value > 0 && !tree.stump.Value) { //Utilities.Monitor.Log($" {Grabber.InstanceName} harvesting fruit tree: {(new SVObject(tree.indexOfFruit.Value, 1)).Name} {tree.fruitsOnTree.Value} {pair.Key.X},{pair.Key.Y}", StardewModdingAPI.LogLevel.Trace); SVObject item; if (tree.struckByLightningCountdown.Value > 0) { item = new SVObject(382, tree.fruitsOnTree.Value); } else { int quality = SVObject.lowQuality; if (tree.daysUntilMature.Value <= -112) { quality = SVObject.medQuality; } if (tree.daysUntilMature.Value <= -224) { quality = SVObject.highQuality; } if (tree.daysUntilMature.Value <= -336) { quality = SVObject.bestQuality; } item = new SVObject(tree.indexOfFruit.Value, tree.fruitsOnTree.Value, quality: quality); } Grabber.GrabberChest.addItem(item); tree.fruitsOnTree.Value = 0; } } }
private int GetNextFish(GameLocation location, FishingRod rod) { int clearWaterDistance = GetPrivateValue <int>(rod, "clearWaterDistance"); Player lastUser = GetPrivateValue <Player>(rod, "lastUser"); Vector2 bobber = GetPrivateValue <Vector2>(rod, "bobber"); double num3 = (rod.attachments[0] != null) ? rod.attachments[0].Price / 10f : 0f; Rectangle rectangle2 = new Rectangle(location.fishSplashPoint.X * Game1.tileSize, location.fishSplashPoint.Y * Game1.tileSize, Game1.tileSize, Game1.tileSize); Rectangle value2 = new Rectangle((int)bobber.X - Game1.tileSize * 5 / 4, (int)bobber.Y - Game1.tileSize * 5 / 4, Game1.tileSize, Game1.tileSize); bool flag = rectangle2.Intersects(value2); SVObject @object = location.getFish(rod.fishingNibbleAccumulator, (rod.attachments[0] != null) ? rod.attachments[0].ParentSheetIndex : -1, clearWaterDistance + (flag ? 1 : 0), lastUser, num3 + (flag ? 0.4 : 0.0)); if (!IsFish(@object.ParentSheetIndex)) { return(GetNextFish(location, rod)); } return(@object.ParentSheetIndex); }
public override void Action() { if (!IsAllowed || !(bool)Value) { return; } //dig up artifacts foreach (var loc in (Grabber.RangeEntireMap ? Utilities.GetLocationObjectTiles(Grabber.Location) : Grabber.NearbyTilesRange).ToArray()) { if (Grabber.Location.Objects.ContainsKey(loc) && Grabber.Location.Objects[loc].ParentSheetIndex == 590 && !Grabber.Location.isTileHoeDirt(loc) && !Grabber.IsChestFull) { Utilities.DigUpArtifactSpot((int)loc.X, (int)loc.Y, Grabber.Location); Grabber.Location.Objects.Remove(loc); Grabber.Location.terrainFeatures.Add(loc, new HoeDirt()); //Utilities.Monitor.Log($" {Grabber.InstanceName} digging up artifact {loc.X},{loc.Y} {Grabber.Location.debris.Count()}", StardewModdingAPI.LogLevel.Trace); } } foreach (var debris in Grabber.Location.debris.ToArray()) { if (debris == null) { continue; } var debriItem = new SVObject(debris.Chunks.First().debrisType, 1); //handle picking up a book if (debriItem.parentSheetIndex == 102) { Game1.player.addItemByMenuIfNecessaryElseHoldUp(debriItem); } else if (!debriItem.Name.ToLower().Contains("error") && debriItem.ParentSheetIndex > 0) { Grabber.GrabberChest.addItem(debriItem); } if (!debriItem.Name.ToLower().Contains("error") && debriItem.ParentSheetIndex > 0) { Grabber.Location.debris.Remove(debris); } //Utilities.Monitor.Log($" **{Grabber.InstanceName} debris {debris.debrisType?.Value} {debriItem.Name} type {debriItem.Type} index {debriItem.ParentSheetIndex}", StardewModdingAPI.LogLevel.Trace); } }
public override void Action() { if (!IsAllowed || !(bool)Value) { return; } FruitTrees(); KeyValuePair <Vector2, HoeDirt>[] hoeDirts = (Grabber.Dirts).Where((arg) => arg.Value.readyForHarvest()).ToArray(); //Utilities.Monitor.Log($" {Grabber.InstanceName} Attempting to harvest crops {(bool)Value} {hoeDirts.Count()}", StardewModdingAPI.LogLevel.Trace); foreach (KeyValuePair <Vector2, HoeDirt> pair in hoeDirts) { HoeDirt dirt = pair.Value; Vector2 tile = pair.Key; Crop crop = pair.Value.crop; SVObject harvest; int stack = 0; if (Grabber.IsChestFull || !(bool)Value) { break; } if (crop == null) { continue; } if (Utilities.IsCropFlower(crop) && (!Flowers || SDate.Now().Day != 28)) { Utilities.Monitor.Log($" {Grabber.InstanceName} Crop is a flower and AutoHarvestFlowers: is false = {Flowers} or its not the 28 {SDate.Now()}", StardewModdingAPI.LogLevel.Trace); continue; } if (crop != null && crop.currentPhase.Value >= crop.phaseDays.Count - 1 && (!crop.fullyGrown.Value || crop.dayOfCurrentPhase.Value <= 0)) { int num1 = 1; int num2 = 0; int num3 = 0; Random random = new Random((int)tile.X * 7 + (int)tile.Y * 11 + (int)Game1.stats.DaysPlayed + (int)Game1.uniqueIDForThisGame); switch ((dirt.fertilizer.Value)) { case 368: num3 = 1; break; case 369: num3 = 2; break; } double num4 = 0.2 * (Game1.player.FarmingLevel / 10.0) + 0.2 * num3 * ((Game1.player.FarmingLevel + 2.0) / 12.0) + 0.01; double num5 = Math.Min(0.75, num4 * 2.0); if (random.NextDouble() < num4) { num2 = 2; } else if (random.NextDouble() < num5) { num2 = 1; } if ((crop.minHarvest.Value) > 1 || (crop.maxHarvest.Value) > 1) { var calculated = Math.Min(crop.minHarvest.Value + 1, crop.maxHarvest.Value + 1 + Game1.player.FarmingLevel / crop.maxHarvestIncreasePerFarmingLevel.Value); num1 = crop.minHarvest.Value == calculated ? calculated : random.Next(crop.minHarvest.Value, calculated); } if (crop.chanceForExtraCrops.Value > 0.0) { while (random.NextDouble() < Math.Min(0.9, crop.chanceForExtraCrops.Value)) { ++num1; } } for (int i = 0; i < num1; i++) { stack += 1; } if (crop.harvestMethod.Value == 1) { if (crop.regrowAfterHarvest.Value != -1) { crop.dayOfCurrentPhase.Value = crop.regrowAfterHarvest.Value; crop.fullyGrown.Value = true; } else { dirt.crop = null; } harvest = new SVObject(crop.indexOfHarvest.Value, stack, false, -1, num2); } else { harvest = !crop.programColored.Value ? new SVObject(crop.indexOfHarvest.Value, stack, false, -1, num2) : new ColoredObject(crop.indexOfHarvest.Value, stack, crop.tintColor.Value) { Quality = num2 }; if (crop.regrowAfterHarvest.Value != -1) { crop.dayOfCurrentPhase.Value = crop.regrowAfterHarvest.Value; crop.fullyGrown.Value = true; } else { dirt.crop = null; } } if (harvest != null) { //Utilities.Monitor.Log($" {InstanceName} Harvested: {harvest.Name} {harvest.Stack} {pair.Key.X},{pair.Key.Y}", StardewModdingAPI.LogLevel.Trace); Grabber.GrabberChest.addItem(harvest); if (Grabber.GainExperience) { Utilities.GainExperience(Grabber.FARMING, 3); } //PlantSeed(tile, dirt); } } } Grabber.Grabber.showNextIndex.Value |= Grabber.GrabberChest.items.Count != 0; }
private void OnOneSecondElapsed(object sender, EventArgs args) { if (!Context.IsWorldReady || config.TicksInterval == 0) { return; } Player player = Game1.player; ticksElapsed = (byte)((ticksElapsed + 1) % config.TicksInterval); if (ticksElapsed == 0) { Rectangle bb = ExpandBoundingBox(Game1.player.GetBoundingBox(), Game1.tileSize * 5, Game1.tileSize * 5); GameLocation location = Game1.currentLocation; //AutoHarvest Grown Crops if (config.AutoHarvestCrops) { foreach (Vector2 position in location.terrainFeatures.Keys) { TerrainFeature feature = location.terrainFeatures[position]; if (feature is HoeDirt dirt) { Crop crop = dirt.crop; if (crop == null) { continue; } if (config.AutoDestroyDeadCrops && crop.dead) { dirt.destroyCrop(position); continue; } if (!crop.fullyGrown || !bb.Intersects(feature.getBoundingBox(position))) { continue; } crop.harvest((int)position.X, (int)position.Y, dirt); } } } //Collecting Forages if (config.AutoCollectForages) { ICollection <Vector2> keys = new List <Vector2>(location.Objects.Keys); foreach (Vector2 vec in keys) { SVObject obj = location.Objects[vec]; if (!bb.Intersects(obj.boundingBox)) { continue; } if (obj.isForage(location)) { Random random = new Random((int)Game1.uniqueIDForThisGame / 2 + (int)Game1.stats.DaysPlayed + (int)vec.X + (int)vec.Y * 777); if (player.professions.Contains(16)) { obj.quality = 4; } else { if (random.NextDouble() < player.ForagingLevel / 30f) { obj.quality = 2; } else if (random.NextDouble() < player.ForagingLevel / 15f) { obj.quality = 1; } } if (player.couldInventoryAcceptThisItem(obj)) { if (player.IsMainPlayer) { Game1.playSound("pickUpItem"); DelayedAction.playSoundAfterDelay("coin", 300); } player.animateOnce(279 + player.FacingDirection); if (!location.isFarmBuildingInterior()) { player.gainExperience(2, 7); } else { player.gainExperience(0, 5); } player.addItemToInventoryBool(obj.getOne(), false); Stats expr_70E = Game1.stats; uint itemsForaged = expr_70E.ItemsForaged; expr_70E.ItemsForaged = itemsForaged + 1u; if (player.professions.Contains(13) && random.NextDouble() < 0.2 && !obj.questItem && player.couldInventoryAcceptThisItem(obj) && !location.isFarmBuildingInterior()) { player.addItemToInventoryBool(obj.getOne(), false); player.gainExperience(2, 7); } location.Objects.Remove(vec); return; } } } } } }
public static Vector2 GetLocationOf(GameLocation location, SVObject obj) { return(location.Objects.Pairs.Any(kv => kv.Value == obj) ? location.Objects.Pairs.First(kv => kv.Value == obj).Key : new Vector2(-1, -1)); }
public NextItem(SVObject item, Chest chest) { Item = item; Chest = chest; }
public static void UnifyFlowerColors() { foreach (KeyValuePair <Vector2, TerrainFeature> featurePair in Game1.currentLocation.terrainFeatures.Pairs.Where(kv => kv.Value is HoeDirt)) { Vector2 loc = featurePair.Key; HoeDirt dirt = (HoeDirt)featurePair.Value; Crop crop = dirt.crop; if (crop == null || dirt.crop.dead.Value || !dirt.crop.programColored.Value) { continue; } Color oldColor = crop.tintColor.Value; switch (crop.indexOfHarvest.Value) { case FlowerIndex.Poppy: //Poppy crop.tintColor.Value = Config.PoppyColor; break; case FlowerIndex.Tulip: //Tulip crop.tintColor.Value = Config.TulipColor; break; case FlowerIndex.BlueJazz: //Blue Jazz crop.tintColor.Value = Config.JazzColor; break; case FlowerIndex.SummerSpangle: //Summer Spangle crop.tintColor.Value = Config.SummerSpangleColor; break; case FlowerIndex.FairyRose: //Fairy Rose crop.tintColor.Value = Config.FairyRoseColor; break; default: Color?color = GetCustomizedFlowerColor(crop.indexOfHarvest.Value); if (color != null) { crop.tintColor.Value = color.Value; break; } else { continue; } } if (oldColor.PackedValue == crop.tintColor.Value.PackedValue) { continue; } SVObject obj = new SVObject(crop.indexOfHarvest.Value, 1); Logger.Log($"changed {obj.DisplayName} @[{loc.X},{loc.Y}] to color(R:{crop.tintColor.R},G:{crop.tintColor.G},B:{crop.tintColor.B},A:{crop.tintColor.A})"); } }
public override void Action() { if (!IsAllowed || !(bool)Value) { return; } Utilities.Monitor.Log($" {Grabber.InstanceName} Attempting to forage items", StardewModdingAPI.LogLevel.Trace); Vector2[] nearbyTiles = (Grabber.RangeEntireMap ? Utilities.GetLocationObjectTiles(Grabber.Location) : Grabber.NearbyTilesRange).ToArray(); Random random = new Random(); //Handle animal houses foreach (Vector2 tile in nearbyTiles.Where(tile => Grabber.Location.Objects.ContainsKey(tile) && Utilities.IsGrabbableCoop(Grabber.Location.Objects[tile])).ToArray()) { if (Grabber.IsChestFull) { break; } if (tile != null && Grabber.Location.objects.ContainsKey(tile) && Grabber.Location.objects[tile].Name != null && Grabber.Location.objects[tile].Name.Contains("Slime Ball")) { Random rr = new Random((int)Game1.stats.daysPlayed + (int)Game1.uniqueIDForThisGame + (int)tile.X * 77 + (int)tile.Y * 777 + 2); Grabber.GrabberChest.addItem(new SVObject(766, random.Next(10, 21), false, -1, 0)); int i = 0; while (random.NextDouble() < 0.33) { i++; } if (i > 0) { Grabber.GrabberChest.addItem(new SVObject(557, i, false, -1, 0)); } } else if (Grabber.GrabberChest.addItem(Grabber.Location.Objects[tile]) != null) { continue; } //Utilities.Monitor.Log($" {Grabber.InstanceName} foraged: {Grabber.Location.Objects[tile].Name} {tile.X},{tile.Y}", StardewModdingAPI.LogLevel.Trace); Grabber.Location.Objects.Remove(tile); if (Grabber.GainExperience) { Utilities.GainExperience(Grabber.FORAGING, 5); } } //Handle Spring onions foreach (Vector2 tile in nearbyTiles.Where((tile) => Grabber.Location.terrainFeatures.ContainsKey(tile) && Grabber.Location.terrainFeatures[tile] is HoeDirt dirt && dirt.crop != null && dirt.crop.forageCrop.Value && dirt.crop.whichForageCrop.Value == 1)) { if (Grabber.IsChestFull) { break; } if (tile == null || !Grabber.Location.terrainFeatures.ContainsKey(tile)) { continue; } SVObject onion = new SVObject(399, 1, false, -1, 0); if (Game1.player.professions.Contains(16)) { onion.Quality = 4; } else if (random.NextDouble() < Game1.player.ForagingLevel / 30.0) { onion.Quality = 2; } else if (random.NextDouble() < Game1.player.ForagingLevel / 15.0) { onion.Quality = 1; } if (Game1.player.professions.Contains(13)) { while (random.NextDouble() < 0.2) { onion.Stack += 1; } } Utilities.Monitor.Log($" {Grabber.InstanceName} foraged: {onion.Name} {onion.Stack} {tile.X}, {tile.Y}", StardewModdingAPI.LogLevel.Trace); Grabber.GrabberChest.addItem(onion); (Grabber.Location.terrainFeatures[tile] as HoeDirt).crop = null; if (Grabber.GainExperience) { Utilities.GainExperience(Grabber.FORAGING, 3); } } //Handle world forageables foreach (Vector2 tile in nearbyTiles.Where(tile => Grabber.Location.Objects.ContainsKey(tile) && (Utilities.IsGrabbableWorld(Grabber.Location.Objects[tile]) || Grabber.Location.Objects[tile].isForage(null))).ToArray()) { if (Grabber.IsChestFull) { break; } if (tile == null || !Grabber.Location.Objects.ContainsKey(tile)) { continue; } SVObject obj = Grabber.Location.Objects[tile]; if (Game1.player.professions.Contains(16)) { obj.Quality = 4; } else if (random.NextDouble() < Game1.player.ForagingLevel / 30.0) { obj.Quality = 2; } else if (random.NextDouble() < Game1.player.ForagingLevel / 15.0) { obj.Quality = 1; } if (Game1.player.professions.Contains(13)) { while (random.NextDouble() < 0.2) { obj.Stack += 1; } } Utilities.Monitor.Log($" {Grabber.InstanceName} foraged: {obj.Name} {obj.Stack} {tile.X},{tile.Y}", StardewModdingAPI.LogLevel.Trace); Item item = Grabber.GrabberChest.addItem(obj); Grabber.Location.Objects.Remove(tile); if (Grabber.GainExperience) { Utilities.GainExperience(Grabber.FORAGING, 7); } } //Handle berry bushes if (Grabber.RangeEntireMap) { int berryIndex; foreach (LargeTerrainFeature feature in Grabber.Location.largeTerrainFeatures) { if (Grabber.IsChestFull) { break; } if (Game1.currentSeason == "spring") { berryIndex = 296; } else if (Game1.currentSeason == "fall") { berryIndex = 410; } else { break; } if (feature is Bush bush) { if (bush.inBloom(Game1.currentSeason, Game1.dayOfMonth) && bush.tileSheetOffset.Value == 1) { SVObject berry = new SVObject(berryIndex, 1 + Game1.player.FarmingLevel / 4, false, -1, 0); if (Game1.player.professions.Contains(16)) { berry.Quality = 4; } Utilities.Monitor.Log($" {Grabber.InstanceName} foraged: {berry.Name} {berry.Stack}", StardewModdingAPI.LogLevel.Trace); bush.tileSheetOffset.Value = 0; bush.setUpSourceRect(); Grabber.GrabberChest.addItem(berry); } } } } Grabber.Grabber.showNextIndex.Value |= Grabber.GrabberChest.items.Count != 0; }
private void OnGameTick(object sender, EventArgs args) { if (!Context.IsWorldReady || !config.Enabled) { return; } if (isFirstTick) { isFirstTick = false; OutputNames(Helper.DirectoryPath); } Player player = Game1.player; Dictionary <Vector2, TerrainFeature> features = player.currentLocation.terrainFeatures; Tool CurrentTool = player.CurrentTool; IMinigame minigame = Game1.currentMinigame; if (config.InfiniteStamina) { player.Stamina = player.MaxStamina; } if (config.AutokillEnemies) { KillEnemies(player, this); } if (config.AutoSave) { tickCount = (tickCount + 1) % config.AutoSaveInterval; if (tickCount == 0) { SaveGame.Save(); Monitor.Log("Auto saved!"); } } if (config.SkipFishingMinigame) { if (player.CurrentTool is FishingRod rod) { IClickableMenu clickableManu = Game1.activeClickableMenu; if (clickableManu is BobberBar bar) { if (GetPrivateValue <float>(bar, "scale") <= 0f) { int random = new Random().Next() % 100; Monitor.Log("Random value:" + random); if (random < config.PercentageTreasureHunt) { //Treasure caught! Monitor.Log("Treasure Caught!"); SetPrivateValue(bar, "treasureCaught", true); } } else { SetPrivateValue(bar, "fadeOut", true); SetPrivateValue(bar, "perfect", true); SetPrivateValue(bar, "distanceFromCatching", 10); } } } } if (config.InfiniteWateringCan) { if (CurrentTool is WateringCan wc) { wc.WaterLeft = wc.waterCanMax; } } if (config.InstantCatchFish) { if (CurrentTool is FishingRod rod) { if (rod.isFishing && rod.timeUntilFishingBite > 0) { rod.timeUntilFishingBite = 0; } } } if (config.NoGarbageFishing) { if (CurrentTool is FishingRod rod) { int whichFish = GetPrivateValue <int>(rod, "whichFish"); if (!IsFish(whichFish)) { SetPrivateValue(rod, "whichFish", GetNextFish(player.currentLocation, rod)); Vector2 bobber = GetPrivateValue <Vector2>(rod, "bobber"); Game1.screenOverlayTempSprites.Clear(); Game1.screenOverlayTempSprites.Add(new TemporaryAnimatedSprite(Game1.mouseCursors, new Rectangle(612, 1913, 74, 30), 1500f, 1, 0, Game1.GlobalToLocal(Game1.viewport, bobber + new Vector2(-140f, (float)(-(float)Game1.tileSize * 5 / 2))), false, false, 1f, 0.005f, Color.White, 4f, 0.075f, 0f, 0f, true) { scaleChangeChange = -0.005f, motion = new Vector2(0f, -0.1f), endFunction = new TemporaryAnimatedSprite.endBehavior(rod.startMinigameEndFunction), extraInfoForEndBehavior = GetPrivateValue <int>(rod, "whichFish") }); } } } if (config.AutoWateringCrops) { foreach (Vector2 loc in features.Keys) { if (features[loc] is HoeDirt feature) { feature.state = 1; } } } if (config.InstantGrowTree) { foreach (Vector2 loc in features.Keys) { if (features[loc] is Tree tree) { if (tree.growthStage < 5) { tree.growthStage = 5; tree.hasSeed = true; } } else if (features[loc] is FruitTree fTree) { if (fTree.growthStage < 4) { fTree.growthStage = 4; fTree.dayUpdate(player.currentLocation, loc); } } } } if (config.FastMachineProcessing) { foreach (GameLocation location in Game1.locations) { Dictionary <Vector2, SVObject> objects = location.Objects; foreach (Vector2 loc in objects.Keys) { SVObject obj = objects[loc]; obj.minutesElapsed(1000, player.currentLocation); } } } if (config.MagnetDropItems) { foreach (Debris debri in player.currentLocation.debris) { MagnetDebris(debri, player); } } }
private void OnKeyPressed(object sender, EventArgsKeyPressed e) { Player player = Game1.player; if (e.KeyPressed == Keys.C) { if (!config.UseToolsNearby || player.CurrentTool == null) { return; } Rectangle bb = ExpandBoundingBox(player.GetBoundingBox(), 1000, 1000); GameLocation location = player.currentLocation; Dictionary <Vector2, TerrainFeature> features = location.terrainFeatures; if (player.CurrentTool is Axe) { foreach (Vector2 loc in features.Keys) { TerrainFeature feature = features[loc]; if (feature.getBoundingBox(loc).Intersects(bb) && feature is Tree tree) { tree.health = 0; tree.performToolAction(player.CurrentTool, 0, loc, location); } } Dictionary <Vector2, SVObject> objects = new Dictionary <Vector2, SVObject>(location.Objects); foreach (Vector2 loc in objects.Keys) { SVObject obj = objects[loc]; if (obj != null && loc != null && obj.getBoundingBox(loc) != null && obj.getBoundingBox(loc).Intersects(bb) && (obj.Name == "Twig" || obj.name == "Weeds")) { obj.performToolAction(player.CurrentTool); location.removeObject(loc, false); Monitor.Log(string.Format("removed tile: {0}", obj.name)); } } if (location is Farm farm) { BreakStumps(player, bb, farm.resourceClumps); } else if (location is Woods woods) { BreakStumps(player, bb, woods.stumps); } else if (location is Forest forest) { if (BreakStump(player, bb, forest.log)) { forest.log = null; } } } else if (player.CurrentTool is Pickaxe) { int playerX = player.getStandingX() / Game1.tileSize, playerY = player.getStandingY() / Game1.tileSize; Dictionary <Vector2, SVObject> objects = new Dictionary <Vector2, SVObject>(location.Objects); foreach (Vector2 loc in objects.Keys) { int num = (int)loc.X / Game1.tileSize; int num2 = (int)loc.Y / Game1.tileSize; SVObject obj = objects[loc]; if (obj != null && loc != null && obj.getBoundingBox(loc) != null && obj.getBoundingBox(loc).Intersects(bb) && (obj.name == "Stone")) { location.Objects.Remove(loc); if (!(location is MineShaft)) { Game1.createRadialDebris(Game1.currentLocation, 14, num, num2, Game1.random.Next(2, 5), false, -1, false, -1); location.breakStone(obj.parentSheetIndex, num, num2, player, new Random()); } else if (location is MineShaft shaft) { if (GetPrivateValue <int>(shaft, "stonesLeftOnThisLevel") == 0) { return; } shaft.checkStoneForItems(obj.parentSheetIndex, num, num2, player); int stonesLeft = GetPrivateValue <int>(shaft, "stonesLeftOnThisLevel"); Monitor.Log("Stones left is " + stonesLeft); if (GetPrivateValue <int>(shaft, "stonesLeftOnThisLevel") == 0) { Monitor.Log("Creating ladder!"); shaft.createLadderDown(playerX, playerY); } } } } if (location is Farm farm) { BreakStumps(player, bb, farm.resourceClumps); } else if (location is Woods woods) { BreakStumps(player, bb, woods.stumps); } else if (location is MineShaft shaft) { BreakStumps(player, bb, shaft.resourceClumps); } } } else if (e.KeyPressed == Keys.PageDown) { GameLocation location = player.currentLocation; if (location != null && location is MineShaft mineshaft) { if (mineshaft.mineLevel == 120) { return; } Game1.enterMine(false, Game1.mine.mineLevel + 1, null); Game1.playSound("stairsdown"); } } }