public static void OnInputsInserted(PerformObjectDropInData PODIData, int AugmentorQuantity) { #if LEGACYCODE if (MachineInfo.TryGetMachineInfo(PODIData.Machine, out MachineInfo Info)) { if (!Info.AttachableAugmentors.Contains(AugmentorType.Duplication) || AugmentorQuantity <= 0 || !Info.RequiresInput || PODIData.Machine.readyForHarvest) { return; } bool Success = SpawnDuplicate(AugmentorQuantity, PODIData.CurrentMinutesUntilReady, Info.RequiresInput, out double Chance); if (Success) { if (PODIData.Machine.getOne() is Object Duplicate) { Duplicate.Stack = 1; int SpawnDirection = Randomizer.Next(4); Game1.createItemDebris(Duplicate, Game1.player.getStandingPosition(), SpawnDirection, null, -1); } } MachineAugmentorsMod.LogTrace(AugmentorType.Duplication, AugmentorQuantity, PODIData.Machine, Info.RequiresInput, PODIData.Machine.TileLocation, "CreateDuplicate", 0, Chance, Convert.ToInt32(Success), Chance); } #endif }
public static void OnInputsInserted(PerformObjectDropInData PODIData, int AugmentorQuantity) { if (MachineInfo.TryGetMachineInfo(PODIData.Machine, out MachineInfo Info)) { if (!Info.AttachableAugmentors.Contains(AugmentorType.Efficiency) || AugmentorQuantity <= 0 || !Info.RequiresInput || PODIData.Input == null) { return; } int PreviousAmountInserted = PODIData.PreviousInputQuantity - PODIData.CurrentInputQuantity; int NewAmountInserted; double Effect; double DesiredNewValue; if (PreviousAmountInserted <= 0) { // No clue why, but for some machines the game hasn't actually taken the input yet by the time Object.performObjectDropIn finishes. // so assume the input amount was = to 1 when computing the refund. NewAmountInserted = ComputeNewValue(AugmentorQuantity, 1, Info.RequiresInput, out Effect, out DesiredNewValue) - 1 - Math.Abs(PreviousAmountInserted); // -1 because we assume it required at least 1 input, -PreviousInputQuantityUsed because another augmentor whose effect could have been applied first may have set the quantity to a negative value to allow saving a material } else { NewAmountInserted = ComputeNewValue(AugmentorQuantity, PreviousAmountInserted, Info.RequiresInput, out Effect, out DesiredNewValue); } int RefundAmt = PreviousAmountInserted - NewAmountInserted; if (RefundAmt > 0) { bool WasStackDepleted = PODIData.Input.Stack <= 0; PODIData.Input.Stack += RefundAmt; // If Stack was set to 0 by the game, then the game would have removed it from their inventory, and so they wouldn't be able to receive the refunded quantity if (WasStackDepleted && PODIData.WasInputInInventory && Game1.player.Items[PODIData.InputInventoryIndex.Value] == null) { Game1.player.addItemToInventory(PODIData.Input, PODIData.InputInventoryIndex.Value); } } // Refund coal when processing ores if (IsOre(PODIData.Input)) { double Chance = 1.0 - Effect; int SpawnedQuantity = WeightedRound(Chance); if (SpawnedQuantity > 0) { Object Coal = new Object(382, SpawnedQuantity, false, -1, 0); int SpawnDirection = Randomizer.Next(4); Game1.createItemDebris(Coal, PODIData.Machine.TileLocation * Game1.tileSize, SpawnDirection, null, -1); } } MachineAugmentorsMod.LogTrace(AugmentorType.Efficiency, AugmentorQuantity, PODIData.Machine, Info.RequiresInput, PODIData.Machine.TileLocation, "Input.Stack", PreviousAmountInserted, DesiredNewValue, NewAmountInserted, Effect); } }
/// <summary>Intended to be invoked whenever the player inserts materials into a machine that requires inputs, such as when placing copper ore into a furnace.</summary> private static void OnInputsInserted(PerformObjectDropInData PODIData) { if (PODIData == null || PODIData.CurrentHeldObject == null || PODIData.Input == null || !Context.IsMainPlayer) { return; } SObject Machine = PODIData.Machine; if (Machine == null || !Machine.TryGetCombinedQuantity(out int CombinedQuantity)) { return; } // Compute the maximum multiplier we can apply to the input and output based on how many more of the inputs the player has int PreviousInputQuantityUsed = PODIData.PreviousInputQuantity - PODIData.CurrentInputQuantity; double MaxMultiplier = PreviousInputQuantityUsed == 0 ? PODIData.CurrentInputQuantity : Math.Abs(PODIData.PreviousInputQuantity * 1.0 / PreviousInputQuantityUsed); // Modify the output int PreviousOutputStack = PODIData.CurrentHeldObjectQuantity; int NewOutputStack = ComputeModifiedStack(CombinedQuantity, MaxMultiplier, PreviousOutputStack, out double OutputEffect, out double DesiredNewOutputValue); PODIData.CurrentHeldObject.Stack = NewOutputStack; Machine.SetHasModifiedOutput(true); ModEntry.LogTrace(CombinedQuantity, PODIData.Machine, PODIData.Machine.TileLocation, "HeldObject.Stack", PreviousOutputStack, DesiredNewOutputValue, NewOutputStack, OutputEffect); // Modify the input int CurrentInputQuantityUsed; double InputEffect; double DesiredNewInputValue; if (PreviousInputQuantityUsed <= 0) { // No clue why, but for some machines the game hasn't actually taken the input yet by the time Object.performObjectDropIn finishes. // so assume the input amount was = to 1. CurrentInputQuantityUsed = ComputeModifiedStack(CombinedQuantity, MaxMultiplier, 1, out InputEffect, out DesiredNewInputValue) - 1 - Math.Abs(PreviousInputQuantityUsed); } else { CurrentInputQuantityUsed = ComputeModifiedStack(CombinedQuantity, MaxMultiplier, PreviousInputQuantityUsed, out InputEffect, out DesiredNewInputValue); } int NewInputStack = PODIData.PreviousInputQuantity - CurrentInputQuantityUsed; PODIData.Input.Stack = NewInputStack; if (NewInputStack <= 0) { if (PODIData.WasInputInInventory) { PODIData.Farmer.removeItemFromInventory(PODIData.Input); } else { PODIData.Input.Stack = 1; // Just a failsafe to avoid glitched out Items with zero quantity, such as if the input came from a chest due to the Automate mod } } }
public static void OnInputsInserted(PerformObjectDropInData PODIData, int AugmentorQuantity) { #if LEGACYCODE if (MachineInfo.TryGetMachineInfo(PODIData.Machine, out MachineInfo Info)) { if (!Info.AttachableAugmentors.Contains(AugmentorType.Quality) || AugmentorQuantity <= 0 || !Info.RequiresInput) { return; } if (Info.IsFurnace() && Info.TryGetUpgradedQuality(PODIData.CurrentHeldObject, out Object UpgradedObject)) { double Effect = ComputeEffect(AugmentorQuantity, Info.RequiresInput); bool Success = WeightedRound(Effect) == 1; if (Success) { PODIData.Machine.heldObject.Value = UpgradedObject; } MachineAugmentorsMod.LogTrace(AugmentorType.Quality, AugmentorQuantity, PODIData.Machine, Info.RequiresInput, PODIData.Machine.TileLocation, "HeldObject.Quality", 0, Effect, Success ? 1 : 0, Effect); } else if (Info.HasQualityProducts) { int PreviousQuality = PODIData.CurrentHeldObject.Quality; int NewQuality = ComputeNewValue(AugmentorQuantity, PreviousQuality, Info.RequiresInput, out double Effect, out double DesiredNewValue); PODIData.CurrentHeldObject.Quality = NewQuality; MachineAugmentorsMod.LogTrace(AugmentorType.Quality, AugmentorQuantity, PODIData.Machine, Info.RequiresInput, PODIData.Machine.TileLocation, "HeldObject.Quality", PreviousQuality, DesiredNewValue, NewQuality, Effect); } } #endif if (MachineInfo.TryGetMachineInfo(PODIData.Machine, out MachineInfo Info)) { if (!Info.AttachableAugmentors.Contains(AugmentorType.Quality) || AugmentorQuantity <= 0 || !Info.RequiresInput) { return; } if (Info.IsFurnace() && Info.TryGetUpgradedQuality(PODIData.CurrentHeldObject, out Object UpgradedObject)) { double Effect = ComputeEffect(AugmentorQuantity, Info.RequiresInput); bool Success = WeightedRound(Effect) == 1; if (Success) { PODIData.Machine.heldObject.Value = UpgradedObject; } MachineAugmentorsMod.LogTrace(AugmentorType.Quality, AugmentorQuantity, PODIData.Machine, Info.RequiresInput, PODIData.Machine.TileLocation, "HeldObject.Quality", 0, Effect, Success ? 1 : 0, Effect); } } }
public static void OnInputsInserted(PerformObjectDropInData PODIData, int AugmentorQuantity) { #if LEGACYCODE if (MachineInfo.TryGetMachineInfo(PODIData.Machine, out MachineInfo Info)) { if (!Info.AttachableAugmentors.Contains(AugmentorType.Speed) || AugmentorQuantity <= 0 || !Info.RequiresInput || PODIData.Machine.readyForHarvest.Value) { return; } int PreviousMinutes = PODIData.CurrentMinutesUntilReady; int NewMinutes = ComputeNewValue(AugmentorQuantity, PreviousMinutes, Info.RequiresInput, out double Effect, out double DesiredNewValue); if (PreviousMinutes != NewMinutes) { // Find the GameLocation of the Machine // (Possible TODO: If using Automate mod, may need to iterate all GameLocations until finding the one where GameLocation.Objects[Machine Tile Location] is the Machine) GameLocation MachineLocation = null; if (Game1.player.currentLocation.Objects.TryGetValue(PODIData.Machine.TileLocation, out Object PlacedMachine) && PlacedMachine == PODIData.Machine) { MachineLocation = Game1.player.currentLocation; } // There seems to be a bug where there is no product if the machine is instantly done processing. //NewMinutes = Math.Max(10, NewMinutes); // temporary fix - require at least one 10-minute processing cycle // It looks like Object.checkForAction happens right AFTER Object.performObjectDropIn, and checkForAction is setting Object.heldObject=null if Object.readyForHarvest=true // So set a flag that tells GamePatches.CheckForAction_Prefix to skip execution if (NewMinutes <= 0) { GamePatches.SkipNextCheckForAction = true; } if (MachineLocation != null) { int Elapsed = PreviousMinutes - NewMinutes; PODIData.Machine.minutesElapsed(Elapsed, MachineLocation); } else { PODIData.Machine.MinutesUntilReady = NewMinutes; if (NewMinutes <= 0) { PODIData.Machine.readyForHarvest.Value = true; } } } MachineAugmentorsMod.LogTrace(AugmentorType.Speed, AugmentorQuantity, PODIData.Machine, Info.RequiresInput, PODIData.Machine.TileLocation, "HeldObject.MinutesUntilReady", PreviousMinutes, DesiredNewValue, NewMinutes, Effect); } #endif }
internal void OnInputsInserted(PerformObjectDropInData PODIData) { if (!PODIData.IsLocalPlayer) { return; } // This point of the code should be reached when placing an input item into a machine that requires inputs, // such as when placing Copper Ore into a furnace if (TryFindAugmentedTile(PODIData.Machine, PODIData.Machine.TileLocation, out AugmentedTile AT)) { foreach (KeyValuePair <AugmentorType, int> KVP in GetOrderedEnumerable(AT.Quantities)) { AugmentorType Type = KVP.Key; int AttachedQuantity = KVP.Value; if (AttachedQuantity > 0) { if (Type == AugmentorType.Output) { OutputAugmentor.OnInputsInserted(PODIData, AttachedQuantity); } else if (Type == AugmentorType.Speed) { SpeedAugmentor.OnInputsInserted(PODIData, AttachedQuantity); } else if (Type == AugmentorType.Efficiency) { EfficiencyAugmentor.OnInputsInserted(PODIData, AttachedQuantity); } else if (Type == AugmentorType.Quality) { QualityAugmentor.OnInputsInserted(PODIData, AttachedQuantity); } else if (Type == AugmentorType.Production) { ProductionAugmentor.OnInputsInserted(PODIData, AttachedQuantity); } else if (Type == AugmentorType.Duplication) { DuplicationAugmentor.OnInputsInserted(PODIData, AttachedQuantity); } else { throw new NotImplementedException(string.Format("Unrecognized AugmentorType: {0}", Type.ToString())); } } } } }
public static void OnInputsInserted(PerformObjectDropInData PODIData, int AugmentorQuantity) { #if LEGACYCODE if (MachineInfo.TryGetMachineInfo(PODIData.Machine, out MachineInfo Info)) { if (!Info.AttachableAugmentors.Contains(AugmentorType.Output) || !Info.RequiresInput || PODIData.CurrentHeldObject == null) { return; } int PreviousStack = PODIData.CurrentHeldObjectQuantity; int NewStack = ComputeNewValue(AugmentorQuantity, PreviousStack, Info.RequiresInput, out double Effect, out double DesiredNewValue); PODIData.CurrentHeldObject.Stack = NewStack; MachineAugmentorsMod.LogTrace(AugmentorType.Output, AugmentorQuantity, PODIData.Machine, Info.RequiresInput, PODIData.Machine.TileLocation, "HeldObject.Stack", PreviousStack, DesiredNewValue, NewStack, Effect); } #endif }
public static bool Prefix(SObject __instance, Item dropInItem, bool probe, Farmer who, ref bool __result) { try { if (probe) { PODIData = null; } else { PODIData = new PerformObjectDropInData(who, __instance, dropInItem); //ModEntry.Logger.Log(string.Format("{0} Prefix: {0} ({1})", nameof(PerformObjectDropInActionPatch), dropInItem.DisplayName, dropInItem.Stack), LogLevel.Info); } return(true); } catch (Exception ex) { ModEntry.Logger.Log(string.Format("Unhandled Error in {0}.{1}:\n{2}", nameof(PerformObjectDropInActionPatch), nameof(Prefix), ex), LogLevel.Error); PODIData = null; return(true); } }
public static bool PerformObjectDropInAction_Prefix(Object __instance, Item dropInItem, bool probe, Farmer who, ref bool __result) { try { if (probe) { PODIData = null; } else { PODIData = new PerformObjectDropInData(who, __instance, dropInItem); //MachineAugmentorsMod.ModInstance.Monitor.Log(string.Format("Prefix: {0} ({1})", dropInItem.DisplayName, dropInItem.Stack), LogLevel.Info); } return(true); } catch (Exception ex) { MachineAugmentorsMod.ModInstance.Monitor.Log(string.Format("Unhandled Error in {0}:\n{1}", nameof(PerformObjectDropInAction_Prefix), ex), LogLevel.Error); PODIData = null; return(true); } }
public static void OnInputsInserted(PerformObjectDropInData PODIData, int AugmentorQuantity) { if (MachineInfo.TryGetMachineInfo(PODIData.Machine, out MachineInfo Info)) { if (!Info.AttachableAugmentors.Contains(AugmentorType.Production) || AugmentorQuantity <= 0 || !Info.RequiresInput || PODIData.CurrentHeldObject == null || PODIData.Input == null) { return; } // Compute the maximum multiplier we can apply to the input and output based on how many more of the inputs the player has int PreviousInputQuantityUsed = PODIData.PreviousInputQuantity - PODIData.CurrentInputQuantity; double MaxMultiplier = PreviousInputQuantityUsed == 0 ? int.MaxValue : Math.Abs(PODIData.PreviousInputQuantity * 1.0 / PreviousInputQuantityUsed); // Modify the output int PreviousOutputStack = PODIData.CurrentHeldObjectQuantity; int NewOutputStack = ComputeNewValue(AugmentorQuantity, MaxMultiplier, PreviousOutputStack, Info.RequiresInput, out double OutputEffect, out double DesiredNewOutputValue); PODIData.CurrentHeldObject.Stack = NewOutputStack; MachineAugmentorsMod.LogTrace(AugmentorType.Production, AugmentorQuantity, PODIData.Machine, Info.RequiresInput, PODIData.Machine.TileLocation, "HeldObject.Stack", PreviousOutputStack, DesiredNewOutputValue, NewOutputStack, OutputEffect); // Modify the input int CurrentInputQuantityUsed; double InputEffect; double DesiredNewInputValue; if (PreviousInputQuantityUsed <= 0) { // No clue why, but for some machines the game hasn't actually taken the input yet by the time Object.performObjectDropIn finishes. // so assume the input amount was = to 1. CurrentInputQuantityUsed = ComputeNewValue(AugmentorQuantity, MaxMultiplier, 1, Info.RequiresInput, out InputEffect, out DesiredNewInputValue) - 1 - Math.Abs(PreviousInputQuantityUsed); // -1 because we assume it required at least 1 input, -PreviousInputQuantityUsed because EfficiencyAugmentor may have set the quantity to a negative value to allow saving a material } else { CurrentInputQuantityUsed = ComputeNewValue(AugmentorQuantity, MaxMultiplier, PreviousInputQuantityUsed, Info.RequiresInput, out InputEffect, out DesiredNewInputValue); } int NewInputStack = PODIData.PreviousInputQuantity - CurrentInputQuantityUsed; PODIData.Input.Stack = NewInputStack; if (NewInputStack <= 0) { if (PODIData.WasInputInInventory) { Game1.player.removeItemFromInventory(PODIData.Input); } else { PODIData.Input.Stack = 1; // Just a failsafe to avoid glitched out Items with zero quantity, such as if the input came from a chest due to the Automate mod } } //// Modify the input //int CurrentInputQuantityUsed = ComputeNewValue(AugmentorQuantity, MaxMultiplier, PreviousInputQuantityUsed, Info.RequiresInput, out double InputEffect, out double DesiredNewInputValue); //int NewInputStack = PODIData.PreviousInputQuantity - CurrentInputQuantityUsed; //PODIData.Input.Stack = NewInputStack; //if (NewInputStack <= 0) //{ // if (PODIData.WasInputInInventory) // Game1.player.removeItemFromInventory(PODIData.Input); // else // { // PODIData.Input.Stack = 1; // Just a failsafe to avoid glitched out Items with zero quantity, such as if the input came from a chest due to the Automate mod // } //} MachineAugmentorsMod.LogTrace(AugmentorType.Production, AugmentorQuantity, PODIData.Machine, Info.RequiresInput, PODIData.Machine.TileLocation, "Input-UsedAmount", PreviousInputQuantityUsed, DesiredNewInputValue, CurrentInputQuantityUsed, InputEffect); } }
/// <summary>Intended to be invoked whenever the player inserts materials into a machine that requires inputs, such as when placing copper ore into a furnace.</summary> private static void OnInputsInserted(PerformObjectDropInData PODIData) { if (PODIData == null || PODIData.CurrentHeldObject == null || PODIData.Input == null) { return; } bool IsCurrentPlayer = (!Context.IsMultiplayer && !Context.IsSplitScreen) || PODIData.Farmer.UniqueMultiplayerID == Game1.player.UniqueMultiplayerID; if (!IsCurrentPlayer) { return; } SObject Machine = PODIData.Machine; if (!ModEntry.UserConfig.ShouldModifyInputsAndOutputs(Machine) || !Machine.TryGetCombinedQuantity(out int CombinedQuantity)) { return; } int SecondaryInputQuantityAvailable = int.MaxValue; if (PODIData.Input.IsOre() && PODIData.Farmer != null && ModEntry.UserConfig.FurnaceMultiplyCoalInputs) { SecondaryInputQuantityAvailable = PODIData.Farmer.Items.Where(x => x != null && x.IsCoal()).Sum(x => x.Stack); } // Compute the maximum multiplier we can apply to the input and output based on how many more of the inputs the player has int PreviousInputQuantityUsed = PODIData.PreviousInputQuantity - PODIData.CurrentInputQuantity; double MaxMultiplier = Math.Min(SecondaryInputQuantityAvailable, PreviousInputQuantityUsed == 0 ? PODIData.CurrentInputQuantity : Math.Abs(PODIData.PreviousInputQuantity * 1.0 / PreviousInputQuantityUsed)); // Modify the output int PreviousOutputStack = PODIData.CurrentHeldObjectQuantity; int NewOutputStack = ComputeModifiedStack(CombinedQuantity, MaxMultiplier, PreviousOutputStack, out double OutputEffect, out double DesiredNewOutputValue); PODIData.CurrentHeldObject.Stack = NewOutputStack; Machine.SetHasModifiedOutput(true); ModEntry.LogTrace(CombinedQuantity, PODIData.Machine, PODIData.Machine.TileLocation, "HeldObject.Stack", PreviousOutputStack, DesiredNewOutputValue, NewOutputStack, OutputEffect); // Modify the input int CurrentInputQuantityUsed; double InputEffect; double DesiredNewInputValue; if (PreviousInputQuantityUsed <= 0) { // No clue why, but for some machines the game hasn't actually taken the input yet by the time Object.performObjectDropIn finishes. // so assume the input amount was = to 1. CurrentInputQuantityUsed = ComputeModifiedStack(CombinedQuantity, MaxMultiplier, 1, out InputEffect, out DesiredNewInputValue) - 1 - Math.Abs(PreviousInputQuantityUsed); } else { CurrentInputQuantityUsed = ComputeModifiedStack(CombinedQuantity, MaxMultiplier, PreviousInputQuantityUsed, out InputEffect, out DesiredNewInputValue); } int NewInputStack = PODIData.PreviousInputQuantity - CurrentInputQuantityUsed; PODIData.Input.Stack = NewInputStack; if (NewInputStack <= 0) { if (PODIData.WasInputInInventory) { PODIData.Farmer.removeItemFromInventory(PODIData.Input); } else { PODIData.Input.Stack = 1; // Just a failsafe to avoid glitched out Items with zero quantity, such as if the input came from a chest due to the Automate mod } } if (PODIData.Input.IsOre() && PODIData.Farmer != null && ModEntry.UserConfig.FurnaceMultiplyCoalInputs) { int RemainingCoalToConsume = RNGHelpers.WeightedRound(OutputEffect) - 1; // 1 coal was already automatically consumed by the vanilla function for (int i = 0; i < PODIData.Farmer.Items.Count; i++) { Item CurrentItem = PODIData.Farmer.Items[i]; if (CurrentItem != null && CurrentItem.IsCoal()) { int AmountToConsume = Math.Min(CurrentItem.Stack, RemainingCoalToConsume); CurrentItem.Stack -= AmountToConsume; RemainingCoalToConsume -= AmountToConsume; if (CurrentItem.Stack <= 0) { PODIData.Farmer.removeItemFromInventory(i); } if (RemainingCoalToConsume <= 0) { break; } } } } }