Jump to content

HAB

Member
  • Posts

    27
  • Joined

  • Last visited

Everything posted by HAB

  1. HAB

    Fixed

    using System; using Newtonsoft.Json; using Oxide.Core; using System.Collections.Generic; using System.Linq; using UnityEngine; using Oxide.Core.Plugins; namespace Oxide.Plugins { [Info("The Door Knocker", "Cannabis", "1.4.4")] [Description("Allows players to shoot multiple rockets at once with configurable settings")] class TheDoorKnocker : RustPlugin { #region Declarations private const string useperm = "thedoorknocker.use"; private SavedData data; #endregion #region Oxide Hooks void Init() { // Register permissions foreach (var kvp in config.maxRocketPermission) { permission.RegisterPermission(kvp.Key, this); } permission.RegisterPermission(useperm, this); // Register language messages and command lang.RegisterMessages(_messages, this); cmd.AddChatCommand(config.rocketamtcmd, this, nameof(CmdHandleRockets)); // Load data data = SavedData.Load(); // Clean old data if enabled if (config.cleanOldData) { timer.Once(5f, () => { foreach (var userID in data.playerData.Keys.ToList()) { if (data.playerData[userID]?.lastSeen == null) continue; TimeSpan timeDifference = DateTime.UtcNow - data.playerData[userID].lastSeen; if (timeDifference.TotalDays >= config.daysSinceLastSeenToClean) { data.playerData.Remove(userID); } } data.Save(); }); } } void OnPlayerConnected(BasePlayer player) { if (player == null || !permission.UserHasPermission(player.UserIDString, useperm) || data.playerData.ContainsKey(player.userID)) return; InitializePlayerData(player.userID); } void OnUserPermissionGranted(string id, string permName) { if (!ulong.TryParse(id, out ulong userID) || (permName != useperm && !config.maxRocketPermission.ContainsKey(permName))) return; if (!data.playerData.ContainsKey(userID)) { InitializePlayerData(userID); } } void OnUserGroupAdded(string playerId, string groupName) { if (!ulong.TryParse(playerId, out ulong userID)) return; string[] permissions = permission.GetGroupPermissions(groupName); if (!permissions.Contains(useperm) || data.playerData.ContainsKey(userID)) return; InitializePlayerData(userID); } void OnNewSave(string filename) { if (config.wipeOnWipe) { data = new SavedData(); data.Save(); } } void OnPlayerDisconnected(BasePlayer player, string reason) { if (player != null && data.playerData.ContainsKey(player.userID)) { data.playerData[player.userID].lastSeen = DateTime.UtcNow; data.Save(); } } void OnUserPermissionRevoked(string id, string permName) { if (!ulong.TryParse(id, out ulong userID)) return; BasePlayer player = BasePlayer.FindByID(userID); if (player == null) return; if (permName == useperm && data.playerData.ContainsKey(userID)) { data.playerData.Remove(userID); data.Save(); } else if (config.maxRocketPermission.ContainsKey(permName) && permission.UserHasPermission(id, useperm) && data.playerData.ContainsKey(userID)) { data.playerData[userID].playerRockets = config.defaultPlayerData.amount; data.Save(); } } void OnRocketLaunched(BasePlayer player, BaseEntity entity) { if (player == null || !permission.UserHasPermission(player.UserIDString, useperm) || !data.playerData.ContainsKey(player.userID) || !data.playerData[player.userID].rocketsEnabled) return; Item heldItem = player.GetActiveItem(); if (heldItem?.info?.shortname != "rocket.launcher") return; BaseProjectile.Magazine rocketMagazine = player.GetHeldEntity()?.GetComponent<BaseProjectile>()?.primaryMagazine; if (rocketMagazine == null) return; int rocketsSent = Math.Min(data.playerData[player.userID].playerRockets, GetMaxRockets(player)); if (rocketsSent < 1) return; int rocketType; string ammoType = rocketMagazine.ammoType?.shortname ?? string.Empty; switch (ammoType) { case "ammo.rocket.basic": if (config.blockTypes.Contains("basic") || !data.playerData[player.userID].playerPreferences.basicRocket) return; rocketType = 1; break; case "ammo.rocket.hv": if (config.blockTypes.Contains("hv") || !data.playerData[player.userID].playerPreferences.hvRocket) return; rocketType = 2; break; case "ammo.rocket.fire": if (config.blockTypes.Contains("fire") || !data.playerData[player.userID].playerPreferences.fireRocket) return; rocketType = 3; break; case "ammo.rocket.smoke": if (config.blockTypes.Contains("smoke") || !data.playerData[player.userID].playerPreferences.smokeRocket) return; rocketType = 4; break; default: if (!data.playerData[player.userID].playerPreferences.basicRocket) return; rocketType = 1; break; } SpawnRockets(player, rocketsSent, rocketType); } void Unload() { data.Save(); } #endregion #region Commands private void CmdHandleRockets(BasePlayer player, string command, string[] args) { if (player == null || !permission.UserHasPermission(player.UserIDString, useperm)) { PrintToChat(player, lang.GetMessage("NoPermission", this, player.UserIDString)); return; } if (!data.playerData.ContainsKey(player.userID)) { InitializePlayerData(player.userID); } if (args.Length == 0 || args.Length > 2) { PrintToChat(player, lang.GetMessage("NoArgs", this, player.UserIDString)); return; } int maxRockets = GetMaxRockets(player); if (maxRockets == 0) { PrintToChat(player, lang.GetMessage("InvalidRockets", this, player.UserIDString)); return; } if (int.TryParse(args[0], out int amount)) { if (amount > maxRockets) { PrintToChat(player, string.Format(lang.GetMessage("TooMany", this, player.UserIDString), maxRockets)); return; } if (amount <= 0) { PrintToChat(player, lang.GetMessage("NoZero", this, player.UserIDString)); return; } data.UpdateAmount(player.userID, amount); PrintToChat(player, string.Format(lang.GetMessage("ChangeRockets", this, player.UserIDString), amount)); return; } if (bool.TryParse(args[0], out bool enabled)) { data.UpdateEnabled(player.userID, enabled); PrintToChat(player, lang.GetMessage(enabled ? "TurnedOn" : "TurnedOff", this, player.UserIDString)); return; } if (args[0].ToLower() == "toggle" && args.Length == 2) { string type = args[1].ToLower(); if (config.blockTypes.Contains(type)) { PrintToChat(player, string.Format(lang.GetMessage("TypeDisabledTryToggle", this, player.UserIDString), type)); return; } bool newState; string displayName = type; switch (type) { case "basic": newState = !data.playerData[player.userID].playerPreferences.basicRocket; data.playerData[player.userID].playerPreferences.basicRocket = newState; break; case "hv": newState = !data.playerData[player.userID].playerPreferences.hvRocket; data.playerData[player.userID].playerPreferences.hvRocket = newState; break; case "fire": newState = !data.playerData[player.userID].playerPreferences.fireRocket; data.playerData[player.userID].playerPreferences.fireRocket = newState; displayName = "incendiary"; break; case "smoke": newState = !data.playerData[player.userID].playerPreferences.smokeRocket; data.playerData[player.userID].playerPreferences.smokeRocket = newState; break; default: PrintToChat(player, lang.GetMessage("InvalidTypeToggle", this, player.UserIDString)); return; } PrintToChat(player, string.Format(lang.GetMessage("TypeToggled", this, player.UserIDString), newState ? "enabled" : "disabled", displayName)); data.Save(); } } #endregion #region Helpers private void InitializePlayerData(ulong userID) { data.playerData.Add(userID, new TheDoorKnockerData { lastSeen = DateTime.UtcNow, playerPreferences = new TheDoorKnockerPlayerPreferences { basicRocket = true, hvRocket = true, fireRocket = false, smokeRocket = false }, playerRockets = config.defaultPlayerData.amount, rocketsEnabled = config.defaultPlayerData.enabled }); data.Save(); } private int GetMaxRockets(BasePlayer player) { int max = config.defaultPlayerData.amount; foreach (var kvp in config.maxRocketPermission) { if (permission.UserHasPermission(player.UserIDString, kvp.Key)) { max = Math.Max(max, kvp.Value); } } return max; } private void SpawnRockets(BasePlayer player, int amount, int type) { if (amount <= 1) return; Item item = player.GetActiveItem(); if (item?.info?.shortname != "rocket.launcher" || item.condition <= 0) return; string rocketPrefab; int rocketId; float velocity; switch (type) { case 1: rocketPrefab = "assets/prefabs/ammo/rocket/rocket_basic.prefab"; rocketId = -742865266; velocity = config.rocketSpeeds.basicVelocity; break; case 2: rocketPrefab = "assets/prefabs/ammo/rocket/rocket_hv.prefab"; rocketId = -1841918730; velocity = config.rocketSpeeds.hvVelocity; break; case 3: rocketPrefab = "assets/prefabs/ammo/rocket/rocket_fire.prefab"; rocketId = 1638322904; velocity = config.rocketSpeeds.fireVelocity; break; case 4: rocketPrefab = "assets/prefabs/ammo/rocket/rocket_smoke.prefab"; rocketId = -17123659; velocity = config.rocketSpeeds.smokeVelocity; break; default: return; } for (int i = 0; i < amount - 1; i++) { if (config.takeDurability) { item.LoseCondition(config.durabilityAmount); if (item.condition <= 0) return; } Vector3 aimDirection = Quaternion.Euler(player.serverInput.current.aimAngles) * Vector3.forward; aimDirection = Quaternion.Euler( UnityEngine.Random.Range(-config.aimCone, config.aimCone), UnityEngine.Random.Range(-config.aimCone, config.aimCone), 0) * aimDirection; Quaternion rocketRotation = Quaternion.Euler(player.serverInput.current.aimAngles); TimedExplosive rocket = GameManager.server.CreateEntity(rocketPrefab, player.eyes.position + aimDirection * 1.5f, rocketRotation) as TimedExplosive; if (rocket == null) continue; rocket.creatorEntity = player; ServerProjectile rocketProjectile = rocket.GetComponent<ServerProjectile>(); if (rocketProjectile != null) { rocketProjectile.InitializeVelocity(aimDirection * velocity); } rocket.Spawn(); } } #endregion #region Configuration private static ConfigData config; private class ConfigData { [JsonProperty(PropertyName = "Permissions and allowed max rockets per permission")] public Dictionary<string, int> maxRocketPermission { get; set; } [JsonProperty(PropertyName = "Chat command")] public string rocketamtcmd { get; set; } [JsonProperty(PropertyName = "Rocket spread (degrees)")] public float aimCone { get; set; } [JsonProperty(PropertyName = "Blocked rocket types")] public List<string> blockTypes { get; set; } [JsonProperty(PropertyName = "Default player data")] public TheDoorKnockerDefaultPlayerData defaultPlayerData { get; set; } [JsonProperty(PropertyName = "Clean up old player data")] public bool cleanOldData { get; set; } [JsonProperty(PropertyName = "Days before cleaning old data")] public double daysSinceLastSeenToClean { get; set; } [JsonProperty(PropertyName = "Take durability per extra rocket")] public bool takeDurability { get; set; } [JsonProperty(PropertyName = "Durability taken per rocket")] public int durabilityAmount { get; set; } [JsonProperty(PropertyName = "Wipe data on map wipe")] public bool wipeOnWipe { get; set; } [JsonProperty(PropertyName = "Custom rocket speeds")] public TheDoorKnockerRocketSpeeds rocketSpeeds { get; set; } } private ConfigData GetDefaultConfig() { return new ConfigData { maxRocketPermission = new Dictionary<string, int> { {"thedoorknocker.basic", 2}, {"thedoorknocker.vip", 3}, {"thedoorknocker.example", 69} }, rocketamtcmd = "tdk", aimCone = 4.0f, blockTypes = new List<string> { "smoke", "fire" }, cleanOldData = true, daysSinceLastSeenToClean = 7, takeDurability = false, durabilityAmount = 1, wipeOnWipe = true, defaultPlayerData = new TheDoorKnockerDefaultPlayerData { amount = 2, enabled = true }, rocketSpeeds = new TheDoorKnockerRocketSpeeds { basicVelocity = 30, fireVelocity = 30, hvVelocity = 60, smokeVelocity = 30 } }; } protected override void LoadConfig() { base.LoadConfig(); try { config = Config.ReadObject<ConfigData>(); if (config == null) { LoadDefaultConfig(); } } catch { PrintError("Configuration file is corrupt! Loading default config..."); LoadDefaultConfig(); } ValidateConfig(); SaveConfig(); } protected override void LoadDefaultConfig() { config = GetDefaultConfig(); } protected override void SaveConfig() { Config.WriteObject(config); } private void ValidateConfig() { bool changed = false; if (config.maxRocketPermission == null) { config.maxRocketPermission = GetDefaultConfig().maxRocketPermission; changed = true; } if (string.IsNullOrEmpty(config.rocketamtcmd)) { config.rocketamtcmd = "tdk"; changed = true; } if (config.blockTypes == null) { config.blockTypes = GetDefaultConfig().blockTypes; changed = true; } if (config.defaultPlayerData == null) { config.defaultPlayerData = GetDefaultConfig().defaultPlayerData; changed = true; } if (config.rocketSpeeds == null) { config.rocketSpeeds = GetDefaultConfig().rocketSpeeds; changed = true; } // Add more validations if necessary if (changed) { PrintWarning("Invalid config values detected! Corrected and saving changes."); SaveConfig(); } } public class TheDoorKnockerDefaultPlayerData { [JsonProperty(PropertyName = "Enable TDK by default")] public bool enabled { get; set; } [JsonProperty(PropertyName = "Default rocket amount")] public int amount { get; set; } } public class TheDoorKnockerRocketSpeeds { [JsonProperty(PropertyName = "Basic rocket speed")] public int basicVelocity { get; set; } [JsonProperty(PropertyName = "HV rocket speed")] public int hvVelocity { get; set; } [JsonProperty(PropertyName = "Smoke rocket speed")] public int smokeVelocity { get; set; } [JsonProperty(PropertyName = "Fire rocket speed")] public int fireVelocity { get; set; } } #endregion #region Data Handling class SavedData { [JsonProperty("Player data")] public Dictionary<ulong, TheDoorKnockerData> playerData = new Dictionary<ulong, TheDoorKnockerData>(); public static SavedData Load() => Interface.Oxide.DataFileSystem.ReadObject<SavedData>("TheDoorKnocker/TDK_playerData") ?? new SavedData(); public void Save() => Interface.Oxide.DataFileSystem.WriteObject("TheDoorKnocker/TDK_playerData", this); public void UpdateAmount(ulong userId, int rocketAmount) { if (playerData.ContainsKey(userId)) { playerData[userId].playerRockets = rocketAmount; Save(); } } public void UpdateEnabled(ulong userId, bool enabled) { if (playerData.ContainsKey(userId)) { playerData[userId].rocketsEnabled = enabled; Save(); } } } public class TheDoorKnockerData { [JsonProperty(PropertyName = "Rocket count")] public int playerRockets { get; set; } [JsonProperty(PropertyName = "Rockets enabled")] public bool rocketsEnabled { get; set; } [JsonProperty(PropertyName = "Last seen")] public DateTime lastSeen { get; set; } [JsonProperty(PropertyName = "Player preferences")] public TheDoorKnockerPlayerPreferences playerPreferences { get; set; } } public class TheDoorKnockerPlayerPreferences { public bool basicRocket { get; set; } public bool hvRocket { get; set; } public bool fireRocket { get; set; } public bool smokeRocket { get; set; } } #endregion #region Language Dictionary<string, string> _messages = new Dictionary<string, string> { { "NoPermission", "You lack <color=#FF0000>permission</color> to use this command." }, { "TurnedOn", "You have <color=#00FBFF>enabled</color> multiple rockets per shot." }, { "TurnedOff", "You have <color=#FF0000>disabled</color> multiple rockets per shot." }, { "ChangeRockets", "Successfully changed rockets to <color=#0394fc>{0}</color>"}, { "NoArgs", "Available arguments: <color=#03f8fc>true/false | # of rockets | toggle [basic/hv/fire/smoke]</color>"}, { "InvalidRockets", "You lack permission to launch multiple rockets.\nContact an administrator if you believe this is an error."}, { "TooMany", "You cannot set more than {0} rockets."}, { "NoZero", "Disable TheDoorKnocker instead of setting rockets to 0."}, { "InvalidTypeToggle", "Invalid type. Valid types: basic, hv, fire, smoke"}, { "TypeDisabledTryToggle", "Cannot toggle {0} rockets as they are disabled."}, { "TypeToggled", "You have {0} {1} rockets."} }; #endregion } } TheDoorKnocker.cs
  2. HAB

    Skills

    After restart, players would not have access to skills. I think this is because the method that handles permissions might occur prior to the skills plugin being loaded.. This mod just reloads the named plugins that handle each skill a bit after restart is completed to make sure that their perms get registered. I have also been having an issue with certain mods that I use for skills that will not add players to their corresponding groups, even after i reload the plugin, which works for other cases.
  3. HAB

    Skills

    ReloadAfterStartup plugin to make sure permissions are added properly after restart.
  4. HAB

    weird issue on loot/interact

    sometimes it opens loot window on one press of key sometimes it takes 2 or 3 presses
  5. HAB

    config reverts to default on reload

    That worked, thanks.
  6. i'm just trying to remove the command "s" so that it doesn't conflict with another plugin and everytime i reload, the config puts the "s" I just removed right back in. I think in whatever case, the config reverts back to default values. { "Skin Commands (skin items in you inventory": [ "skin", "s" ], TO: { "Skin Commands (skin items in you inventory": [ "skin" ],
  7. HAB

    Groups

    I meant that I am using the groups option in the skills config. "Groups": [ "OwnCasinoPremiumUse" ], This does not work. I have been doing it this way for a long time now and it has always added the player to the group and it could be seen in AdminMenu.
  8. HAB

    Groups

    This happens when I use groups in config as well.
  9. HAB

    Groups

    In AdminMenu, it does not add player name to Groups>Group Users>(Name of Group) page after purchasing a skill like it did before. Strangely though, in Groups>User Groups>(Player Name) it does add/show the group highlighted amonst the group list for the specific user after buying the skill, but it does not give the perm to the player in Permissions>Player as the perm remains unhighlighted there. Also, you cannot deselect any highlighted groups in User Group to be able to remove perms - they are stuck on.
  10. HAB

    Groups

    I am using oxide. This could be an issue with AdminMenu as well but not sure. here's an example for my config: { "Enabled": true, "Permission": "", "Type": "None", "ID (for None)": 22, "Image": "https://i.imgur.com/hJusqF8.png", "Title": "Home Casino", "Description": "Enables you to make a casino for your base.\nPlace wheel last to insure proper link between terminals.", "Shortname": "", "Stages": { "1": { "Permission (ex: skills.vip)": "", "Cost": 500.0, "Value [metabolism - value, for everyone else %]": 0.0, "Value 2": 0.0, "Commands": [], "Groups": [ "OwnCasinoPremiumUse" ], "Permissions": [ "owncasinopremium.use" ], "Required skill stages": [] } (I see the player with the perms and group listed in the skills data config)
  11. HAB

    Groups

    Custom skills do not seem to be adding players into the groups I have designated for them.
  12. This picture is at D3. Map performance is amazing btw.
  13. HAB

    Safe Highlight

    Can this detect zonemanager zones and if so, rectangular zones?
  14. when the drop-down menu is clicked, it immediately closes chat which causes the cursor to disappear.
  15. HAB

    junkyard & trainyard prefab missing

    also having reports of players falling through the map
  16. hey niko, junkyard & trainyard prefab are missing entirely from map where they should be.
  17. HAB

    Damage Bug?

    Disregard this post. Everything is working.
  18. HAB

    Exploit

    To get unfrozen, one can spawn a vehicle in front of them using vehicle license mod and ride off. One work-around might be to prevent use of chat if frozen so that commands cannot be used.
1.9m

Downloads

Total number of downloads.

8.9k

Customers

Total customers served.

131.2k

Files Sold

Total number of files sold.

2.7m

Payments Processed

Total payments processed.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.