C#:
using System;
using System.Linq;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;
using Oxide.Core;
namespace Oxide.Plugins {
[Info("CMe", "TF Crazy", "1.0.4")]
[Description("The /me command allows you to display a specific action above the head of a player. It’s particularly used for actions that couldn’t have been done in game in a roleplay context.")]
public class CMe : RustPlugin {
#region Fields
private static string permUse = "cme.use";
private static string permView = "cme.view";
private static List<ulong> adminList = new List<ulong>();
#endregion
#region Server
/// <summary>Iniialize</summary>
private void OnServerInitialized() {
permission.RegisterPermission(permUse, this);
permission.RegisterPermission(permView, this);
cmd.AddChatCommand(cfg.chat.command, this, nameof(cmdCMeCommand));
}
/// <summary>Destroy object if plugin unload</summary>
private void Unload() {
Me message;
foreach(BasePlayer player in BasePlayer.activePlayerList) {
message = player.GetComponent<Me>();
if (message != null) UnityEngine.Object.Destroy(message);
}
}
#endregion
#region Component
/// <summary>Create me objet</summary>
public class Me : MonoBehaviour {
private BasePlayer player;
private TimeSpan start;
private string message;
public void Awake() => player = GetComponent<BasePlayer>();
/// <summary>Called for display player message</summary>
/// <param name="message">String: Contains messsage sended by player</param>
public void DisplayMessage(string text) {
this.start = DateTime.Now.TimeOfDay;
if(cfg.setting.capitalize) this.message = text.ToUpper();
this.message = cfg.setting.pattern.Replace("{message}", this.message);
InvokeRepeating("Instance", 0f, 0.075f);
}
/// <summary>Display message for all players in radius</summary>
public void Instance() {
if(start.Add(TimeSpan.FromSeconds(cfg.setting.duration)) < DateTime.Now.TimeOfDay) Destroy(this);
foreach (BasePlayer target in BasePlayer.activePlayerList) {
if(target == null) continue;
if(!player.IPlayer.HasPermission(permView)) continue;
if(!IsReady(player)) continue;
if(!CheckDistance(player.transform.position, target.transform.position, cfg.setting.range)) continue;
FakeAdminEnable(target);
DrawText(target, new Vector3(player.transform.position.x, player.transform.position.y + 2f, player.transform.position.z), message, cfg.setting.color, cfg.setting.size, 0.1f);
FakeAdminDisable(target);
}
}
}
#endregion
#region Chat Command
/// <summary>Chat command for create me</summary>
/// <param name="player">BasePlayer: contain informations about the player</param>
/// <param name="command">String: chat command</param>
/// <param name="args">String[]: message sended in array</param>
private void cmdCMeCommand(BasePlayer player, string command, string[] args) {
if(player == null) return;
if(!player.IPlayer.HasPermission(permUse)) {
SendReply(player, GetLang("Msg_NotAllowed", true, player.IPlayer.Id, cfg.chat.command));
return;
}
if(args == null || args.Count() == 0) {
SendReply(player, GetLang("Msg_Command", true, player.IPlayer.Id, cfg.chat.command));
return;
}
Me message;
message = player.GetComponent<Me>();
if (message != null) UnityEngine.Object.Destroy(message);
message = player.gameObject.AddComponent<Me>();
message.DisplayMessage(string.Join(" ", args));
}
#endregion
#region Function
/// <summary>Check if player is ready for receive action</summary>
/// <param name="player">BasePlayer: contain informations about the player</param>
/// <return>True if player can receive</return>
private static bool IsReady(BasePlayer player) {
if(player.IsDead()) return false;
if(player.IsSleeping()) return false;
if(player.IsReceivingSnapshot) return false;
return true;
}
/// <summary>Check if two players are less than or equal to the specified distance</summary>
/// <param name="p">Vector3: location of player</param>
/// <param name="t">Vector3: location of target</param>
/// <param name="radius">Float: location of target</param>
/// <return>Bool: true if less or equal</return>
private static bool CheckDistance(Vector3 p, Vector3 t, float radius) {
var distance = Math.Floor(Vector3.Distance(p, t));
if (distance >= radius) return false;
return true;
}
/// <summary>Draw text</summary>
/// <param name="player">BasePlayer: contain informations about the player</param>
/// <param name="pos">Vector3: location for display</param>
/// <param name="text">String: message</param>
/// <param name="color">String: color to hex</param>
/// <param name="size">Int: size</param>
/// <param name="duration">Float: display duration</param>
private static void DrawText(BasePlayer player, Vector3 pos, string text, string color, int size, float duration) => player.SendConsoleCommand("ddraw.text", duration, Color.white, pos, $"<color={color}><size={size}>{text}</size></color>");
/// <summary>Get language dictionary message</summary>
/// <param name="langKey">String: Dictionary key</param>
/// <param name="prefix">Bool: Default false. If true add chat prefix after message</param>
/// <param name="playerId">String: Default null. Player Id (IPlayer)</param>
/// <param name="args">Params Object: Arguments array</param>
/// <returns>String: formated or empty</returns>
private string GetLang(string langKey, bool prefix = false, string playerId = null, params object[] args) {
string str = string.Empty;
if(prefix) str = $"<size={cfg.chat.title_size}><color={cfg.chat.title_color}>{cfg.chat.title_msg}</color></size><br><br>";
return str + string.Format(lang.GetMessage(langKey, this, playerId), args);
}
/// <summary>Set admin to fake admin (for send protected command)</summary>
/// <param name="player">BasePlayer: contain informations about the player</param>
private static void FakeAdminEnable(BasePlayer player) {
if(player.IsAdmin) {
if(!adminList.Contains(player.userID)) adminList.Add(player.userID);
return;
}
player.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, true);
player.SendNetworkUpdateImmediate();
}
/// <summary>Unset admin to fake admin (for send protected command)</summary>
/// <param name="player">BasePlayer: contain informations about the player</param>
private static void FakeAdminDisable(BasePlayer player) {
if(adminList.Contains(player.userID)) return;
player.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, false);
player.SendNetworkUpdateImmediate();
}
#endregion
#region Config
private static ConfigData cfg;
private class ConfigData {
[JsonProperty(PropertyName = "CONFIG")]
public Setting setting {
get;
set;
}
[JsonProperty(PropertyName = "CHAT")]
public Chat chat {
get;
set;
}
[JsonProperty(PropertyName = "VERSION")]
public VersionNumber version {
get;
set;
}
}
private class Setting {
[JsonProperty(PropertyName = "» Message duration (seconds)")]
public int duration {
get;
set;
}
[JsonProperty(PropertyName = "» Message size")]
public int size {
get;
set;
}
[JsonProperty(PropertyName = "» Message color")]
public string color {
get;
set;
}
[JsonProperty(PropertyName = "» Message pattern")]
public string pattern {
get;
set;
}
[JsonProperty(PropertyName = "» Message in capital letters ?")]
public bool capitalize {
get;
set;
}
[JsonProperty(PropertyName = "» Display range")]
public float range {
get;
set;
}
}
private class Chat {
[JsonProperty(PropertyName = "» Chat Command")]
public string command {
get;
set;
}
[JsonProperty(PropertyName = "» Chat Prefix message")]
public string title_msg {
get;
set;
}
[JsonProperty(PropertyName = "» Chat prefix size")]
public int title_size {
get;
set;
}
[JsonProperty(PropertyName = "» Chat prefix color")]
public string title_color {
get;
set;
}
}
private ConfigData GetBaseConfig() {
return new ConfigData {
setting = new Setting {
duration = 10, size = 20, color = "#ce422b", pattern = "* {message} *", capitalize = true, range = 15f
}
, chat = new Chat {
command = "me", title_msg = "Roleplay Message", title_size = 18, title_color = "#ce422b",
}
, version = Version
}
;
}
protected override void LoadConfig() {
base.LoadConfig();
cfg = Config.ReadObject<ConfigData>();
if (cfg.version < Version) UpdateConfigValues();
Config.WriteObject(cfg, true);
}
protected override void LoadDefaultConfig() => cfg = GetBaseConfig();
protected override void SaveConfig() => Config.WriteObject(cfg, true);
private void UpdateConfigValues() {
PrintWarning("Config update detected! Updating config values...");
ConfigData baseConfig = GetBaseConfig();
cfg.version = Version;
PrintWarning("Config update completed!");
}
#endregion
#region Localization
/// <summary>
/// Language text /lang
/// </summary>
protected override void LoadDefaultMessages() {
/// <summary>
/// English
/// </summary>
lang.RegisterMessages(new Dictionary<string, string> {
["Msg_Command"]
= "Syntax: <color=#939393>/{0} your message</color>.", ["Msg_NotAllowed"] = "You are not allowed to use the <color=#939393>/{0}</color> command."
}
, this);
/// <summary>
/// French
/// </summary>
lang.RegisterMessages(new Dictionary<string, string> {
["Msg_Command"]
= "Syntaxe : <color=#939393>/{0} votre message</color>.", ["Msg_NotAllowed"] = "Vous n'êtes pas autorisé à utiliser la commande <color=#939393>/{0}</color>."
}
, this, "fr");
}
#endregion
}
}