PersistantCorpses/PersistantCorpses.cs

380 lines
14 KiB
C#

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Persistant Corpses", "bmgjet", "1.0.2")]
[Description("Player Corpses don't despawn unless there health is 0.")]
public class PersistantCorpses : RustPlugin
{
#region Vars
//User Editable
private float RefreshTimer = 6f;
private bool NPCSupport = false;
private int textsize = 22;
private Color textcolor = Color.red;
private bool stripitems = false;
private int scorelimit = 10;
//Dont change below
private const string permClean = "PersistantCorpses.clean";
private const string permCount = "PersistantCorpses.count";
private const string permScore = "PersistantCorpses.score";
private const string permView = "PersistantCorpses.view";
private Dictionary<BasePlayer, Dictionary<bool, string>> Viewers = new Dictionary<BasePlayer, Dictionary<bool, string>>();
private Coroutine _routine;
private Dictionary<string, int> Score = new Dictionary<string, int> { };
private Dictionary<BaseNetworkable, Vector3> Corpses = new Dictionary<BaseNetworkable, Vector3> { };
#endregion
#region Language
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
{"Info", "There are {0} corpses on map!"},
{"Score", "Players Deaths {0}"},
{"Clean", "{0} corpses have been removed from the map!"},
{"View", "{0} Corpse view!"},
{"Permission", "You need permission to do that!"}
}, this);
}
private void message(BasePlayer chatplayer, string key, params object[] args)
{
if (chatplayer == null) { return; }
var message = string.Format(lang.GetMessage(key, this, chatplayer.UserIDString), args);
chatplayer.ChatMessage(message);
}
#endregion
#region Oxide Hooks
private void Init()
{
permission.RegisterPermission(permClean, this);
permission.RegisterPermission(permCount, this);
permission.RegisterPermission(permView, this);
permission.RegisterPermission(permScore, this);
}
private void Unload()
{
if (_routine != null)
{
try
{
ServerMgr.Instance.StopCoroutine(_routine);
}
catch { }
_routine = null;
}
}
private void OnEntitySpawned(BaseNetworkable entity)
{
if (entity != null && (entity.name.Contains("player_corpse") || entity.name.Contains("scientist_corpse")))
{
PlayerCorpse corpse = entity as PlayerCorpse;
if (corpse != null)
{
BasePlayer moddedpayer = BasePlayer.Find(corpse.playerSteamID.ToString());
if (moddedpayer != null)
{
corpse._playerName = "[" + moddedpayer.lastDamage.ToString() + "]" + corpse._playerName.ToString();
if (stripitems)
{
corpse.DropItems();
}
}
else
{
//bot
if (stripitems && NPCSupport)
{
corpse.DropItems();
}
}
}
}
}
private object OnEntityKill(BaseNetworkable entity)
{
if (entity != null && (entity.name.Contains("player_corpse") || entity.name.Contains("scientist_corpse")))
{
if (entity.name.Contains("scientist_corpse") && !NPCSupport) { return null; }
PlayerCorpse corpse = entity as PlayerCorpse;
if (corpse.health == 0) { return null; }
return false;
}
return null;
}
#endregion
#region Core
private void CheckIfViewed()
{
if (Viewers.Count == 0) //If no viewers left remove routine
{
ServerMgr.Instance.StopCoroutine(_routine);
_routine = null;
Puts("Corpse View Thread Stopped!");
}
}
private void CleanOut(Dictionary<BaseNetworkable, Vector3> co)
{
foreach (KeyValuePair<BaseNetworkable, Vector3> ent in co.ToList())
{
PlayerCorpse OldCorpse = ent.Key as PlayerCorpse;
if (OldCorpse != null)
{
OldCorpse.health = 0f;
OldCorpse.Kill();
}
}
}
private void BuildCorpseDict()
{
Corpses.Clear();
foreach (var entity in BaseNetworkable.serverEntities.OfType<BaseNetworkable>())
{
if (!Corpses.ContainsKey(entity))
{
PlayerCorpse x = entity as PlayerCorpse;
if (x != null)
{
Corpses.Add(entity, x.transform.position);
}
}
}
}
private void ShowCorpses(BasePlayer viewplayer, string filter)
{
foreach (KeyValuePair<BaseNetworkable, Vector3> ent in Corpses)
{
try
{
PlayerCorpse corpse = ent.Key as PlayerCorpse;
if (corpse == null || corpse.transform == null) { continue; }
if (corpse.playerName.ToLower().Contains(filter.ToLower()) || filter == "")
{
viewplayer.SendConsoleCommand("ddraw.text", RefreshTimer, textcolor, corpse.transform.position, "<size=" + textsize + ">" + corpse.playerName + "</size>");
}
}
catch { }
}
}
IEnumerator CorpseScanRoutine()
{
do //start loop
{
foreach (KeyValuePair<BasePlayer, Dictionary<bool, string>> viewer in Viewers.ToList())
{
foreach (KeyValuePair<bool, string> viewerinfo in viewer.Value.ToList())
{
//toggle admin flag so you can show a normal user with out it auto banning them for cheating
if (!viewerinfo.Key)
{
viewer.Key.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, true);
viewer.Key.SendNetworkUpdateImmediate();
}
ShowCorpses(viewer.Key, viewerinfo.Value);
if (!viewerinfo.Key && viewer.Key.HasPlayerFlag(BasePlayer.PlayerFlags.IsAdmin))
{
viewer.Key.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, false);
viewer.Key.SendNetworkUpdateImmediate();
}
}
if (!viewer.Key.IsConnected || viewer.Key.IsSleeping())
{
//Remove from viewers list
Viewers.Remove(viewer.Key);
message(viewer.Key, "View", "Stopped");
}
}
yield return CoroutineEx.waitForSeconds(RefreshTimer);
} while (Viewers.Count != 0);
_routine = null;
Puts("Corpse View Thread Stopped!");
}
[ChatCommand("corpse.clean")]
private void CmdCorpseClean(BasePlayer player, string command, string[] args)
{
if (!player.IPlayer.HasPermission(permCount))
{
message(player, "Permission", "count");
return;
}
BuildCorpseDict();
if (args.Length == 0)
{
CleanOut(Corpses);
message(player, "Clean", Corpses.Count.ToString());
return;
}
Dictionary<BaseNetworkable, Vector3> CleanOutList = new Dictionary<BaseNetworkable, Vector3>();
foreach (KeyValuePair<BaseNetworkable, Vector3> ent in Corpses)
{
try
{
PlayerCorpse OldCorpse = ent.Key as PlayerCorpse;
if (OldCorpse != null)
{
if (OldCorpse.playerName.ToLower().Contains(args[0].ToLower()))
{
CleanOutList.Add(ent.Key, ent.Value);
}
}
}
catch { }
}
CleanOut(CleanOutList);
message(player, "Clean", CleanOutList.Count.ToString());
}
[ChatCommand("corpse.view")]
private void CmdCorpseView(BasePlayer player, string command, string[] args)
{
if (!player.IPlayer.HasPermission(permView))
{
message(player, "Permission", "view");
return;
}
if (_routine != null) //Check if already running
{
if (args.Length == 0) //No Args passed
{
if (Viewers.ContainsKey(player))
{
Viewers.Remove(player); //Remove player from list
message(player, "View", "Stopped");
CheckIfViewed();
return;
}
}
CheckIfViewed();
}
if (args.Length > 0) //args passed
{
if (Viewers.ContainsKey(player)) //Updates filter on player
{
Viewers[player] = new Dictionary<bool, string> { { player.IsAdmin, args[0] } };
}
else
{
Viewers.Add(player, new Dictionary<bool, string> { { player.IsAdmin, args[0] } }); //Filter "" = all players
}
message(player, "View", "Started filtered");
}
else
{
Viewers.Add(player, new Dictionary<bool, string> { { player.IsAdmin, "" } }); //Filter "" = all players
message(player, "View", "Started");
}
BuildCorpseDict();
if (_routine == null) //Start routine
{
Puts("Corpse View Thread Started");
_routine = ServerMgr.Instance.StartCoroutine(CorpseScanRoutine());
}
}
[ChatCommand("corpse.count")]
private void CmdCorpseCount(BasePlayer player, string command, string[] args)
{
if (!player.IPlayer.HasPermission(permCount))
{
message(player, "Permission", "count");
return;
}
BuildCorpseDict();
if (args.Length == 0)
{
message(player, "Info", Corpses.Count.ToString());
return;
}
int i = 0;
foreach (KeyValuePair<BaseNetworkable, Vector3> ent in Corpses)
{
try
{
PlayerCorpse OldCorpse = ent.Key as PlayerCorpse;
if (OldCorpse != null)
{
if (OldCorpse.playerName.ToLower().Contains(args[0].ToLower()))
{
i++;
}
}
}
catch { }
}
message(player, "Info", i.ToString());
}
[ChatCommand("corpse.score")]
private void CmdCorpseScore(BasePlayer player, string command, string[] args)
{
if (!player.IPlayer.HasPermission(permScore))
{
message(player, "Permission", "score");
return;
}
BuildCorpseDict();
Score.Clear();
foreach (KeyValuePair<BaseNetworkable, Vector3> ent in Corpses)
{
PlayerCorpse OldCorpse = ent.Key as PlayerCorpse;
if (OldCorpse != null)
{
try
{
if (!Score.ContainsKey(OldCorpse.playerSteamID.ToString()))
{
if (OldCorpse.playerSteamID != 0)
Score.Add(OldCorpse.playerSteamID.ToString(), 1);
continue;
}
Score[OldCorpse.playerSteamID.ToString()]++;
continue;
}
catch { }
}
}
string output = "\n";
var orderByDescendingResult = from s in Score
orderby s.Value descending
select s;
int sl = 0;
foreach (KeyValuePair<string, int> o in orderByDescendingResult)
{
if (sl > scorelimit)
{
break;
}
BasePlayer dead = BasePlayer.FindAwakeOrSleeping(o.Key.ToString());
if (dead != null)
{
output += dead.displayName + " Died " + o.Value.ToString() + " Times\n";
sl++;
}
}
message(player, "Score", output);
}
#endregion
}
}