C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System.Collections.Generic;
using System;
using Newtonsoft.Json;
using Oxide.Core.Plugins;
using Oxide.Core.Configuration;
using UnityEngine;
using System.Linq;
using Facepunch;
namespace Oxide.Plugins
{
[Info("Weapon Trajectory", "Dana", "1.0.4")] //Original author Jake_Rich
[Description("Draws the trajectory of rockets and explosives.")]
public class WeaponTrajectory : RustPlugin
{
public static WeaponTrajectory _plugin;
public JSONFile<ConfigData> _settingsFile;
public ConfigData Settings { get { return _settingsFile.Instance; } }
public PlayerDataController<GrenadePlayerData> PlayerData;
public const float UpdateRate = 0.1f;
public const string Permission_Path = "weapontrajectory.show";
void Init()
{
_plugin = this;
}
void Loaded()
{
//Dont create empty config files
if (typeof(ConfigData).GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic).Length > 0)
{
_settingsFile = new JSONFile<ConfigData>($"{Name}", ConfigLocation.Config, extension: ".cfg");
}
PlayerData = new PlayerDataController<GrenadePlayerData>();
//Don't create empty lang files
if (lang_en.Count > 0)
{
lang.RegisterMessages(lang_en, this);
}
permission.RegisterPermission(Permission_Path, this);
timer.Every(UpdateRate, DoPlayerUpdate);
}
void Unload()
{
PlayerData.Unload();
}
public class ConfigData
{
public float GrenadeVelocityScale = 1.25f;
public float RocketVelocityScale = 1f;
public float HVRocketVelocityScale = 1f;
public float FireRocketVelocityScale = 1f;
public bool UsePermissions = false;
}
public class GrenadePlayerData : BasePlayerData
{
}
void DoPlayerUpdate()
{
foreach(var player in BasePlayer.activePlayerList)
{
try
{
CheckPlayerInput(player);
}
catch
{
}
}
}
void CheckPlayerInput(BasePlayer player)
{
if (player.serverInput.IsDown(BUTTON.FIRE_PRIMARY))
{
var heldItem = player.GetActiveItem();
if (heldItem.info.shortname == "grenade.f1")
{
DrawGrenadePath(player);
}
}
else if (player.serverInput.IsDown(BUTTON.FIRE_SECONDARY))
{
var heldItem = player.GetActiveItem();
if (heldItem.info.shortname == "rocket.launcher")
{
DrawRocketPath(player, heldItem.GetHeldEntity() as BaseLauncher);
}
else if(heldItem.info.shortname == "explosive.timed")
{
DrawGrenadePath(player);
}
}
}
void DrawGrenadePath(BasePlayer player)
{
if (Settings.UsePermissions)
{
if (!permission.UserHasPermission(player.UserIDString, Permission_Path) && !player.IsAdmin)
{
return;
}
}
//Puts($"{comp.maxThrowVelocity}");
//DrawArrow(player, UpdateRate, Color.green, player.eyes.position, player.eyes.position + player.eyes.BodyForward());
List<Vector3> list = Pool.GetList<Vector3>();
DoMovement(list, player.eyes.position, (player.eyes.BodyForward() * 13 + player.estimatedVelocity * 0.5f) * Settings.GrenadeVelocityScale);
for (int i = 0; i < list.Count - 1; i++)
{
DrawArrow(player, UpdateRate, Color.green, list[i], list[i+1]);
}
Pool.FreeList(ref list);
}
void DrawRocketPath(BasePlayer player,BaseLauncher launcher)
{
if (Settings.UsePermissions)
{
if (!permission.UserHasPermission(player.UserIDString, Permission_Path) && !player.IsAdmin)
{
return;
}
}
if (launcher.primaryMagazine.contents == 0)
{
return;
}
var ammoType = launcher.primaryMagazine.ammoType.GetComponent<ItemModProjectile>().projectileObject.Get().GetComponent<ServerProjectile>();
float velocityScale = Settings.RocketVelocityScale;
if (launcher.primaryMagazine.ammoType.shortname == "ammo.rocket.hv")
{
velocityScale = Settings.HVRocketVelocityScale;
}
else if (launcher.primaryMagazine.ammoType.shortname == "ammo.rocket.fire")
{
velocityScale = Settings.FireRocketVelocityScale;
}
List<Vector3> list = Pool.GetList<Vector3>();
float step = 0.3f;
DoMovement(list, player.eyes.position + (player.eyes.BodyForward() * ammoType.speed) * velocityScale * step, (player.eyes.BodyForward() * ammoType.speed) * velocityScale, step, 30, ammoType.gravityModifier);
for (int i = 0; i < list.Count - 1; i++)
{
DrawArrow(player, UpdateRate, Color.green, list[i], list[i + 1]);
}
Pool.FreeList(ref list);
}
void OnExplosiveThrown(BasePlayer player, BaseEntity entity)
{
if (entity.ShortPrefabName == "grenade.f1.deployed" || entity.ShortPrefabName == "explosive.timed.deployed")
{
entity.SetVelocity(entity.GetComponent<Rigidbody>().velocity * Settings.GrenadeVelocityScale);
}
//if(entity.ShortPrefabName == "explosive.timed.deployed")
//{
// entity.SetVelocity(entity.GetComponent<Rigidbody>().velocity * Settings.GrenadeVelocityScale);
//}
}
void OnRocketLaunched(BasePlayer player, BaseEntity entity)
{
var rocket = entity as TimedExplosive;
if (rocket == null)
{
return;
}
var projectile = rocket.GetComponent<ServerProjectile>();
float velocityScale = Settings.RocketVelocityScale;
if (entity.ShortPrefabName == "rocket_hv")
{
velocityScale = Settings.HVRocketVelocityScale;
}
else if (entity.ShortPrefabName == "rocket_fire")
{
velocityScale = Settings.FireRocketVelocityScale;
}
projectile.CurrentVelocity *= velocityScale;
Puts(entity.ShortPrefabName);
//rocket.explosionEffect.//assets/prefabs/npc/patrol helicopter/effects/rocket_explosion.prefab
}
private void DoMovement(List<Vector3> output, Vector3 currentPos, Vector3 currentVelocity, float step = 0.1f, int maxSteps = 20, float gravityModifier = 1f)
{
for(int i = 0; i < maxSteps; i++)
{
output.Add(currentPos);
//DoMovement
currentVelocity += Physics.gravity * gravityModifier * step;
currentPos = currentPos + currentVelocity * step;
//Update velocity
//currentVelocity -= currentVelocity.normalized * (currentVelocity.magnitude * this.drag * step);
}
output.Add(currentPos);
}
private class VelocityUpdate
{
public Vector3 Position;
public Vector3 Velocity;
}
void OnFrame()
{
SendDDrawCommands();
}
#region DDraw
private static Dictionary<BasePlayer, List<string>> DDrawCommandQueue = new Dictionary<BasePlayer, List<string>>();
private static void QueueDDrawCommand(BasePlayer player, string command, params object[] args)
{
List<string> list;
if (!DDrawCommandQueue.TryGetValue(player, out list))
{
list = new List<string>();
DDrawCommandQueue.Add(player, list);
}
list.Add(ConsoleSystem.BuildCommand(command, args));
}
public static void DrawCube(BasePlayer player, float duration, UnityEngine.Color color, Vector3 position, float size = 1)
{
QueueDDrawCommand(player, "ddraw.box", duration, color, position, size);
}
public static void DrawBox(BasePlayer player, float duration, UnityEngine.Color color, Vector3 min, Vector3 max)
{
QueueDDrawCommand(player, "ddraw.line", duration, color, new Vector3(min.x, min.y, min.z), new Vector3(min.x, min.y, max.z));
QueueDDrawCommand(player, "ddraw.line", duration, color, new Vector3(min.x, min.y, min.z), new Vector3(min.x, max.y, min.z));
QueueDDrawCommand(player, "ddraw.line", duration, color, new Vector3(min.x, min.y, min.z), new Vector3(max.x, min.y, min.z));
QueueDDrawCommand(player, "ddraw.line", duration, color, new Vector3(max.x, max.y, max.z), new Vector3(max.x, max.y, min.z));
QueueDDrawCommand(player, "ddraw.line", duration, color, new Vector3(max.x, max.y, max.z), new Vector3(max.x, min.y, max.z));
QueueDDrawCommand(player, "ddraw.line", duration, color, new Vector3(max.x, max.y, max.z), new Vector3(min.x, max.y, max.z));
QueueDDrawCommand(player, "ddraw.line", duration, color, new Vector3(min.x, max.y, min.z), new Vector3(min.x, max.y, max.z));
QueueDDrawCommand(player, "ddraw.line", duration, color, new Vector3(min.x, max.y, min.z), new Vector3(max.x, max.y, min.z));
QueueDDrawCommand(player, "ddraw.line", duration, color, new Vector3(max.x, min.y, min.z), new Vector3(max.x, max.y, min.z));
QueueDDrawCommand(player, "ddraw.line", duration, color, new Vector3(max.x, min.y, min.z), new Vector3(max.x, min.y, max.z));
QueueDDrawCommand(player, "ddraw.line", duration, color, new Vector3(min.x, min.y, max.z), new Vector3(max.x, min.y, max.z));
QueueDDrawCommand(player, "ddraw.line", duration, color, new Vector3(min.x, min.y, max.z), new Vector3(min.x, max.y, max.z));
}
public static void DrawText(BasePlayer player, string text, float duration, UnityEngine.Color color, Vector3 position, int size = 12)
{
QueueDDrawCommand(player, "ddraw.text", duration, color, position, size == 12 ? text : $"<size={size}>{text.Replace("\n", "\\n")}</size>");
}
public static void DrawSphere(BasePlayer player, float duration, UnityEngine.Color color, Vector3 position, float size)
{
QueueDDrawCommand(player, "ddraw.sphere", duration, color, position, size);
}
public static void DrawArrow(BasePlayer player, float duration, Color color, Vector3 start, Vector3 end)
{
QueueDDrawCommand(player, "ddraw.arrow", duration, color, start, end, 0.1);
}
public void SendDDrawCommands()
{
if (DDrawCommandQueue.Count == 0)
{
return;
}
foreach (var request in DDrawCommandQueue)
{
if (request.Key == null)
{
continue;
}
bool fakeAdmin = request.Key.IsAdmin == false;
if (fakeAdmin)
{
request.Key.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, true);
request.Key.SendNetworkUpdateImmediate();
}
foreach (var cmd in request.Value)
{
request.Key.SendConsoleCommand(cmd);
}
if (fakeAdmin)
{
request.Key.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, false);
request.Key.SendNetworkUpdateImmediate();
}
}
DDrawCommandQueue.Clear();
}
#endregion
#region Lang API
public Dictionary<string, string> lang_en = new Dictionary<string, string>()
{
};
public static string GetLangMessage(string key, BasePlayer player)
{
return _plugin.lang.GetMessage(key, _plugin, player.UserIDString);
}
public static string GetLangMessage(string key, ulong player)
{
return _plugin.lang.GetMessage(key, _plugin, player.ToString());
}
public static string GetLangMessage(string key, string player)
{
return _plugin.lang.GetMessage(key, _plugin, player);
}
#endregion
#region PlayerData
public class BasePlayerData
{
[JsonIgnore]
public BasePlayer Player { get; set; }
public string userID { get; set; } = "";
public BasePlayerData()
{
}
public BasePlayerData(BasePlayer player) : base()
{
userID = player.UserIDString;
Player = player;
}
}
public class PlayerDataController<T> where T : BasePlayerData
{
[JsonPropertyAttribute(Required = Required.Always)]
private Dictionary<string, T> playerData { get; set; } = new Dictionary<string, T>();
private JSONFile<Dictionary<string, T>> _file;
private Timer _timer;
public IEnumerable<T> All { get { return playerData.Values; } }
public PlayerDataController()
{
}
public PlayerDataController(string filename = null)
{
if (filename == null)
{
return;
}
_file = new JSONFile<Dictionary<string, T>>(filename);
_timer = _plugin.timer.Every(120f, () =>
{
_file.Save();
});
}
public void Unload()
{
if (_file == null)
{
return;
}
_file.Save();
}
public T Get(string identifer)
{
T data;
if (!playerData.TryGetValue(identifer, out data))
{
data = Activator.CreateInstance<T>();
playerData[identifer] = data;
}
return data;
}
public T Get(ulong userID)
{
return Get(userID.ToString());
}
public T Get(BasePlayer player)
{
var data = Get(player.UserIDString);
data.Player = player;
return data;
}
public bool Has(ulong userID)
{
return playerData.ContainsKey(userID.ToString());
}
public void Set(string userID, T data)
{
playerData[userID] = data;
}
public bool Remove(string userID)
{
return playerData.Remove(userID);
}
public void Update(T data)
{
playerData[data.userID] = data;
}
}
#endregion
#region Configuration Files
public enum ConfigLocation
{
Data = 0,
Config = 1,
Logs = 2,
Plugins = 3,
Lang = 4,
Custom = 5,
}
public class JSONFile<Type> where Type : class
{
private DynamicConfigFile _file;
public string _name { get; set; }
public Type Instance { get; set; }
private ConfigLocation _location { get; set; }
private string _path { get; set; }
public JSONFile(string name, ConfigLocation location = ConfigLocation.Data, string path = null, string extension = ".json")
{
_name = name.Replace(".json", "");
_location = location;
switch (location)
{
case ConfigLocation.Data:
{
_path = $"{Oxide.Core.Interface.Oxide.DataDirectory}/{name}{extension}";
break;
}
case ConfigLocation.Config:
{
_path = $"{Oxide.Core.Interface.Oxide.ConfigDirectory}/{name}{extension}";
break;
}
case ConfigLocation.Logs:
{
_path = $"{Oxide.Core.Interface.Oxide.LogDirectory}/{name}{extension}";
break;
}
case ConfigLocation.Lang:
{
_path = $"{Oxide.Core.Interface.Oxide.LangDirectory}/{name}{extension}";
break;
}
case ConfigLocation.Custom:
{
_path = $"{path}/{name}{extension}";
break;
}
}
_file = new DynamicConfigFile(_path);
_file.Settings = new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore };
Init();
}
public virtual void Init()
{
Load();
Save();
Load();
}
public virtual void Load()
{
if (!_file.Exists())
{
Save();
}
Instance = _file.ReadObject<Type>();
if (Instance == null)
{
Instance = Activator.CreateInstance<Type>();
Save();
}
return;
}
public virtual void Save()
{
_file.WriteObject(Instance);
return;
}
public virtual void Reload()
{
Load();
}
private void Unload(Plugin sender, PluginManager manager)
{
}
}
#endregion
}
}