using Harmony; using Steamworks; using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Reflection; using UnityEngine; [ModTitle("CustomToolSpeed")] [ModAuthor("traxam")] [ModDescription("Customize how fast your tools are.")] [ModWallpaperUrl("https://traxam.s-ul.eu/DLQfta1O")] [ModIconUrl("https://traxam.s-ul.eu/jzonnucQ")] [ModVersion("1.1.1")] [RaftVersion("Update 9.05 (3847312)")] [ModVersionCheckUrl("https://www.raftmodding.com/api/v1/mods/customtoolspeed/version.txt")] public class CustomToolSpeedMod : Mod { private readonly string PLAYER_PREFS_TOOL_SPEED = "traxam.CustomToolSpeed.toolSpeed"; private readonly string HARMONY_ID = "traxam.CustomToolSpeed"; private Dictionary originalToolSpeeds; public static float currentToolsSpeed = 1; private HarmonyInstance harmonyInstance; public void Start() { originalToolSpeeds = new Dictionary(); SO_GameModeValue[] gameModeValues = (SO_GameModeValue[]) Traverse.Create(typeof(GameModeValueManager)).Field("gameModeValues").GetValue(); for (var i = 0; i < gameModeValues.Length; i++) { originalToolSpeeds[gameModeValues[i].gameMode] = gameModeValues[i].toolVariables.removeSpeedMultiplier; } RConsole.registerCommand(typeof(CustomToolSpeedMod), "Change the tool speed", "toolspeed", HandleToolSpeedCommand); harmonyInstance = HarmonyInstance.Create(HARMONY_ID); harmonyInstance.PatchAll(Assembly.GetExecutingAssembly()); Info("Mod was loaded successfully!"); if (PlayerPrefs.HasKey(PLAYER_PREFS_TOOL_SPEED)) { float toolSpeed = PlayerPrefs.GetFloat(PLAYER_PREFS_TOOL_SPEED); SetToolSpeedMultiplier(toolSpeed, false); FollowUpLog("The current tool speed is " + currentToolsSpeed + "."); } FollowUpLog("Type toolspeed to change the tool speed, i.e. toolspeed 2.5 (1 is the default tool speed)."); } public void HandleToolSpeedCommand() { string[] arguments = RConsole.lastCommands.LastOrDefault().Split(new string[]{" "}, StringSplitOptions.RemoveEmptyEntries); if (arguments.Length < 2) { Info("The current tool speed is " + currentToolsSpeed + "."); FollowUpLog("Type toolspeed to change the tool speed, i.e. toolspeed 2.5 (1 is the default tool speed)."); } else { float value; try { value = float.Parse(arguments[1], CultureInfo.InvariantCulture); if (value <= 0) { Error("The provided tool speed (" + arguments[1] + ") is not a positive value."); FollowUpLog("Please provide a positive decimal tool speed value, i.e. toolspeed 2.5 (1 is the default tool speed)."); } else { SetToolSpeedMultiplier(value, true); Info("Tool speed was set to " + value + ". Type toolspeed 1 to reset it."); } } catch (FormatException e) { Error("" + arguments[1] + " is not a valid value. Please provide a positive decimal tool speed value, i.e. toolspeed 2.5 (1 is the default tool speed)."); } } } public void SetToolSpeedMultiplier(float multiplier, bool save) { SO_GameModeValue[] gameModeValues = (SO_GameModeValue[]) Traverse.Create(typeof(GameModeValueManager)).Field("gameModeValues").GetValue(); for (var i = 0; i < gameModeValues.Length; i++) { gameModeValues[i].toolVariables.removeSpeedMultiplier = originalToolSpeeds[gameModeValues[i].gameMode] * multiplier; } currentToolsSpeed = multiplier; if (save) { PlayerPrefs.SetFloat(PLAYER_PREFS_TOOL_SPEED, multiplier); PlayerPrefs.Save(); } } public void OnModUnload() { harmonyInstance.UnpatchAll(HARMONY_ID); SetToolSpeedMultiplier(1, false); Info("Tool speeds were reset."); } private void Info(string message) { RConsole.Log("[info]\ttraxam's CustomToolSpeed: " + message); } private void FollowUpLog(string message) { RConsole.Log("\t" + message); } private void Error(string message) { RConsole.LogError("[error]\ttraxam's CustomToolSpeed: " + message); } [HarmonyPatch(typeof(Axe))] [HarmonyPatch("OnAxeHit")] private class AxeHitPatch { private static bool Prefix(Axe __instance, ref Network_Player ___playerNetwork, ref HarvestableTree ___currentTreeToChop, ref RaycastHit ___chopHitPoint, ref LayerMask ___hitmask, ref PlayerInventory ___playerInventory, ref AxeMode ___mode) { if (!___playerNetwork) { ___playerNetwork = __instance.GetComponentInParent(); } if (!___playerNetwork.IsLocalPlayer) { return false; } if (!__instance.gameObject.activeInHierarchy) { return false; } ___currentTreeToChop = null; if (Helper.HitAtCursor(out ___chopHitPoint, 5f, ___hitmask)) { if (___chopHitPoint.transform.tag == "Tree") { HarvestableTree componentInParent = ___chopHitPoint.transform.GetComponentInParent(); if (componentInParent != null && !componentInParent.Depleted) { ___currentTreeToChop = componentInParent; } } Message_AxeHit message_AxeHit = new Message_AxeHit(Messages.AxeHit, ___playerNetwork, ___playerNetwork.steamID); if (___currentTreeToChop != null) { message_AxeHit.treeObjectIndex = (int)___currentTreeToChop.PickupNetwork.ObjectIndex; if (Semih_Network.IsHost) { int howOften = (int) Math.Floor(CustomToolSpeedMod.currentToolsSpeed); for (int i = 0; i < howOften; i++) { ___currentTreeToChop.Harvest(___playerInventory); } } } message_AxeHit.HitPoint = ___chopHitPoint.point; message_AxeHit.HitNormal = ___chopHitPoint.normal; ___playerNetwork.Inventory.RemoveDurabillityFromHotSlot(1); if (Semih_Network.IsHost) { ___playerNetwork.Network.RPC(message_AxeHit, Target.Other, EP2PSend.k_EP2PSendReliable, NetworkChannel.Channel_Game); __instance.PlayEffect(___playerNetwork.transform.parent, message_AxeHit.HitPoint, message_AxeHit.HitNormal); } else { ___playerNetwork.SendP2P(message_AxeHit, EP2PSend.k_EP2PSendReliable, NetworkChannel.Channel_Game); } ___currentTreeToChop = null; if (___mode == AxeMode.Chopping) { ___mode = AxeMode.None; } return false; } return false; } } }