public static void HandleFinishedObjectInMachine(Object machine, Chest connectedChest) { var logMessage = $"Collecting a {machine.heldObject?.Name} from your {machine.Name}."; if (connectedChest.items.Count > ChestMaxItems) { Monitor.Log($"Your chest is already full. Cannot place item from {machine.Name} into it.", LogLevel.Error); return; } machine.checkForAction(Who); Who.items.ForEach(i => { if (i != null) { var result = connectedChest.addItem(i); if (result != null) { Game1.player.addItemToInventory(result); } } }); if (machine.heldObject != null && machine.minutesUntilReady > 0) { logMessage += $" The next {machine.heldObject.Name} will be ready in {machine.minutesUntilReady}"; } Who.ClearInventory(); Monitor.Log(logMessage, LogLevel.Info); }
private void InteractWithObjectAhead(object Sender, EventArgs e) { if (!Context.IsWorldReady || !Context.CanPlayerMove) { return; } if (!Game1.player.isMoving()) { return; } Point pointAhead = Utility.GetPointAheadPlayer(); Point tileAhead = new Point(pointAhead.X / Game1.tileSize, pointAhead.Y / Game1.tileSize); StardewValley.Object objectAhead = ( Game1.currentLocation.isObjectAt(pointAhead.X, pointAhead.Y) ? ( Game1.currentLocation.getObjectAt(pointAhead.X, pointAhead.Y) ) : null ); if (this.config.EnableAutoFenceGateManagement && objectAhead is Fence) { // Check for horse control (config-based) if (this.config.OnlyOpenFenceGateWhileRidingHorse && !Game1.player.isRidingHorse()) { return; } // Check if objectAhead is an untracked, closed fence gate if (this.TrackedFenceGates.ContainsKey(pointAhead)) { return; } if (!(objectAhead as Fence).isGate || (objectAhead as Fence).gatePosition != 0) { return; } // Interact with objectAhead and track it for automatic closing objectAhead.checkForAction(Game1.player, false); TrackedFenceGates.Add(pointAhead, Game1.currentLocation); return; } int transportAhead = Utility.GetDoorType(tileAhead); if (this.config.EnableAutoTransport && Convert.ToBoolean(transportAhead)) { // If transportAhead is a ladder going down in the mines, check config to handle or not if (transportAhead == 8 && !this.config.EnableAutoMineDownLadder) { return; } // Interact with transport tile ahead Game1.currentLocation.checkAction(new Location(tileAhead.X, tileAhead.Y), Game1.viewport, Game1.player); return; } }
/// <summary>Try to harvest the output from a machine.</summary> /// <param name="machine">The machine to harvest.</param> /// <returns>Returns whether it was harvested.</returns> private bool TryHarvestMachine(SObject machine) { if (this.Config.HarvestMachines && machine != null && machine.readyForHarvest.Value && machine.heldObject.Value != null) { machine.checkForAction(Game1.player); return(true); } return(false); }
/// <summary>Apply the tool to the given tile.</summary> /// <param name="tile">The tile to modify.</param> /// <param name="tileObj">The object on the tile.</param> /// <param name="tileFeature">The feature on the tile.</param> /// <param name="player">The current player.</param> /// <param name="tool">The tool selected by the player (if any).</param> /// <param name="item">The item selected by the player (if any).</param> /// <param name="location">The current location.</param> public override bool Apply(Vector2 tile, SObject tileObj, TerrainFeature tileFeature, Farmer player, Tool tool, Item item, GameLocation location) { // spawned forage if (this.Config.HarvestForage && tileObj?.IsSpawnedObject == true) { this.CheckTileAction(location, tile, player); return(true); } // crop or spring onion (if an object like a scarecrow isn't placed on top of it) if (this.TryGetHoeDirt(tileFeature, tileObj, out HoeDirt dirt, out bool dirtCoveredByObj)) { if (dirtCoveredByObj || dirt.crop == null) { return(false); } if (this.Config.ClearDeadCrops && dirt.crop.dead.Value) { this.UseToolOnTile(this.FakePickaxe, tile); // clear dead crop return(true); } bool shouldHarvest = dirt.crop.programColored.Value // from Utility.findCloseFlower ? this.Config.HarvestFlowers : this.Config.HarvestCrops; if (shouldHarvest) { if (dirt.crop.harvestMethod.Value == Crop.sickleHarvest) { return(dirt.performToolAction(tool, 0, tile, location)); } else { this.CheckTileAction(location, tile, player); } } return(true); } // machines if (this.Config.HarvestMachines && tileObj != null && tileObj.readyForHarvest.Value && tileObj.heldObject.Value != null) { tileObj.checkForAction(Game1.player); return(true); } // fruit tree if (this.Config.HarvestFruitTrees && tileFeature is FruitTree tree && tree.fruitsOnTree.Value > 0) { tree.performUseAction(tile, location); return(true); } // grass if (this.Config.HarvestGrass && tileFeature is Grass) { location.terrainFeatures.Remove(tile); if (Game1.getFarm().tryToAddHay(1) == 0) // returns number left { Game1.addHUDMessage(new HUDMessage("Hay", HUDMessage.achievement_type, true, Color.LightGoldenrodYellow, new SObject(178, 1))); } return(true); } // weeds if (this.Config.ClearWeeds && this.IsWeed(tileObj)) { this.UseToolOnTile(tool, tile); // doesn't do anything to the weed, but sets up for the tool action (e.g. sets last user) tileObj.performToolAction(tool, location); // triggers weed drops, but doesn't remove weed location.removeObject(tile, false); return(true); } // bush Rectangle tileArea = this.GetAbsoluteTileArea(tile); if (this.Config.HarvestForage && location.largeTerrainFeatures.FirstOrDefault(p => p.getBoundingBox(p.tilePosition.Value).Intersects(tileArea)) is Bush bush) { if (!bush.townBush.Value && bush.tileSheetOffset.Value == 1 && bush.inBloom(Game1.currentSeason, Game1.dayOfMonth)) { bush.performUseAction(bush.tilePosition.Value, location); return(true); } } return(false); }
private void ButtonsChanged(object?sender, ButtonsChangedEventArgs e) { // No world, we return. if (!Context.IsWorldReady) { return; } if (Game1.activeClickableMenu != null) { return; } // If an event is up, return, because we don't want to accidentally warp out of an event. // This shouldn't be possible anyway, but I'm keeping this here for safety. if (Game1.eventUp) { return; } Farmer player = Game1.player; // If the return sceptre cooldown is over... if (rodCooldown.CanWarp) { // And if the player is holding a return scepter... if (player.CurrentItem is Wand && player.CurrentItem.Name.Equals("Return Scepter")) { // The cooldown is over, and the player is holding a return sceptre. Now we check to see // whether they press the return to previous point bind, or the Multiple Mini-Obelisk menu bind. if (e.Pressed.Contains(SButton.MouseRight) || config.ReturnToLastPoint.JustPressed()) { // The player pressed the return to previous point bind. if (!player.bathingClothes.Value && player.IsLocalPlayer && !player.onBridge.Value) { logger.Log($"Warping farmer {player.Name} to {previousPoint.Location.Name} on tile {previousPoint.Tile}", LogLevel.Trace); // We reset our countdown timer and status to zero, because we want it to start from when the player last did a normal warp. rodCooldown.ResetCountdown(); #region Modified decompile section // Shamelessly taken from the decompile and modified slightly. Sorry, CA! for (int i = 0; i < 12; i++) { TemporaryAnimatedSprite zoomyDust = new TemporaryAnimatedSprite(354, Game1.random.Next(25, 75), 6, 1, new Vector2(Game1.random.Next((int)player.position.X - 256, (int)player.position.X + 192), Game1.random.Next((int)player.position.Y - 256, (int)player.position.Y + 192)), flicker: false, (Game1.random.NextDouble() < 0.5)); Game1.currentLocation.TemporarySprites.Add(zoomyDust); } Game1.currentLocation.playSound("wand"); Game1.displayFarmer = false; player.temporarilyInvincible = true; player.temporaryInvincibilityTimer = -2000; player.Halt(); player.faceDirection(2); player.CanMove = false; player.freezePause = 2000; Game1.flashAlpha = 1f; DelayedAction.fadeAfterDelay(DoWarp, 1000); int nextTileDelay = 0; for (int xTile = player.getTileX() + 8; xTile >= player.getTileX() - 8; xTile--) { TemporaryAnimatedSprite flash = new TemporaryAnimatedSprite(6, new Vector2(xTile, player.getTileY()) * 64f, Color.White, 8, flipped: false, 50f) { layerDepth = 1f, delayBeforeAnimationStart = nextTileDelay * 25, motion = new Vector2(-0.25f, 0f) }; Game1.currentLocation.TemporarySprites.Add(flash); nextTileDelay++; } #endregion } } else if (config.EnableMultiObeliskSupport) { // Support is enabled... if (config.OpenObeliskWarpMenuController.JustPressed() || config.OpenObeliskWarpMenuKbm.JustPressed()) { // The button was pressed, so we want to check to see if the mod is installed. if (multiObeliskModInstalled) { // The mod is installed, so we can continue. if (config.CountWarpMenuAsScepterUsage) { // The setting to count warp menu usage as scepter usage is enabled, so we set our previous point. previousPoint.Location = player.currentLocation; previousPoint.Tile = player.getTileLocation(); } // Reset our cooldown. rodCooldown.ResetCountdown(); // And create a temporary, dummy mini-obelisk, and "interact" with it to spawn the warp menu. SObject dummyObelisk = new SObject(); dummyObelisk.ParentSheetIndex = 238; dummyObelisk.checkForAction(Game1.player); } else { Game1.showRedMessage("Multiple Mini-Obelisks support is enabled, but the mod itself isn't installed."); } } } } } }
/// <summary>Apply the tool to the given tile.</summary> /// <param name="tile">The tile to modify.</param> /// <param name="tileObj">The object on the tile.</param> /// <param name="tileFeature">The feature on the tile.</param> /// <param name="player">The current player.</param> /// <param name="tool">The tool selected by the player (if any).</param> /// <param name="item">The item selected by the player (if any).</param> /// <param name="location">The current location.</param> public override bool Apply(Vector2 tile, SObject tileObj, TerrainFeature tileFeature, Farmer player, Tool tool, Item item, GameLocation location) { // spawned forage if (this.Config.HarvestForage && tileObj?.IsSpawnedObject == true) { // pick up forage & cancel animation if (this.CheckTileAction(location, tile, player)) { IReflectedField <int> animationID = this.Reflection.GetField <int>(player.FarmerSprite, "currentSingleAnimation"); switch (animationID.GetValue()) { case FarmerSprite.harvestItemDown: case FarmerSprite.harvestItemLeft: case FarmerSprite.harvestItemRight: case FarmerSprite.harvestItemUp: player.completelyStopAnimatingOrDoingAction(); player.forceCanMove(); break; } } return(true); } // crop or spring onion (if an object like a scarecrow isn't placed on top of it) if (this.TryGetHoeDirt(tileFeature, tileObj, out HoeDirt dirt, out bool dirtCoveredByObj)) { if (dirtCoveredByObj || dirt.crop == null) { return(false); } if (this.Config.ClearDeadCrops && dirt.crop.dead.Value) { this.UseToolOnTile(this.FakePickaxe, tile, player, location); // clear dead crop return(true); } if (this.ShouldHarvest(dirt.crop)) { return(dirt.crop.harvestMethod.Value == Crop.sickleHarvest ? dirt.performToolAction(tool, 0, tile, location) : dirt.performUseAction(tile, location)); } return(true); } // machines if (this.Config.HarvestMachines && tileObj != null && tileObj.readyForHarvest.Value && tileObj.heldObject.Value != null) { tileObj.checkForAction(Game1.player); return(true); } // fruit tree if (this.Config.HarvestFruitTrees && tileFeature is FruitTree tree && tree.fruitsOnTree.Value > 0) { tree.performUseAction(tile, location); return(true); } // grass // (see Grass.performToolAction) if (this.Config.HarvestGrass && tileFeature is Grass) { location.terrainFeatures.Remove(tile); Random random = Game1.IsMultiplayer ? Game1.recentMultiplayerRandom : new Random((int)(Game1.uniqueIDForThisGame + tile.X * 1000.0 + tile.Y * 11.0)); if (random.NextDouble() < (tool.InitialParentTileIndex == MeleeWeapon.goldenScythe ? 0.75 : 0.5)) { if (Game1.getFarm().tryToAddHay(1) == 0) // returns number left { Game1.addHUDMessage(new HUDMessage("Hay", HUDMessage.achievement_type, true, Color.LightGoldenrodYellow, new SObject(178, 1))); } } return(true); } // weeds if (this.Config.ClearWeeds && this.IsWeed(tileObj)) { this.UseToolOnTile(tool, tile, player, location); // doesn't do anything to the weed, but sets up for the tool action (e.g. sets last user) tileObj.performToolAction(tool, location); // triggers weed drops, but doesn't remove weed location.removeObject(tile, false); return(true); } // bush Rectangle tileArea = this.GetAbsoluteTileArea(tile); if (this.Config.HarvestForage) { Bush bush = tileFeature as Bush ?? location.largeTerrainFeatures.FirstOrDefault(p => p.getBoundingBox(p.tilePosition.Value).Intersects(tileArea)) as Bush; if (bush?.tileSheetOffset.Value == 1 && (bush.size.Value == Bush.greenTeaBush || (bush.size.Value == Bush.mediumBush && !bush.townBush.Value))) { bush.performUseAction(bush.tilePosition.Value, location); return(true); } } return(false); }