Иконка ресурса

FREE AimTrainingGameManager : 0.0.1 0.0.1

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using Oxide.Core;
using Oxide.Core.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace Oxide.Plugins {
    [Info("Aim Training Game Manager", "Fyre", "0.0.1")]
    public class AimTrainingGameManager : RustPlugin {
        /**
		 * For 1v1 ranked scrims, to make it simple have 1 arena where 2 people are fighting and have the rest spectating
		 * (maybe dont let them spectate so they can't give callouts on discord, or have no spectators at all)
		 * 
		 * Need a better way of finding what game and what team a player is on
		 * (maybe a new class that contains BasePlayer with game and side information, make a list of this object and then have
		 * a method to find the object in the list by the BasePlayer for when a hook only gives BasePlayer)
		 * then change spectating instead of its own team to a flag (isSpectating) and then maybe make another (isOnlySpectating) if they wish to stay spectating and not join a team.* Need a way to differentiate between flats, gamemodes, etc.but also need the player to be able to be in no games (isInGame or something?) with flatID and team null for example
		 * 
		 * TODO: I actually like that idea ^
		 */
        private List<Game> games;
#region Oxide Hooks
        void Init() {
            Util.initFlatConfig();
            games = new List<Game>();
        }
        // Moves players back to their team's spawn when they are too far away from it
        object OnPlayerTick(BasePlayer player, PlayerTick msg, bool wasPlayerStalled) {
            foreach (Game g in games) {
                if (!g.isStarted) {
                    string side = null;
                    if (g.aTeamPlayers.Contains(player)) {
                        side = "a";
                        break;
                    }
                    else if (g.bTeamPlayers.Contains(player)) {
                        side = "b";
                    }
                    if (side != null) {
                        Vector3 curPos = player.ServerPosition;
                        // TODO: Test this: Vector3 diff = g.GetSpawn(side) - curPos; and compare this instead (check if Math.abs(diff.x) or Math.abs(diff.z) is greater than 9)
                        if (Math.Abs(curPos.x - g.GetSpawn(side).x) > 9 || Math.Abs(curPos.z - g.GetSpawn(side).z) > 9) {
                            player.Teleport(g.GetSpawn(side));
                        }
                        break;
                    }
                }
            }
            return null;
        }
        /**
		 * Stop ingame players from taking damage unless the game they are in has started or the attacker is on the same team
		 */
        object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
            if (info.HitEntity.GetType() != typeof(BasePlayer)) {
                return null;
            }
            BasePlayer attacker = info.InitiatorPlayer;
            BasePlayer victim = (BasePlayer)info.HitEntity;
            bool sameTeam = false;
            bool isAttackerInGame = false;
            Game attackerGame = null;
            foreach (Game game in games) {
                if (game.aTeamPlayers.Contains(attacker)) {
                    if (game.aTeamPlayers.Contains(victim)) {
                        sameTeam = true;
                    }
                    isAttackerInGame = true;
                    attackerGame = game;
                    break;
                }
                else if (game.bTeamPlayers.Contains(attacker)) {
                    if (game.bTeamPlayers.Contains(victim)) {
                        sameTeam = true;
                    }
                    isAttackerInGame = true;
                    attackerGame = game;
                    break;
                }
            }
            // TODO: Change "|| sameTeam" to enable friendly fire
            if (isAttackerInGame && (!attackerGame.isStarted || sameTeam)) {
                info.damageTypes.ScaleAll(0);
            }
            return null;
        }
        /*
		 * If player is going to die, instead of killing them have them heal and teleport to spectator spawn
		 */
        object OnPlayerDeath(BasePlayer player, HitInfo info) {
            /* 
			 * Let the player die if they are disconnected
			 * TODO: Uncomment so it doesn't block death of disconnected players.Commented because bots aren't "connected" to the server so they will also be allowed to be fully killed
			 */
            /*if (!player.IsConnected) {
				return null;
			}*/
            BasePlayer killer = info.InitiatorPlayer;
            // Checking if the killer is in a game
            bool isKillerInGame = false;
            Game killerGame = null;
            foreach (Game game in games) {
                if (game.aTeamPlayers.Contains(killer) || game.bTeamPlayers.Contains(killer)) {
                    isKillerInGame = true;
                    killerGame = game;
                    break;
                }
            }
            if (isKillerInGame) {
                killerGame.OnPlayerKilled(player, info, rust);
            }
            else {
                // This shouldn't happen (the killer wasn't in a game)
                player.StopWounded();
                player.Heal(100);
                player.Teleport(Util.worldSpawn);
            }
            // Returning anything other than null overwrites default behavior (stops them from dying)
            return 0;
        }
        void OnPlayerDisconnected(BasePlayer player) {
            player.Kill();
            foreach (Game game in games) {
                if (game.aTeamPlayers.Contains(player) || game.bTeamPlayers.Contains(player)) {
                    game.OnPlayerLeave(player);
                }
            }
        }
        // Spawn at spawn
        object OnPlayerRespawn(BasePlayer player) {
            return new BasePlayer.SpawnPoint() {
                pos = Util.worldSpawn, rot = new UnityEngine.Quaternion(0, 0, 0, 1)
            }
            ;
        }
        void OnEntitySpawned(BaseNetworkable entity) {
            string[] deletePrefabs = new string[] {
                "hotairballoon.prefab", "stone-collectable.prefab", "testridablehorse.prefab", "horse.corpse.prefab"
            }
            ;
            if (entity.name.EndsWith("player.prefab")) {
                JoinFlat((BasePlayer)entity, "flat", new string[] {
                    "0"
                }
                );
            }
            if (deletePrefabs.Contains(entity.PrefabName)) {
                timer.Once(1, () => {
                    entity.Kill();
                }
                );
            }
        }
#endregion
#region Commands
        [ChatCommand("flat")]
        // TODO: If flat is full, send player to spectators, and send them back again if they try to join from spectator to a team
        void JoinFlat(BasePlayer player, string command, string[] args) {
            if (args.Length == 1 && int.Parse(args[0]) < 9) {
                bool gameExists = false;
                Game runningGame = null;
                foreach (Game g in games) {
                    if (g.aTeamPlayers.Concat(g.bTeamPlayers).ToList().Contains(player)) {
                        rust.SendChatMessage(player, "", "You are already in a game.Type /leave to leave.", player.UserIDString);
                        return;
                    }
                    if (g.flatID == int.Parse(args[0])) {
                        gameExists = true;
                        runningGame = g;
                        break;
                    }
                }
                if (gameExists) {
                    if (runningGame.aTeamPlayers.Count > runningGame.bTeamPlayers.Count) {
                        runningGame.OnPlayerJoinTeam(player, "b");
                    }
                    else {
                        runningGame.OnPlayerJoinTeam(player, "a");
                    }
                    /*
					 * If the game object was created but there aren't any active players as leader, leadership is transferred to the connecting player.* Chances are, this will happen when there is nobody in the arena
					 */
                    if (!runningGame.aTeamPlayers.Contains(runningGame.leader) && !runningGame.bTeamPlayers.Contains(runningGame.leader)) {
                        runningGame.OnLeaderUpdate(player);
                    }
                }
                else {
                    runningGame = new Game(rust);
                    runningGame.flatID = int.Parse(args[0]);
                    // Don't call OnLeaderUpdate here because its the first time the flat is being created
                    runningGame.leader = player;
                    games.Add(runningGame);
                    runningGame.OnPlayerJoinTeam(player, "a");
                }
                rust.SendChatMessage(player, "", "Sending you to flat " + args[0]);
            }
        }
        [ChatCommand("leave")]
        void Leave(BasePlayer player, string command, string[] args) {
            foreach (Game game in games) {
                if (game.aTeamPlayers.Contains(player) || game.bTeamPlayers.Contains(player)) {
                    if (game.isStarted) {
                        rust.SendChatMessage(player, "", "You may not leave a game that has already started.");
                    }
                    else {
                        game.OnPlayerLeave(player);
                    }
                    return;
                }
            }
            rust.SendChatMessage(player, "", "You are not in a game.");
        }
        [ChatCommand("spawn")]
        void TeleportToSpawn(BasePlayer player, string command, string[] args) {
            player.Teleport(Util.worldSpawn);
        }
        [ChatCommand("start")]
        void StartGame(BasePlayer player, string command, string[] args) {
            foreach (Game g in games) {
                if (g.aTeamPlayers.Concat(g.bTeamPlayers).ToList().Contains(player)) {
                    if (g.leader.Equals(player)) {
                        if (!g.isStarted) {
                            if (g.aTeamPlayers.Count > 0 && g.bTeamPlayers.Count > 0) {
                                g.StartRound();
                                foreach (BasePlayer p in g.aTeamPlayers.Concat(g.bTeamPlayers)) {
                                    rust.SendChatMessage(p, "", "A round has started!");
                                }
                                break;
                            }
                            else {
                                rust.SendChatMessage(player, "", "There are not enough players on this flat to start a game.");
                            }
                        }
                        else {
                            rust.SendChatMessage(player, "", "A round has already started.");
                        }
                    }
                    else {
                        rust.SendChatMessage(player, "", "You are not this flat's leader.Ask " + g.leader.displayName + " to type /start");
                    }
                    return;
                }
            }
            rust.SendChatMessage(player, "", "You are not in a game.");
        }
#endregion
    }
    public class Game {
        public int flatID;
        public BasePlayer leader;
        public List<BasePlayer> aTeamPlayers;
        public List<BasePlayer> bTeamPlayers;
        public Dictionary<BasePlayer, string> spectators;
        private Oxide.Game.Rust.Libraries.Rust rust;
        public List<string> kitAttire;
        public List<string> kitWeapons;
        public List<string> kitAmmo;
        public Dictionary<string, int> kitMeds;
        public bool isStarted;
        public Game(Oxide.Game.Rust.Libraries.Rust rust) {
            aTeamPlayers = new List<BasePlayer>();
            bTeamPlayers = new List<BasePlayer>();
            spectators = new Dictionary<BasePlayer, string>();
            kitAttire = new List<string>();
            kitWeapons = new List<string>();
            kitAmmo = new List<string>();
            kitMeds = new Dictionary<string, int>();
            // Allow choosing of how many of each med to give
            this.rust = rust;
            // TODO: Allow changing kits
            kitAttire.Add("metal.facemask");
            kitAttire.Add("metal.plate.torso");
            kitAttire.Add("roadsign.kilt");
            kitAttire.Add("hoodie");
            kitAttire.Add("shoes.boots");
            kitAttire.Add("pants");
            kitAttire.Add("tactical.gloves");
            kitWeapons.Add("rifle.ak");
            kitAmmo.Add("ammo.rifle");
            kitMeds["syringe.medical"] = 12;
            kitMeds["bandage"] = 12;
            isStarted = false;
        }
        public void StartRound() {
            isStarted = true;
            foreach (BasePlayer p in aTeamPlayers.Concat(bTeamPlayers).ToList()) {
                HealAndGiveKit(p);
            }
            // Allow movement/placing walls/damage/etc.}
            public void EndRound() {
                string winner = "";
                if (aTeamPlayers.Count == 0) {
                    winner = "B";
                }
                else if (bTeamPlayers.Count == 0) {
                    winner = "A";
                }
                foreach (BasePlayer p in aTeamPlayers.Concat(bTeamPlayers.Concat(spectators.Keys)).ToList()) {
                    rust.SendChatMessage(p, "", "Team " + winner + " won the round!");
                }
                foreach (BasePlayer s in spectators.Keys.ToList()) {
                    string side = spectators[s];
                    // Keeping spectators.remove and teleport inside ifs so that people that aren't on a team stay as spectators
                    if (side.Equals("a")) {
                        aTeamPlayers.Add(s);
                        spectators.Remove(s);
                    }
                    else if (side.Equals("b")) {
                        bTeamPlayers.Add(s);
                        spectators.Remove(s);
                    }
                }
                foreach (BasePlayer p in aTeamPlayers) {
                    HealAndGiveKit(p);
                    p.Teleport(GetSpawn("a"));
                }
                foreach (BasePlayer p in bTeamPlayers) {
                    HealAndGiveKit(p);
                    p.Teleport(GetSpawn("b"));
                }
                isStarted = false;
                // Destroy placed walls, stop movement out of spawn, stop allowing placing of walls, stop damage, etc.}
                void HealAndGiveKit(BasePlayer p) {
                    p.inventory.Strip();
                    p.StopWounded();
                    p.metabolism.bleeding.value = 0;
                    p.metabolism.SendChangesToClient();
                    p.Heal(100);
                    GiveKit(p, kitAttire, kitWeapons, kitAmmo, kitMeds);
                }
#region Events
                public void OnPlayerKilled(BasePlayer victim, HitInfo info, Oxide.Game.Rust.Libraries.Rust rust) {
                    // Send kill message
                    BasePlayer killer = info.InitiatorPlayer;
                    string killerTeam = null;
                    if (aTeamPlayers.Contains(killer)) {
                        killerTeam = "a";
                    }
                    else if (bTeamPlayers.Contains(killer)) {
                        killerTeam = "b";
                    }
                    string victimTeam = null;
                    if (aTeamPlayers.Contains(victim)) {
                        victimTeam = "a";
                    }
                    else if (bTeamPlayers.Contains(victim)) {
                        victimTeam = "b";
                    }
                    string weaponName;
                    int distance;
                    try {
                        weaponName = info.Weapon.LookupPrefab().name;
                        distance = (int)info.ProjectileDistance;
                    }
                    catch {
                        weaponName = "suicide";
                        distance = 0;
                    }
                    // Get kill message with colors relative to team A
                    string killMessage = GetKillMessage("a", killerTeam, victimTeam, killer.displayName, victim.displayName, weaponName, distance);
                    foreach (BasePlayer gamePlayer in aTeamPlayers) {
                        rust.SendChatMessage(gamePlayer, "", killMessage, killer.UserIDString);
                    }
                    // Get kill message with colors relative to team B
                    killMessage = GetKillMessage("b", killerTeam, victimTeam, killer.displayName, victim.displayName, weaponName, distance);
                    foreach (BasePlayer gamePlayer in bTeamPlayers) {
                        rust.SendChatMessage(gamePlayer, "", killMessage, killer.UserIDString);
                    }
                    // Get kill message with colors relative to spectators
                    killMessage = GetKillMessageSpectator(killer.displayName, victim.displayName, weaponName, distance);
                    foreach (BasePlayer spectator in spectators.Keys) {
                        rust.SendChatMessage(spectator, "", killMessage, killer.UserIDString);
                    }
                    victim.StopWounded();
                    victim.metabolism.bleeding.value = 0;
                    victim.metabolism.SendChangesToClient();
                    victim.Heal(100);
                    // Add victim to spectators
                    if (victimTeam.Equals("a")) {
                        aTeamPlayers.Remove(victim);
                        spectators.Add(victim, "a");
                    }
                    else if (victimTeam.Equals("b")) {
                        bTeamPlayers.Remove(victim);
                        spectators.Add(victim, "b");
                    }
                    // Teleport victim to spectator area
                    victim.Teleport(GetSpecSpawn());
                    // If the game is finished
                    if (aTeamPlayers.Count == 0 || bTeamPlayers.Count == 0) {
                        EndRound();
                    }
                }
                public void OnPlayerJoinTeam(BasePlayer player, string side) {
                    player.metabolism.bleeding.value = 0;
                    player.metabolism.SendChangesToClient();
                    player.Heal(100);
                    // Check if they just want to join spectators and not A/B
                    if (side.Equals("s")) {
                        aTeamPlayers.Remove(player);
                        bTeamPlayers.Remove(player);
                        spectators[player] = "s";
                        player.Teleport(GetSpecSpawn());
                        return;
                    }
                    // If the game isn't started, add player to team, else put them in spectators with the side they want to join saved for next round
                    if (!isStarted) {
                        if (side.Equals("a")) {
                            aTeamPlayers.Add(player);
                            bTeamPlayers.Remove(player);
                        }
                        else if (side.Equals("b")) {
                            bTeamPlayers.Add(player);
                            aTeamPlayers.Remove(player);
                        }
                        else HealAndGiveKit(player);
                        player.Teleport(GetSpawn(side));
                    }
                    else {
                        spectators.Add(player, side);
                        player.Teleport(GetSpecSpawn());
                    }
                    string message = "<color=#02f0e8>" + player.displayName + "</color> has joined team " + side.ToUpper();
                    foreach (BasePlayer p in aTeamPlayers) {
                        rust.SendChatMessage(p, "", message);
                    }
                    foreach (BasePlayer p in bTeamPlayers) {
                        rust.SendChatMessage(p, "", message);
                    }
                    foreach (BasePlayer p in spectators.Keys) {
                        rust.SendChatMessage(p, "", message);
                    }
                }
                // TODO: If a player leaves, the game won't end, so you should make it as if they died
                public void OnPlayerLeave(BasePlayer leftPlayer) {
                    aTeamPlayers.Remove(leftPlayer);
                    bTeamPlayers.Remove(leftPlayer);
                    spectators.Remove(leftPlayer);
                    // Check if they are connected, since this is called when players leave the server too
                    if (leftPlayer.IsConnected) {
                        leftPlayer.metabolism.calories.value = 500;
                        leftPlayer.metabolism.hydration.value = 250;
                        leftPlayer.metabolism.SendChangesToClient();
                        leftPlayer.inventory.Strip();
                        leftPlayer.Heal(100);
                        leftPlayer.EnsureDismounted();
                        if (leftPlayer.HasParent()) {
                            leftPlayer.SetParent(null, true, true);
                        }
                        leftPlayer.EndLooting();
                        leftPlayer.StartSleeping();
                        leftPlayer.RemoveFromTriggers();
                        leftPlayer.Teleport(Util.worldSpawn);
                    }
                    if (leader.Equals(leftPlayer)) {
                        List<BasePlayer> allPlayers = aTeamPlayers.Concat(bTeamPlayers).ToList();
                        if (allPlayers.Count > 0) {
                            int index = new System.Random().Next(allPlayers.Count);
                            leader = allPlayers[index];
                            OnLeaderUpdate(leader);
                        }
                    }
                    if (aTeamPlayers.Count == 0 || bTeamPlayers.Count == 0) {
                        EndRound();
                    }
                }
                public void OnLeaderUpdate(BasePlayer newLeader) {
                    leader = newLeader;
                    List<BasePlayer> allPlayers = aTeamPlayers.Concat(bTeamPlayers).Concat(spectators.Keys).ToList();
                    foreach (BasePlayer p in allPlayers) {
                        rust.SendChatMessage(p, "", "<color=#02f0e8>" + p.displayName + "</color> has been made leader.");
                    }
                }
#endregion
#region Utils
                private string GetKillMessageSpectator(string killerName, string victimName, string weaponName, int distance) {
                    // #f09902 is orange
                    return "<color=#f09902>" + killerName + "</color>" + " -> <color=#f09902>" + victimName + "</color> (" + weaponName + ") | " + distance + "m";
                }
                private string GetKillMessage(string receiverTeam, string killerTeam, string victimTeam, string killerName, string victimName, string weaponName, int distance) {
                    string red = "#f02702";
                    string blue = "#0281f0";
                    string killerColor = red;
                    string victimColor = red;
                    if (receiverTeam.Equals(killerTeam)) {
                        killerColor = blue;
                    }
                    if (receiverTeam.Equals(victimTeam)) {
                        victimColor = blue;
                    }
                    return "<color=" + killerColor + ">" + killerName + "</color>" + " -> <color=" + victimColor + ">" + victimName + "</color> (" + weaponName + ") | " + distance + "m";
                }
                void GiveKit(BasePlayer player, List<string> attire, List<string> weapons, List<string> ammo, Dictionary<string, int> meds) {
                    player.inventory.Strip();
                    foreach (string a in attire) {
                        player.inventory.containerWear.AddItem(ItemManager.FindItemDefinition(a), 1);
                    }
                    foreach (string w in weapons) {
                        Item weaponItem = ItemManager.CreateByName(w);
                        var heldEnt = weaponItem.GetHeldEntity() as BaseProjectile;
                        if (heldEnt != null) {
                            heldEnt.primaryMagazine.contents = heldEnt.primaryMagazine.capacity;
                        }
                        player.inventory.GiveItem(weaponItem);
                    }
                    foreach (string a in ammo) {
                        player.inventory.GiveItem(ItemManager.CreateByName(a, 1000));
                    }
                    foreach (string m in meds.Keys) {
                        player.inventory.GiveItem(ItemManager.CreateByName(m, meds[m]));
                    }
                }
                public Vector3 GetSpawn(string side) {
                    float x = float.Parse(Util.flatConfig[flatID.ToString(), side + "SpawnX"].ToString());
                    float y = float.Parse(Util.flatConfig[flatID.ToString(), side + "SpawnY"].ToString());
                    float z = float.Parse(Util.flatConfig[flatID.ToString(), side + "SpawnZ"].ToString());
                    return new Vector3(x, y, z);
                }
                public Vector3 GetSpecSpawn() {
                    float x = float.Parse(Util.flatConfig[flatID.ToString(), "spectatorSpawnX"].ToString());
                    float y = float.Parse(Util.flatConfig[flatID.ToString(), "spectatorSpawnY"].ToString());
                    float z = float.Parse(Util.flatConfig[flatID.ToString(), "spectatorSpawnZ"].ToString());
                    return new Vector3(x, y, z);
                }
#endregion
            }
            public class Util {
                public static Vector3 worldSpawn = new Vector3(-185f, 8f, -344f);
                public static DynamicConfigFile flatConfig = Interface.Oxide.DataFileSystem.GetDatafile("FlatConfig");
                public static void initFlatConfig() {
                    flatConfig["0", "aSpawnX"] = 0;
                    flatConfig["0", "aSpawnY"] = 5.2;
                    flatConfig["0", "aSpawnZ"] = -70;
                    flatConfig["0", "bSpawnX"] = 0;
                    flatConfig["0", "bSpawnY"] = 5.2;
                    flatConfig["0", "bSpawnZ"] = 70;
                    flatConfig["0", "spectatorSpawnX"] = 0;
                    flatConfig["0", "spectatorSpawnY"] = 5.2;
                    flatConfig["0", "spectatorSpawnZ"] = 0;
                    flatConfig.Save();
                }
            }
        }

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок
Сверху