C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Game.Rust.Cui;
using Oxide.Core.Plugins;
using UnityEngine;
using System.Linq;
using Newtonsoft.Json;
using Rust;
using Network;
namespace Oxide.Plugins {
[Info("Arena", "k1lly0u", "0.1.133")]
[Description("A multi arena plugin capable of running many instances of various events at one time")]
class Arena : RustPlugin {
#region Fields
[PluginReference]
Plugin Spawns, ZoneManager, Kits, ImageLibrary, LustyMap, RotatingPickups, Economics, ServerRewards, NoEscape;
public static ArenaUI UI;
public static ArenaStatistics Statistics;
public static ArenaEvents Events;
public static ArenaLootSpawns Loot;
private ArenaData arenaData;
private RestoreData restoreData;
private DynamicConfigFile eventData, restorationData;
private static Arena ins;
private Dictionary<ulong, Timer> killTimers;
public Dictionary<ulong, Timer> respawnTimers;
public Dictionary<string, EventManager> events;
public Dictionary<string, List<AdditionalParamData>> additionalParameters;
private Hash<ulong, Action> pendingTP = new Hash<ulong, Action>();
private Hash<ulong, double> cooldownTP = new Hash<ulong, double>();
public List<string> eventTypes;
public bool isInitialized;
public static bool isUnloading;
#endregion
#region Oxide Hooks
private void Loaded() {
eventData = Interface.Oxide.DataFileSystem.GetFile("Arena/event_data");
restorationData = Interface.Oxide.DataFileSystem.GetFile("Arena/restoration_data");
killTimers = new Dictionary<ulong, Timer>();
respawnTimers = new Dictionary<ulong, Timer>();
events = new Dictionary<string, EventManager>();
additionalParameters = new Dictionary<string, List<AdditionalParamData>> ();
eventTypes = new List<string>();
permission.RegisterPermission("arena.admin", this);
lang.RegisterMessages(Messages, this);
isUnloading = false;
}
private void OnServerInitialized() {
ins = this;
LoadData();
cmd.AddChatCommand(configData.ServerSettings.ChatCommand, this, cmdEventMenu);
if (!configData.EventSettings.Continual) {
Unsubscribe(nameof(OnPlayerInput));
Unsubscribe(nameof(OnPlayerTick));
}
if (!configData.EventSettings.AddToTeams) {
Unsubscribe(nameof(OnTeamDisband));
Unsubscribe(nameof(OnTeamLeave));
Unsubscribe(nameof(OnTeamInvite));
}
timer.In(2, InitializePluginReferences);
}
private void Unload() {
isUnloading = true;
SaveRestoreData();
EventManager[] eventGames = UnityEngine.Object.FindObjectsOfType<EventManager>();
if (eventGames != null) {
foreach (EventManager eventGame in eventGames) UnityEngine.Object.Destroy(eventGame);
}
EventPlayer[] eventPlayers = UnityEngine.Object.FindObjectsOfType<EventPlayer>();
if (eventPlayers != null) {
foreach (EventPlayer eventPlayer in eventPlayers) {
UnityEngine.Object.DestroyImmediate(eventPlayer);
}
}
events.Clear();
ins = null;
Events = null;
Statistics = null;
UI = null;
Loot = null;
}
private void OnServerSave() => SaveRestoreData();
private void OnPlayerConnected(BasePlayer player) {
if (!isInitialized || player == null) return;
if (player.IsDead() || player.IsSleeping() || player.HasPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot)) {
timer.Once(1.5f, () => OnPlayerConnected(player));
return;
}
UnlockInventory(player);
if (configData.ServerSettings.EventOnly) {
EventPlayer eventPlayer = GetUser(player);
if (eventPlayer != null) UnityEngine.Object.DestroyImmediate(eventPlayer);
if (!string.IsNullOrEmpty(configData.LobbySettings.LobbyZoneID)) {
if (!(bool)ZoneManager.Call("isPlayerInZone", configData.LobbySettings.LobbyZoneID, player)) SendToWaiting(player);
}
if (configData.ServerSettings.MenuOnJoin && events.Count > 0) UI.OpenMainMenu(player, events.First().Value.config.eventType);
}
else {
if (restoreData.HasRestoreData(player.userID)) restoreData.RestorePlayer(player);
}
}
private void OnPlayerRespawned(BasePlayer player) {
if (configData.ServerSettings.EventOnly) {
EventPlayer eventPlayer = GetUser(player);
if (eventPlayer != null && eventPlayer.hasEnteredEvent) {
EventManager manager = GetEvent(eventPlayer.currentEvent);
if (manager != null && manager.eventPlayers.Contains(eventPlayer)) manager.LeaveEvent(eventPlayer);
UnityEngine.Object.DestroyImmediate(eventPlayer);
}
UnlockInventory(player);
SendToWaiting(player);
}
}
private void OnPlayerDisconnected(BasePlayer player) {
EventPlayer eventPlayer = GetUser(player);
if (eventPlayer != null) {
EventManager manager = GetEvent(eventPlayer.currentEvent);
if (manager != null) manager.LeaveEvent(eventPlayer);
UnityEngine.Object.Destroy(eventPlayer);
UnlockInventory(player);
UI.DestroyAllUI(player);
if (player.IsAlive()) player.DieInstantly();
}
}
private void OnPlayerInput(BasePlayer player, InputState input) {
if (player == null || input == null) return;
EventPlayer eventPlayer = player.GetComponent<EventPlayer>();
if (eventPlayer != null) {
if (eventPlayer.player.IsSpectating()) {
if (input.WasJustPressed(BUTTON.JUMP)) eventPlayer.UpdateSpectateTarget(1);
else if (input.WasJustPressed(BUTTON.DUCK)) eventPlayer.UpdateSpectateTarget(-1);
}
}
}
private object OnPlayerTick(BasePlayer player, PlayerTick msg, bool wasPlayerStalled) {
EventPlayer eventPlayer = player.GetComponent<EventPlayer>();
if (eventPlayer != null) {
if (eventPlayer.player.IsSpectating()) return false;
}
return null;
}
private void OnEntityTakeDamage(BaseEntity entity, HitInfo info) {
if (isInitialized) {
if (entity == null || info == null) return;
BasePlayer player = entity.ToPlayer();
if (player != null) {
EventPlayer eventPlayer = GetUser(player);
if (eventPlayer != null) {
if (!eventPlayer.hasEnteredEvent) return;
EventManager manager = GetEvent(eventPlayer.currentEvent);
if (manager == null) return;
manager.OnPlayerTakeDamage(eventPlayer, info);
}
}
else {
EventPlayer attacker = GetUser(info.InitiatorPlayer);
if (attacker != null) {
if (!attacker.hasEnteredEvent) return;
EventManager manager = GetEvent(attacker.currentEvent);
if (manager != null) {
manager.CanPlayerDealDamage(attacker, entity, info);
return;
}
NullifyDamage(info);
}
}
}
}
private object CanBeWounded(BasePlayer player, HitInfo info) {
if (player != null) {
EventPlayer eventPlayer = GetUser(player);
if (eventPlayer != null) {
if (!eventPlayer.hasEnteredEvent) return null;
EventManager manager = GetEvent(eventPlayer.currentEvent);
if (manager != null) return false;
}
}
return null;
}
private object OnPlayerDeath(BasePlayer player, HitInfo info) {
if (player != null) {
EventPlayer eventPlayer = GetUser(player);
if (eventPlayer != null) {
if (!eventPlayer.hasEnteredEvent) return null;
EventManager manager = GetEvent(eventPlayer.currentEvent);
if (manager != null) {
if (!eventPlayer.isDead) manager.OnPlayerDeath(eventPlayer, info);
return false;
}
}
}
return null;
}
private void OnRunPlayerMetabolism(PlayerMetabolism metabolism, BaseCombatEntity entity, float delta) {
if (isInitialized) {
EventPlayer eventPlayer = GetUser(entity?.ToPlayer());
if (eventPlayer == null) return;
if (eventPlayer.isDead) {
metabolism.bleeding.value = 0;
metabolism.poison.value = 0;
metabolism.radiation_level.value = 0;
metabolism.radiation_poison.value = 0;
metabolism.wetness.value = 0;
}
}
}
private void OnEntitySpawned(BaseNetworkable entity) {
if (isInitialized) {
if (entity == null) return;
if (configData.ServerSettings.NoHelicopters && entity is BaseHelicopter) {
NextTick(() => {
if (entity != null) (entity as BaseHelicopter).DieInstantly();
return;
}
);
}
if (configData.ServerSettings.NoAirdrops && entity is CargoPlane) {
NextTick(() => {
if (entity != null) entity.Kill();
return;
}
);
}
if (configData.ServerSettings.NoAnimals && entity is BaseNpc) {
NextTick(() => {
if (entity != null) (entity as BaseNpc).DieInstantly();
return;
}
);
}
}
}
private object OnCreateWorldProjectile(HitInfo info, Item item) {
if (isInitialized) {
if (info == null) return null;
if (info.InitiatorPlayer != null) {
EventPlayer eventPlayer = GetUser(info.InitiatorPlayer);
if (eventPlayer != null) {
if (!eventPlayer.hasEnteredEvent) return null;
return false;
}
}
if (info.HitEntity?.ToPlayer() != null) {
EventPlayer eventPlayer = GetUser(info.HitEntity.ToPlayer());
if (eventPlayer != null) {
if (!eventPlayer.hasEnteredEvent) return null;
return false;
}
}
}
return null;
}
private object CanDropActiveItem(BasePlayer player) {
EventPlayer eventPlayer = player.GetComponent<EventPlayer>();
if (eventPlayer != null) {
if (!eventPlayer.hasEnteredEvent) return null;
return false;
}
return null;
}
private object CanLootEntity(BasePlayer player, StorageContainer container) => CanPlayerLoot(player);
private object CanLootEntity(BasePlayer player, DroppedItemContainer container) => CanPlayerLoot(player);
private object CanLootEntity(BasePlayer player, LootableCorpse container) => CanPlayerLoot(player);
private object CanLootEntity(BasePlayer player, ResourceContainer container) => CanPlayerLoot(player);
private object CanPlayerLoot(BasePlayer player) {
if (player != null) {
EventPlayer eventPlayer = GetUser(player);
if (eventPlayer != null) {
if (!eventPlayer.hasEnteredEvent) return null;
EventManager manager = GetEvent(eventPlayer.currentEvent);
if (manager != null && manager.status != EventStatus.Started) {
player.ChatMessage(msg("nolooting", player.userID));
return false;
}
}
}
return null;
}
private void OnEntityBuilt(Planner planner, GameObject gObject) {
BasePlayer player = planner?.GetOwnerPlayer();
if (player == null) return;
BaseEntity entity = gObject?.ToBaseEntity();
if (entity == null) return;
if (entity is BaseCombatEntity) {
EventPlayer eventPlayer = GetUser(player);
if (eventPlayer == null) return;
EventManager manager = GetEvent(eventPlayer.currentEvent);
if (manager == null) return;
manager.OnEntityDeployed(entity as BaseCombatEntity);
}
}
private void OnItemDeployed(Deployer deployer, BaseEntity deployedEntity) {
BasePlayer player = deployer.GetOwnerPlayer();
if (player == null) return;
if (deployedEntity is BaseCombatEntity) {
EventPlayer eventPlayer = GetUser(player);
if (eventPlayer == null) return;
EventManager manager = GetEvent(eventPlayer.currentEvent);
if (manager == null) return;
manager.OnEntityDeployed(deployedEntity as BaseCombatEntity);
}
}
private object CanNetworkTo(BasePlayer player, BasePlayer target) {
if (isInitialized) {
EventPlayer eventPlayer = GetUser(player);
if (eventPlayer != null && eventPlayer.isDead) return false;
}
return null;
}
//private object CanNetworkTo(HeldEntity entity, BasePlayer target)
//{
// if (isInitialized)
// {
// EventPlayer eventPlayer = GetUser(entity?.GetOwnerPlayer());
// if (eventPlayer != null && eventPlayer.isDead)
// return false;
// }
// return null;
//}
private object OnPlayerChat(BasePlayer player, string message, ConVar.Chat.ChatChannel channel) {
if (!configData.ServerSettings.UseChat) return null;
if (player != null) {
if (player.IsAdmin || permission.UserHasPermission(player.UserIDString, "arena.admin")) return null;
EventPlayer eventPlayer = GetUser(player);
if (eventPlayer != null && eventPlayer.hasEnteredEvent) GetEvent(eventPlayer.currentEvent)?.ChatToPlayers(eventPlayer.player, message);
else {
foreach (BasePlayer otherPlayer in BasePlayer.activePlayerList.Where(x => GetUser(x) == null)) otherPlayer.SendConsoleCommand("chat.add", new object[] {
0, player.UserIDString, $"<color={(player.IsAdmin ? "#aaff55" : player.IsDeveloper ? "#fa5" : "#55AAFF")}>{player.displayName}</color>: {message}"
}
);
}
return false;
}
return false;
}
private object OnPlayerCommand(BasePlayer player, string command, string[] args) {
EventPlayer eventPlayer = GetUser(player);
if (player == null || player.IsAdmin || eventPlayer == null || !eventPlayer.hasEnteredEvent) return null;
if (configData.EventSettings.CommandBlacklist.Any(x => command.ToLower().Equals(x.ToLower()))) {
SendReply(player, msg("blacklistcmd", player.userID));
return false;
}
return null;
}
private object OnServerCommand(ConsoleSystem.Arg arg) {
BasePlayer player = arg.Player();
EventPlayer eventPlayer = GetUser(player);
if (player == null || player.IsAdmin || eventPlayer == null || !eventPlayer.hasEnteredEvent || arg.Args == null) return null;
if (configData.EventSettings.CommandBlacklist.Any(x => arg.cmd.FullName.ToLower().Equals(x.ToLower()))) {
SendReply(player, msg("blacklistcmd", player.userID));
return false;
}
return null;
}
private object OnTeamLeave(RelationshipManager.PlayerTeam playerTeam, BasePlayer player) {
EventPlayer eventPlayer = GetUser(player);
if (eventPlayer == null) return null;
EventManager eventManager = GetEvent(eventPlayer.currentEvent);
if (Events.IsTeamEvent(eventManager.config.eventType)) {
return true;
}
return null;
}
private object OnTeamDisband(RelationshipManager.PlayerTeam playerTeam) {
foreach(KeyValuePair<string, EventManager> kvp in events) {
if (playerTeam == kvp.Value.playerTeamA || playerTeam == kvp.Value.playerTeamB) return true;
}
return null;
}
private object OnTeamInvite(BasePlayer player, BasePlayer other) {
EventPlayer eventPlayer = GetUser(player);
if (eventPlayer != null) return true;
return null;
}
private object OnTeamCreate(BasePlayer player) {
EventPlayer eventPlayer = GetUser(player);
if (eventPlayer != null) return true;
return null;
}
#endregion
#region Deathnotes
private object OnDeathNotice(Dictionary<string, object> data, string message) {
object obj;
if (data.TryGetValue("VictimEntity", out obj)) {
BaseCombatEntity victim = obj as BaseCombatEntity;
if (victim != null) {
if (victim.GetComponent<EventPlayer>() || victim.GetComponent<ArenaEvents.NPCSurvival.NPCController>()) return false;
}
}
return null;
}
#endregion
#region Classes and Components
public enum EventStatus {
Pending, Started, Finished
}
public enum ScoreType {
Kills, Deaths, KD
}
public enum Team {
A, B, None
}
public class EventManager : MonoBehaviour {
#region Fields
public string eventName;
public ArenaData.EventConfig config;
public EventStatus status;
internal GameTimer gameTimer;
internal SpawnManager spawnManagerA;
internal SpawnManager spawnManagerB;
private CuiElementContainer scoreContainer = null;
public List<ScoreEntry> scoreData;
public List<EventPlayer> eventPlayers = new List<EventPlayer>();
internal RelationshipManager.PlayerTeam playerTeamA;
internal RelationshipManager.PlayerTeam playerTeamB;
internal bool showKillFeed;
public bool showGameTimers;
public bool godEnabled;
public bool isContinual;
public bool deathKick;
private bool dropAmmo;
private bool dropWeapon;
private bool dropBackpack;
public string currentKit;
private double timeRemaining;
private Dictionary<string, ArenaData.EventConfig> closedEvents = new Dictionary<string, ArenaData.EventConfig>();
private List<BaseCombatEntity> deployedObjects = new List<BaseCombatEntity>();
#endregion
#region Component Management
private void Awake() {
dropAmmo = ins.configData.EventSettings.DropAmmo;
dropWeapon = ins.configData.EventSettings.DropWeapon;
dropBackpack = ins.configData.EventSettings.DropBackpack;
showKillFeed = ins.configData.EventSettings.UseKillFeed;
showGameTimers = ins.configData.GameTimers.ShowGameTimer;
isContinual = ins.configData.EventSettings.Continual;
deathKick = ins.configData.EventSettings.DeathKick;
enabled = false;
gameTimer = gameObject.AddComponent<GameTimer>();
gameTimer.Register(this, TimerExpired, showGameTimers);
}
public virtual void OnDestroy() {
RespawnAllPlayers();
EjectAllPlayers();
if (gameTimer != null) Destroy(gameTimer);
}
public virtual void InitializeEvent(string eventName, ArenaData.EventConfig config) {
this.eventName = eventName;
this.config = config;
spawnManagerA = new SpawnManager();
spawnManagerA.SetSpawnFile(config.eventName, config.teamA.spawnfile);
if (Events.IsTeamEvent(config.eventType)) {
spawnManagerB = new SpawnManager();
spawnManagerB.SetSpawnFile(config.eventName, config.teamB.spawnfile);
}
if (config.eventKits.Count > 0) currentKit = config.eventKits[0];
godEnabled = true;
status = EventStatus.Finished;
InvokeHandler.Invoke(this, WaitMessage, 7f);
if (Events.IsTeamEvent(config.eventType) && ins.configData.EventSettings.AddToTeams) {
playerTeamA = RelationshipManager.Instance.CreateTeam();
playerTeamB = RelationshipManager.Instance.CreateTeam();
}
}
public void CheckValidTeams() {
if (playerTeamA == null) playerTeamA = RelationshipManager.Instance.CreateTeam();
if (playerTeamB == null) playerTeamB = RelationshipManager.Instance.CreateTeam();
}
#endregion
#region Event Management
public void TimerExpired() {
switch (status) {
case EventStatus.Pending : StartMatch();
return;
case EventStatus.Started : EndMatch();
return;
case EventStatus.Finished : Prestart();
return;
}
}
public virtual void Prestart() {
if (!HasValidPlayers()) return;
InvokeHandler.CancelInvoke(this, WaitMessage);
DestroyAllPopups();
scoreData = new List<ScoreEntry>();
status = EventStatus.Pending;
gameTimer.StartTimer(ins.configData.GameTimers.MatchPrestart[config.eventType], msg("roundstarts"));
if (!string.IsNullOrEmpty(config.zoneId)) Loot.OnEventStarted(config.zoneId);
foreach (EventPlayer eventPlayer in eventPlayers) SpawnPlayer(eventPlayer, false, true);
}
public virtual void StartMatch() {
if (!HasValidPlayers()) return;
status = EventStatus.Started;
godEnabled = false;
if (config.timeLimit > 0) gameTimer.StartTimer(config.timeLimit * 60);
foreach (EventPlayer eventPlayer in eventPlayers) {
UI.DestroyUI(eventPlayer.player, ArenaUI.UIPanel.Menu);
eventPlayer.ResetStats();
SpawnPlayer(eventPlayer);
}
UpdateScoreboard();
}
public virtual void EndMatch() {
gameTimer.StopTimer();
if (!string.IsNullOrEmpty(config.zoneId)) Loot.OnEventFinished(config.zoneId);
status = EventStatus.Finished;
godEnabled = true;
RespawnAllPlayers();
if (!isUnloading) {
ins.NextTick(() => {
CleanupEntities();
foreach (EventPlayer eventPlayer in eventPlayers) {
if (eventPlayer.player == null) continue;
Statistics.OnGamePlayed(eventPlayer.player.userID, config);
StripInventory(eventPlayer.player);
if (eventPlayer.isOOB) {
eventPlayer.isOOB = false;
if (ins.killTimers.ContainsKey(eventPlayer.player.userID)) {
ins.killTimers[eventPlayer.player.userID].Destroy();
ins.killTimers.Remove(eventPlayer.player.userID);
}
}
UI.DestroyUI(eventPlayer.player, ArenaUI.UIPanel.Menu);
DisplayFinalScoreboard();
}
Statistics.OnGameFinished(config.eventType, config.eventName);
if (isContinual) {
SwitchTeams();
InvokeHandler.Invoke(this, ResetMatch, 5f);
}
else InvokeHandler.Invoke(this, EjectAllPlayers, 5f);
}
);
}
}
private void SwitchTeams() {
if (!Events.IsTeamEvent(config.eventType) || !config.switchTeamOnRepeat) return;
ArenaData.EventConfig.TeamEntry teamA = config.teamA;
ArenaData.EventConfig.TeamEntry teamB = config.teamB;
config.teamA = teamB;
config.teamB = teamA;
spawnManagerA.SetSpawnFile(config.eventName, config.teamA.spawnfile);
spawnManagerB.SetSpawnFile(config.eventName, config.teamB.spawnfile);
}
private void ResetMatch() {
foreach (EventPlayer eventPlayer in eventPlayers) {
if (eventPlayer.player.IsSpectating()) eventPlayer.FinishSpectating();
StripInventory(eventPlayer.player);
eventPlayer.ResetStats();
}
if (eventPlayers.Count >= config.playersToStart) {
BroadcastToPlayers("playersreached", new string[] {
ins.configData.GameTimers.MatchPrestart[config.eventType].ToString()
}
, true);
Prestart();
}
else InvokeHandler.Invoke(this, WaitMessage, 5f);
}
public void EjectAllPlayers() {
if (eventPlayers.Count > 0) {
for (int i = eventPlayers.Count - 1; i >= 0; i--) LeaveEvent(eventPlayers[i]);
eventPlayers.Clear();
}
}
private void RespawnAllPlayers() {
foreach(EventPlayer eventPlayer in eventPlayers) {
if (eventPlayer.player.IsSpectating()) eventPlayer.FinishSpectating();
if (eventPlayer.isDead) ins.RespawnPlayer(eventPlayer.player);
}
}
private void CheckPlayers() {
if (eventPlayers.Count < config.minimumPlayers) {
switch (status) {
case EventStatus.Finished : case EventStatus.Pending : gameTimer.StopTimer();
status = EventStatus.Finished;
BroadcastToPlayers("notenoughtostart", null, true);
InvokeHandler.Invoke(this, WaitMessage, 7f);
break;
case EventStatus.Started : gameTimer.StopTimer();
BroadcastToPlayers("notenoughtocontinue", null, true);
EndMatch();
break;
}
}
}
private bool HasValidPlayers() {
for (int i = eventPlayers.Count - 1; i >= 0; i--) {
EventPlayer eventPlayer = eventPlayers[i];
if (eventPlayer == null || eventPlayer.player == null || !eventPlayer.player.IsConnected) {
eventPlayers.Remove(eventPlayer);
Destroy(eventPlayer);
}
}
if (eventPlayers.Count == 0 || eventPlayers.Count < config.playersToStart) {
status = EventStatus.Finished;
gameTimer.StopTimer();
BroadcastToPlayers("notenoughtostart", null, true);
InvokeHandler.Invoke(this, WaitMessage, 7f);
return false;
}
return true;
}
private void WaitMessage() {
if (status == EventStatus.Finished) {
BroadcastToPlayers("notenoughtostart", null, true);
InvokeHandler.Invoke(this, WaitMessage, 7f);
}
}
public void DisableMatchingZones() {
closedEvents.Clear();
KeyValuePair<string, EventManager>[] events = ins.events.Where(x => (!string.IsNullOrEmpty(x.Value.config.zoneId) && x.Value.config.zoneId == config.zoneId && x.Value != this)).ToArray();
if (events.Length > 0) {
for (int i = events.Length - 1; i >= 0; i--) {
KeyValuePair<string, EventManager> eventGame = events[i];
closedEvents.Add(eventGame.Key, eventGame.Value.config);
eventGame.Value.EndMatch();
eventGame.Value.EjectAllPlayers();
Destroy(eventGame.Value);
ins.events.Remove(eventGame.Key);
}
}
}
public void EnableMatchingZones() {
if (isUnloading) return;
foreach(KeyValuePair<string, ArenaData.EventConfig> eventGame in closedEvents) ins.InitializeEvent(eventGame.Key, eventGame.Value);
closedEvents.Clear();
}
#endregion
#region Player Management
public virtual bool CanJoinEvent() {
if (eventPlayers.Count >= config.maximumPlayers) return false;
return true;
}
public virtual void JoinEvent(EventPlayer eventPlayer, Team team) {
if (!string.IsNullOrEmpty(config.zoneId)) {
ins.ZoneManager?.Call("AddPlayerToZoneWhitelist", config.zoneId, eventPlayer.player);
if (ins.configData.EventSettings.DisableUsedZones && eventPlayers.Count == 1) DisableMatchingZones();
}
if (ins.configData.EventSettings.BroadcastJoiners) {
BroadcastToAll("joineventglobal", new string[] {
eventPlayer.player.displayName, config.eventName
}
);
}
}
public virtual void LeaveEvent(EventPlayer eventPlayer) {
if (eventPlayers.Contains(eventPlayer)) {
if (eventPlayer.player != null) {
if (eventPlayer.player.IsSpectating()) eventPlayer.FinishSpectating();
if (eventPlayer.player.IsSleeping()) eventPlayer.player.Die();
else {
StripInventory(eventPlayer.player);
//eventPlayer.player.inventory.Strip();
if (!ins.configData.ServerSettings.EventOnly) eventPlayer.RestorePlayer();
else ins.SendToWaiting(eventPlayer.player);
}
}
if (!string.IsNullOrEmpty(config.zoneId)) ins.ZoneManager?.Call("RemovePlayerFromZoneWhitelist", config.zoneId, eventPlayer.player);
eventPlayers.Remove(eventPlayer);
DestroyImmediate(eventPlayer);
if (status != EventStatus.Finished) CheckPlayers();
if (ins.configData.EventSettings.DisableUsedZones && eventPlayers.Count == 0) EnableMatchingZones();
}
}
public void SpawnPlayer(EventPlayer eventPlayer, bool giveKit = true, bool sleep = false) {
BasePlayer player = eventPlayer.player;
if (player == null) return;
if (!ins.configData.EventSettings.SendToArenaOnJoin) eventPlayer.SetPlayer();
if (!eventPlayer.hasEnteredEvent) {
if (Events.IsTeamEvent(config.eventType) && ins.configData.EventSettings.AddToTeams) {
switch (eventPlayer.team) {
case Team.A : playerTeamA.AddPlayer(eventPlayer.player);
break;
case Team.B : playerTeamB.AddPlayer(eventPlayer.player);
break;
}
}
eventPlayer.hasEnteredEvent = true;
}
StripInventory(player);
ins.ResetMetabolism(player);
Vector3 spawnPoint = eventPlayer.team == Team.A ? spawnManagerA.GetSpawnPoint() : spawnManagerB.GetSpawnPoint();
ins.MovePosition(player, spawnPoint, sleep);
if (config.useClassSelector && eventPlayer.currentKit == -1) {
eventPlayer.RemoveFromNetwork();
UI.ShowSpawnScreen(eventPlayer.player);
return;
}
OnPlayerSpawn(eventPlayer);
if (scoreContainer != null) {
UI.DestroyUI(eventPlayer.player, ArenaUI.UIPanel.Scores);
UI.AddUI(eventPlayer.player, ArenaUI.UIPanel.Scores, scoreContainer);
}
if (giveKit) {
ins.NextTick(() => {
if (OverridePlayerKit(eventPlayer) is bool) return;
if (config.eventKits.Count > 1 && config.useClassSelector) ins.GiveKit(player, config.eventKits[eventPlayer.currentKit]);
else ins.GiveKit(player, currentKit);
GiveTeamGear(eventPlayer);
if (ins.configData.EventSettings.LockInventory) LockInventory(eventPlayer.player);
}
);
}
UI.ShowHelpText(player);
}
public virtual void OnPlayerSpawn(EventPlayer eventPlayer) {
}
public virtual void GiveTeamGear(EventPlayer eventPlayer) {
}
public virtual object OverridePlayerKit(EventPlayer eventPlayer) {
return null;
}
public virtual EventPlayer[] GetSpectateTargets(Team team) {
return eventPlayers.Where(x => x.team == team && !x.player.IsSpectating()).ToArray();
}
public int CountAlive() {
int alive = 0;
foreach (EventPlayer eventPlayer in eventPlayers) if (!eventPlayer.isDead && !eventPlayer.player.IsSpectating()) alive++;
return alive;
}
public int CountStillPlaying() {
int alive = 0;
foreach (EventPlayer eventPlayer in eventPlayers) if (!eventPlayer.isEliminated) alive++;
return alive;
}
public int GetTeamCount(Team team) {
IEnumerable<EventPlayer> players = eventPlayers.Where(x => x.team == team);
if (players == null) return 0;
else return players.Count();
}
public int GetTeamAlive(Team team) {
IEnumerable<EventPlayer> players = eventPlayers.Where(x => x.team == team && !x.isDead && !x.player.IsSpectating());
if (players == null) return 0;
else return players.Count();
}
public virtual int GetTeamScore(Team team) {
int kills = 0;
IEnumerable<EventPlayer> teamPlayers = eventPlayers.Where(x => x.team == team);
foreach (EventPlayer eventPlayer in teamPlayers) kills += eventPlayer.kills;
return kills;
}
public void BalanceTeams() {
int aCount = GetTeamCount(Team.A);
int bCount = GetTeamCount(Team.B);
int difference = aCount > bCount + 1 ? aCount - bCount : bCount > aCount + 1 ? bCount - aCount : 0;
Team moveFrom = aCount > bCount + 1 ? Team.A : bCount > aCount + 1 ? Team.B : Team.None;
if (difference > 1 && moveFrom != Team.None) {
BroadcastToPlayers("teamsunbalanced", null, true);
EventPlayer[] teamPlayers = eventPlayers.Where(x => x.team == moveFrom).ToArray();
for (int i = 0; i < (int)Math.Floor((float)difference / 2);
i++) {
EventPlayer eventPlayer = teamPlayers.GetRandom();
eventPlayer.team = moveFrom == Team.A ? Team.B : Team.A;
BroadcastToPlayer(eventPlayer, string.Format(msg("teamswitched", eventPlayer.player.userID), eventPlayer.team));
}
}
}
#endregion
#region Death and Damage Management
public virtual bool CanPlayerDealDamage(EventPlayer attacker, BaseEntity entity, HitInfo info) {
return false;
}
public virtual void OnPlayerTakeDamage(EventPlayer eventPlayer, HitInfo info) {
BasePlayer player = eventPlayer.player;
EventPlayer attacker = ins.GetUser(info.InitiatorPlayer);
if (godEnabled || eventPlayer.isDead) {
ins.NullifyDamage(info);
return;
}
if (info.isHeadshot) {
if (attacker != null) Statistics.OnHeadshot(attacker.player.userID, config);
}
float damageModifier = GetDamageModifier(attacker);
if (damageModifier != 0) info.damageTypes.ScaleAll(damageModifier);
eventPlayer.OnTakeDamage(attacker?.player.userID ?? 0U);
}
public void OnPlayerDeath(EventPlayer eventPlayer, HitInfo info) {
eventPlayer.isDead = true;
BasePlayer player = eventPlayer.player;
if (dropBackpack && CanDropBackpack()) {
DroppedItemContainer itemContainer = ItemContainer.Drop("assets/prefabs/misc/item drop/item_drop_backpack.prefab", player.transform.position, Quaternion.identity, new ItemContainer[] {
player.inventory.containerBelt, player.inventory.containerMain
}
);
if (itemContainer != null) {
itemContainer.playerName = player.displayName;
itemContainer.playerSteamID = player.userID;
}
}
else {
if (dropAmmo && CanDropAmmo()) {
Item item = player.GetActiveItem();
if (item != null) {
BaseProjectile weapon = item.GetHeldEntity() as BaseProjectile;
if (weapon != null && weapon.primaryMagazine.contents > 0) {
Item ammo = ItemManager.Create(weapon.primaryMagazine.ammoType, weapon.primaryMagazine.contents);
BaseEntity entity = ammo.Drop(player.transform.position, Vector3.up);
ammo.Remove(30f);
weapon.primaryMagazine.contents = 0;
ins.RotateDroppedItem(entity);
}
}
}
if (dropWeapon && CanDropWeapons()) {
Item item = player.GetActiveItem();
if (item != null) {
BaseEntity entity = item.Drop(player.transform.position, Vector3.up);
item.Remove(30f);
ins.RotateDroppedItem(entity);
}
}
}
Statistics.OnEventPlayerDeath(eventPlayer, info, config);
//EventPlayer attacker = ins.GetUser(info.InitiatorPlayer);
OnPlayerDeath(eventPlayer, info?.InitiatorPlayer ?? null, info);
if (info != null) ins.NullifyDamage(info);
}
public virtual bool CanShowDeathScreen() {
return true;
}
public virtual void OnPlayerDeath(EventPlayer victim, BasePlayer attacker = null, HitInfo info = null) {
if (victim == null || victim.player == null) return;
victim.isDead = true;
victim.player.Invoke(()=> StripInventory(victim.player), 0.25f);
//victim.player.inventory.Strip();
victim.player.RemoveFromTriggers();
victim.RemoveFromNetwork();
if (victim.player.isMounted) {
BaseMountable baseMountable = victim.player.GetMounted();
if (baseMountable != null) {
baseMountable.DismountPlayer(victim.player);
victim.player.EnsureDismounted();
}
}
string attackerName = attacker != null ? attacker.displayName : string.Empty;
if (CanShowDeathScreen()) UI.ShowDeathScreen(victim.player, string.IsNullOrEmpty(attackerName) ? msg("aredead", victim.player.userID) : string.Format(msg("killedby", victim.player.userID), attackerName), ins.configData.GameTimers.RespawnTimer[config.eventType]);
if (showKillFeed) DisplayKillToChat(victim, attackerName);
}
private void DisplayKillToChat(EventPlayer victim, string attackerName) {
if (Events.IsSurvivalEvent(config.eventType)) {
int remaining = CountAlive();
if (remaining > 1) {
if (string.IsNullOrEmpty(attackerName)) {
if (victim.isOOB) {
BroadcastToPlayers("survrunaway", new string[] {
victim.player.displayName, remaining.ToString()
}
);
}
else BroadcastToPlayers("survsuicide", new string[] {
victim.player.displayName, remaining.ToString()
}
);
}
else {
BroadcastToPlayers("survkilledplayer", new string[] {
attackerName, victim.player.displayName, remaining.ToString()
}
);
}
}
}
else {
if (string.IsNullOrEmpty(attackerName)) {
if (victim.isOOB) {
BroadcastToPlayers("runaway", new string[] {
victim.player.displayName
}
);
}
else BroadcastToPlayers("suicide", new string[] {
victim.player.displayName
}
);
}
else {
if (config.eventType != "GunGame") BroadcastToPlayers("killedplayer", new string[] {
attackerName, victim.player.displayName
}
);
}
}
}
public virtual void OnNpcDeath(BaseCombatEntity entity, HitInfo info) {
}
public virtual void OnNpcCorpseSpawned(LootableCorpse corpse) {
}
public virtual bool IsEventNPC(ulong corpseId) {
return false;
}
public virtual bool CanDropWeapons() {
return true;
}
public virtual bool CanDropAmmo() {
return true;
}
public virtual bool CanDropBackpack() {
return true;
}
public virtual float GetDamageModifier(EventPlayer attacker) {
if (attacker != null) return GetDamageModifier(attacker.player.userID);
return 0f;
}
public virtual float GetDamageModifier(ulong attackerId) {
return 0f;
}
#endregion
#region Entity Management
public void OnEntityDeployed(BaseCombatEntity entity) {
deployedObjects.Add(entity);
}
private void CleanupEntities() {
for (int i = deployedObjects.Count - 1; i >= 0; i--) {
BaseCombatEntity entity = deployedObjects[i];
if (entity != null && !entity.IsDestroyed) entity.DieInstantly();
}
deployedObjects.Clear();
}
#endregion
#region Menu Management
public virtual Dictionary<string, string> GetAdditionalInformation() {
return new Dictionary<string, string>();
}
#endregion
#region Scoreboards
public void DisplayFinalScoreboard() => UI.ShowEventResults(this);
public void UpdateScoreboard() {
scoreContainer = UI.ShowGameScores(this);
}
public void DestroyScoreboard(BasePlayer player) => UI.DestroyUI(player, ArenaUI.UIPanel.Scores);
public virtual List<ScoreEntry> GetGameScores(Team team = Team.A) {
List<ScoreEntry> gameScores = new List<ScoreEntry>();
int i = 1;
foreach (EventPlayer eventPlayer in eventPlayers.Where(x => x.team == team).OrderByDescending(x
// ... [Code preview truncated due to length. Full source in attached file] ...