Hi,
Below you will see the code to replace your current Friendly Fire plugin with.
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
namespace Oxide.Plugins
{
[Info("Friendly Fire", "collect_vood", "1.1.4")]
[Description("Gives you the ability to enable or disable friendly fire player based")]
class FriendlyFire : CovalencePlugin
{
[PluginReference]
private Plugin Friends, Clans;
#region Localization
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>()
{
{ "NoFriendlyFire", "You cannot damage your friends! (<color=#7FFF00>/ff on</color>)" },
{ "OtherNoFriendlyFire", "{0} has friendly fire disabled!" },
{ "FriendAttack", "Your friend {0} tried to attack you!" },
{ "FFOn", "Friendly Fire turned <color=#7FFF00>on</color>!" },
{ "FFOff", "Friendly Fire turned <color=#FF0000>off</color>!" },
{ "AlreadyStateOn", "Friendly Fire is already turned <color=#7FFF00>on</color>!" },
{ "AlreadyStateOff", "Friendly Fire is already turned <color=#FF0000>off</color>!" },
{ "FFHelp", "Friendly Fire:\n/ff on - to turn on friendly fire\n/ff off - to turn off friendly fire" },
{ "CommandArguments", "You have to use <color=#7FFF00>on</color> or <color=#FF0000>off</color> as arguments!" },
{ "NoPermission", "You don't have access to use this command" }
}, this);
}
#endregion
#region Config
private Configuration config;
private class Configuration
{
[JsonProperty(PropertyName = "Command")]
public string Command = "ff";
[JsonProperty(PropertyName = "Player Default Settings", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, bool> PlayerDefaultSettings = new Dictionary<string, bool>
{
{ "Friendly Fire", false }
};
[JsonProperty(PropertyName = "Change friendly fire state permission")]
public string ChangeStatePermission = "friendlyfire.changestate";
[JsonProperty(PropertyName = "Send friendly fire messages")]
public bool SendMessages = true;
[JsonProperty(PropertyName = "Message Cooldown Seconds")]
public float MessageCooldownSeconds = 2f;
[JsonProperty(PropertyName = "Include check if friend")]
public bool isFriendCheck = true;
[JsonProperty(PropertyName = "Include check if team member")]
public bool isTeamMemberCheck = true;
[JsonProperty(PropertyName = "Include check if clan member")]
public bool isClanMemberCheck = true;
}
protected override void LoadDefaultConfig()
{
PrintWarning("Creating a new configuration file");
config = new Configuration();
}
protected override void LoadConfig()
{
base.LoadConfig();
config = Config.ReadObject<Configuration>();
SaveConfig();
}
protected override void SaveConfig() => Config.WriteObject(config);
#endregion
#region Data
private StoredData storedData;
private Dictionary<string, PlayerSettings> allPlayerSettings => storedData.AllPlayerSettings;
private class PlayerSettings
{
public bool ff;
}
private class StoredData
{
public Dictionary<string, PlayerSettings> AllPlayerSettings { get; private set; } = new Dictionary<string, PlayerSettings>();
}
private readonly Dictionary<string, DateTime> messageCooldowns = new Dictionary<string, DateTime>();
private void SaveData() => Interface.Oxide.DataFileSystem.WriteObject(Name, storedData);
private void OnServerSave()
{
SaveData();
CleanupCooldowns();
}
private void Unload()
{
SaveData();
messageCooldowns.Clear();
}
private void CreatePlayerSettings(IPlayer player)
{
if (!allPlayerSettings.ContainsKey(player.Id))
{
allPlayerSettings[player.Id] = new PlayerSettings
{
ff = config.PlayerDefaultSettings["Friendly Fire"]
};
}
}
#endregion
#region Hooks
private void Init()
{
permission.RegisterPermission(config.ChangeStatePermission, this);
storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>(Name);
AddCovalenceCommand(config.Command, nameof(CommandFriendlyFire));
}
private void OnServerInitialized()
{
foreach (var player in BasePlayer.activePlayerList)
CreatePlayerSettings(player.IPlayer);
SaveData();
}
private object OnEntityTakeDamage(BasePlayer victimBP, HitInfo info)
{
if (victimBP == null || info == null)
return null;
BasePlayer attackerBP = GetAttackerPlayer(info);
if (attackerBP == null || attackerBP == victimBP)
return null;
return HandleFriendlyFire(attackerBP, victimBP, info);
}
private void OnUserConnected(IPlayer player) => CreatePlayerSettings(player);
#endregion
#region Command
private void CommandFriendlyFire(IPlayer player, string command, string[] args)
{
if (!HasPermission(player))
{
player.Reply(GetMessage("NoPermission", player));
return;
}
CreatePlayerSettings(player);
if (args.Length <= 0)
{
allPlayerSettings[player.Id].ff = !allPlayerSettings[player.Id].ff;
player.Reply(GetMessage(allPlayerSettings[player.Id].ff ? "FFOn" : "FFOff", player));
return;
}
switch (args[0].ToLower())
{
case "on":
if (allPlayerSettings[player.Id].ff)
{
player.Reply(GetMessage("AlreadyStateOn", player));
break;
}
allPlayerSettings[player.Id].ff = true;
player.Reply(GetMessage("FFOn", player));
break;
case "off":
if (!allPlayerSettings[player.Id].ff)
{
player.Reply(GetMessage("AlreadyStateOff", player));
break;
}
allPlayerSettings[player.Id].ff = false;
player.Reply(GetMessage("FFOff", player));
break;
case "help":
player.Reply(GetMessage("FFHelp", player));
break;
default:
player.Reply(GetMessage("CommandArguments", player));
break;
}
}
#endregion
#region Helpers
private object HandleFriendlyFire(BasePlayer attackerBP, BasePlayer victimBP, HitInfo info)
{
IPlayer attacker = attackerBP.IPlayer;
IPlayer victim = victimBP.IPlayer;
if (attacker == null || victim == null || attacker.Id == victim.Id)
return null;
CreatePlayerSettings(attacker);
CreatePlayerSettings(victim);
if (allPlayerSettings[attacker.Id].ff && allPlayerSettings[victim.Id].ff)
return null;
bool related =
(config.isTeamMemberCheck && IsTeamMember(attackerBP, victimBP)) ||
(config.isFriendCheck && (Friends?.Call<bool>("AreFriends", attacker.Id, victim.Id) ?? false)) ||
(config.isClanMemberCheck && IsClanMember(attackerBP, victimBP));
if (!related)
return null;
if (ShouldSendMessage(attacker.Id, victim.Id))
{
if (!allPlayerSettings[attacker.Id].ff)
attacker.Reply(GetMessage("NoFriendlyFire", attacker));
else
attacker.Reply(GetMessage("OtherNoFriendlyFire", attacker, victim.Name));
victim.Reply(GetMessage("FriendAttack", victim, attacker.Name));
}
Interface.Oxide.CallHook("OnFriendAttacked", attacker, victim, info);
return true;
}
private BasePlayer GetAttackerPlayer(HitInfo info)
{
if (info.InitiatorPlayer != null)
return info.InitiatorPlayer;
var initiatorEntity = info.Initiator as BaseEntity;
if (initiatorEntity == null || initiatorEntity.OwnerID == 0)
return null;
return BasePlayer.FindByID(initiatorEntity.OwnerID) ?? BasePlayer.FindSleeping(initiatorEntity.OwnerID);
}
private bool ShouldSendMessage(string attackerId, string victimId)
{
if (!config.SendMessages)
return false;
if (config.MessageCooldownSeconds <= 0f)
return true;
string key = attackerId + ":" + victimId;
DateTime now = DateTime.UtcNow;
DateTime nextAllowedAt;
if (messageCooldowns.TryGetValue(key, out nextAllowedAt) && now < nextAllowedAt)
return false;
messageCooldowns[key] = now.AddSeconds(config.MessageCooldownSeconds);
return true;
}
private void CleanupCooldowns()
{
if (messageCooldowns.Count == 0)
return;
DateTime now = DateTime.UtcNow;
var remove = new List<string>();
foreach (var kvp in messageCooldowns)
{
if (kvp.Value <= now)
remove.Add(kvp.Key);
}
for (int i = 0; i < remove.Count; i++)
messageCooldowns.Remove(remove[i]);
}
private string GetMessage(string key, IPlayer player, params string[] args) =>
string.Format(lang.GetMessage(key, this, player.Id), args);
private bool HasPermission(IPlayer player) =>
permission.UserHasPermission(player.Id, config.ChangeStatePermission);
private bool IsTeamMember(BasePlayer player, BasePlayer possibleMember)
{
if (player.currentTeam == 0 || possibleMember.currentTeam == 0)
return false;
return player.currentTeam == possibleMember.currentTeam;
}
private bool IsClanMember(BasePlayer player, BasePlayer possibleMember)
{
if (Clans == null || !Clans.IsLoaded)
return false;
var playerClan = Clans.Call<string>("GetClanOf", player);
var otherPlayerClan = Clans.Call<string>("GetClanOf", possibleMember);
if (string.IsNullOrEmpty(otherPlayerClan) || string.IsNullOrEmpty(playerClan))
return false;
return playerClan == otherPlayerClan;
}
#endregion
}
}