C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using Facepunch;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Plugins;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using System.Collections;
using Oxide.Game.Rust.Cui;
using Newtonsoft.Json.Linq;
using Rust;
using static Steamworks.InventoryItem;
/*
* Create new arenas.* Spectator mode.* Make it so servers can disable item prizes.* Add scoreboard for wipe and all time.*/
/* 1.0.9
* Fixed the death mechanic when a player jumps off the edge of the arena.It will not strip the body and force the player to die.* Changed the player death to drop a container instead of a corpse.* Fixed a bug where some DroppedItemContainers would drop to the floor after an event.* Added support for EventHelpers team management system.* Added support for EventHelper join messages.* Added option to allow players to loot while out of the circle.* Fixed an issue with the prizes being deducted per roll, rather than per command run.* Added support to prevent CustomLoot from overwriting the container contents.* Fixed a death-loop bug that would kill the player over and over again.* Fixed an issue where players could not use commands after leaving the event (requires EventHelper v1.0.11+)
* Added support for NTeleportation.Players who teleport to a player who is in the arena, will be teleported back to their old position immediately.*/
namespace Oxide.Plugins {
[Info("Survival Arena", "imthenewguy", "1.0.9")]
[Description("Spawns a battle royal arena in the sky")]
class SurvivalArena : RustPlugin {
#region Config
private Configuration config;
public class Configuration {
[JsonProperty("Game settings")]
public GameSettings gameSettings = new GameSettings();
[JsonProperty("Event Helper settings")]
public EventHelperSettings eventHelperSettings = new EventHelperSettings();
[JsonProperty("Sound settings")]
public SoundEffects soundsSettings = new SoundEffects();
[JsonProperty("Radiation zone settings")]
public SphereInfo radiationZoneSettings = new SphereInfo();
[JsonProperty("Bush prefabs")]
public Dictionary<BiomeType, List<string>> biome_bushes = new Dictionary<BiomeType, List<string>>();
[JsonProperty("Tree prefabs")]
public Dictionary<BiomeType, List<string>> biome_trees = new Dictionary<BiomeType, List<string>>();
[JsonProperty("Dead log prefabs")]
public Dictionary<BiomeType, List<string>> biome_logs = new Dictionary<BiomeType, List<string>>();
[JsonProperty("Prize settings")]
public Rewards prize_settings = new Rewards();
[JsonProperty("Command settings")]
public CommandInfo command_settings = new CommandInfo();
[JsonProperty("Loot settings")]
public Dictionary<string, LootSettings> lootSettings = new Dictionary<string, LootSettings>(StringComparer.OrdinalIgnoreCase);
[JsonProperty("How many delete/spawn actions should we do per game tick when building/removing the arena?")]
public int max_procs_per_tick = 50;
[JsonProperty("Anchor settings")]
public Anchors anchors = new Anchors();
[JsonProperty("Notifications settings")]
public NotificationsInfo notifications = new NotificationsInfo();
public string ToJson() => JsonConvert.SerializeObject(this);
public Dictionary<string, object> ToDictionary() => JsonConvert.DeserializeObject<Dictionary<string, object>>(ToJson());
}
protected override void LoadDefaultConfig() {
config = new Configuration();
config.biome_trees = DefaultBiomeTrees;
config.biome_bushes = DefaultBiomeBushes;
config.biome_logs = DefaultBiomeLogs;
config.lootSettings = DefaultLootSettings;
config.prize_settings.prizes = DefaultPrizes;
}
public class CommandInfo {
[JsonProperty("Command to join an active lobby")]
public string join_command = "survival";
[JsonProperty("Command to leave an active lobby")]
public string leave_command = "saleave";
}
public class SphereInfo {
[JsonProperty("How many spheres should we overlap to make it darker [higher number = darker]?")]
public int darkness = 8;
[JsonProperty("How many stacks of radiation should players accumulate for each second spent outside of the sphere?")]
public int rads_per_second = 3;
[JsonProperty("How many points of radiation should the player accumulate per second while outside of the dome?")]
public int rad_increase_per_tick = 3;
[JsonProperty("Radiation check interval (seconds)")]
public int check_interval = 1;
[JsonProperty("Final circle size")]
public int min_ring_size = 20;
[JsonProperty("Seconds after game start before the circle spawns")]
public int circle_delay = 60;
[JsonProperty("Radiation panel colour [Red Green Blue Alpha][1.0 = full colour]")]
public string panel_colour = "0.5 0 0 0.90";
}
public class Rewards {
[JsonProperty("How many prizes should the player receive per claim?")]
public int rolls_per_claim = 1;
[JsonProperty("Prizes")]
public List<PrizeInfo> prizes = new List<PrizeInfo>();
[JsonProperty("Economic dollars for winning a match [requires: Economics]")]
public CurrencyReward economic_reward = new CurrencyReward(0, 0);
[JsonProperty("Server reward points for winning a match [requires: ServerRewards]")]
public CurrencyReward srp_reward = new CurrencyReward(0, 0);
[JsonProperty("Skill Tree XP given to the player when they win the event [Requires: SkillTree]")]
public double SkillTree_XP_Reward = 1000;
[JsonProperty("Automatically award the player with their prize (false means the player must type the /sprize command to redeem their prize)")]
public bool auto_award = false;
public class CurrencyReward {
public int min_amount;
public int max_amount;
public CurrencyReward(int min_amount, int max_amount) {
this.min_amount = min_amount;
this.max_amount = max_amount;
}
}
}
public class PrizeInfo {
public string shortname;
public int min_quantity;
public int max_quantity;
public ulong skin;
public string displayName;
public int dropWeight;
public PrizeInfo(string shortname, int min_quantity, int max_quantity, int dropWeight = 100, ulong skin = 0, string displayName = null) {
this.shortname = shortname;
this.min_quantity = min_quantity;
this.max_quantity = max_quantity;
this.skin = skin;
this.displayName = displayName;
this.dropWeight = dropWeight;
}
}
public class Anchors {
[JsonProperty("Player counter anchor [Key: Left/Right, Value: Up/Down]")]
public KeyValuePair<float, float> player_count_anchor_adjustment = new KeyValuePair<float, float>(-40f, 7f);
}
public class SoundEffects {
[JsonProperty("Sound effect when the game is about to start")]
public string sound_for_starting = "assets/prefabs/missions/effects/mission_victory.prefab";
[JsonProperty("Sound effect for killing another player")]
public string sound_for_killing = "assets/prefabs/missions/effects/mission_accept.prefab";
[JsonProperty("Sound effect when a player dies (players to all participants)")]
public string sound_for_death = "assets/prefabs/npc/m2bradley/effects/maincannonattack.prefab";
[JsonProperty("Sound when a player redeems a prize")]
public string sound_for_prize = "assets/prefabs/misc/easter/painted eggs/effects/gold_open.prefab";
}
public class EventHelperSettings {
[JsonProperty("Return the players items back immediately after respawn? (setting false requries the player to use a command to get their items back)")]
public bool give_items_back_on_death = true;
[JsonProperty("Use EventHelper to schedule the events (recommended)?")]
public bool use_event_helper_timer = true;
[JsonProperty("Commands to prevent when a player are at the event")]
public string[] prevent_commands = {
"kit", "backpack", "backpack.open"
}
;
[JsonProperty("Allow players to stay in a team when they join the event? [set to true if using any sort of clans or team management plugin]")]
public bool allow_teams = true;
}
public class GameSettings {
[JsonProperty("Minimum players required for the event to proceed")]
public int min_player = 2;
[JsonProperty("Send a message to the contestants when a player dies?")]
public bool message_on_death = true;
[JsonProperty("Minimum respawn time for crates")]
public float min_crate_respawn_time = 30f;
[JsonProperty("Maximum respawn time for crates")]
public float max_crate_respawn_time = 90f;
[JsonProperty("Attempt to clear old arenas when the plugin loads?")]
public bool clear_arena_on_server_start = true;
[JsonProperty("Default lobby time")]
public int defaultStartTime = 300;
[JsonProperty("Commands to run for each player when the game starts and the gates open.Use {id} in replacement of the players steam id")]
public List<string> commands_on_start = new List<string>();
[JsonProperty("Use the NightVision plugin?")]
public bool use_nightvision = true;
[JsonProperty("Allow players to loot while they are outside of the circle (in the radiation zone)?")]
public bool allow_looting_in_rad_zone = false;
[JsonProperty("Settings to help prevent non-participants from getting to the arena")]
public InterferenceSettings interference_settings = new InterferenceSettings();
}
public class InterferenceSettings {
[JsonProperty("Constantly check to see if non-participants are near the arena? [They will be warned then killed if found]")]
public bool check_for_outsiders = true;
[JsonProperty("How often should we check [seconds]")]
public float check_time = 1;
[JsonProperty("How close can the player get to the arena before they are warned")]
public float dist_from_edge_restriction = 50f;
[JsonProperty("How many seconds does the player have to leave the arena before they are killed?")]
public float seconds_to_vacate = 10;
[JsonProperty("Exclude players witht he IsAdmin flag from our checks?")]
public bool ignore_admins = true;
}
public class NotificationsInfo {
[JsonProperty("Notify plugin settings")]
public NotifyInfo sendNotify = new NotifyInfo();
[JsonProperty("GUIAnnouncements plugin settings")]
public GUIAnnouncementsInfo GUIAnnouncements = new GUIAnnouncementsInfo();
}
public class NotifyInfo {
[JsonProperty("Send notifications using the Notify plugin?")]
public bool enabled = true;
[JsonProperty("Notify profile/type")]
public int notifyType = 0;
}
public class GUIAnnouncementsInfo {
[JsonProperty("Send announcements using the GUIAnnouncements plugin?")]
public bool enabled = true;
[JsonProperty("Banner colour - see GUIAnnouncements for colours")]
public string banner_colour = "Purple";
[JsonProperty("Text colour - see GUIAnnouncements for colours")]
public string text_colour = "Yellow";
[JsonProperty("Position adjustment")]
public float position_adjustment = 0;
}
public class LootSettings {
[JsonProperty("Chance for this profile to be selected for the game (weighted system)")]
public int profileWeight = 100;
public int min_items;
public int max_items;
public List<LootInfo> items = new List<LootInfo>();
public LootSettings(int min_items, int max_items, List<LootInfo> items, int profileWeight = 100) {
this.min_items = min_items;
this.max_items = max_items;
this.items = items;
this.profileWeight = profileWeight;
}
}
public class LootInfo {
public string shortname;
public int min_amount;
public int max_amount;
public ulong skin;
public string displayName;
public LootInfo(string shortname, int min_amount, int max_amount, ulong skin = 0, string displayName = null) {
this.shortname = shortname;
this.min_amount = min_amount;
this.max_amount = max_amount;
this.skin = skin;
this.displayName = displayName;
}
}
protected override void LoadConfig() {
base.LoadConfig();
try {
config = Config.ReadObject<Configuration>();
if (config == null) {
throw new JsonException();
}
if (!config.ToDictionary().Keys.SequenceEqual(Config.ToDictionary(x => x.Key, x => x.Value).Keys)) {
PrintToConsole("Configuration appears to be outdated; updating and saving");
SaveConfig();
}
}
catch {
PrintToConsole($"Configuration file {Name}.json is invalid; using defaults");
LoadDefaultConfig();
}
SaveConfig();
}
protected override void SaveConfig() {
PrintToConsole($"Configuration changes saved to {Name}.json");
Config.WriteObject(config, true);
}
#endregion
#region Defalt config
Dictionary<BiomeType, List<string>> DefaultBiomeTrees {
get {
return new Dictionary<BiomeType, List<string>>() {
[BiomeType.Arid]
= new List<string>() {
"assets/bundled/prefabs/autospawn/resource/v3_arid_forest/palm_tree_tall_a_entity.prefab", "assets/bundled/prefabs/autospawn/resource/v3_arid_forest/palm_tree_tall_b_entity.prefab", "assets/bundled/prefabs/autospawn/resource/v3_arid_beachside/palm_tree_short_a_entity.prefab", "assets/bundled/prefabs/autospawn/resource/v3_arid_beachside/palm_tree_short_b_entity.prefab", "assets/bundled/prefabs/autospawn/resource/v3_arid_beachside/palm_tree_short_c_entity.prefab"
}
, [BiomeType.Temperate] = new List<string>() {
"assets/bundled/prefabs/autospawn/resource/v3_temp_forest_pine/pine_a.prefab", "assets/bundled/prefabs/autospawn/resource/v3_temp_forest_pine/pine_c.prefab", "assets/bundled/prefabs/autospawn/resource/v3_temp_field_large/oak_b.prefab", "assets/bundled/prefabs/autospawn/resource/v3_temp_field_large/oak_c.prefab", "assets/bundled/prefabs/autospawn/resource/v3_temp_field_large/oak_d.prefab", "assets/bundled/prefabs/autospawn/resource/v3_temp_forest_pine/birch_big_temp.prefab"
}
, [BiomeType.Tundra] = new List<string>() {
"assets/bundled/prefabs/autospawn/resource/v3_tundra_field_pines/pine_a.prefab", "assets/bundled/prefabs/autospawn/resource/v3_tundra_field_pines/pine_b.prefab", "assets/bundled/prefabs/autospawn/resource/v3_tundra_field_pines/pine_d.prefab", "assets/bundled/prefabs/autospawn/resource/v3_tundra_forest/pine_a.prefab", "assets/bundled/prefabs/autospawn/resource/v3_tundra_forest/pine_c.prefab", "assets/bundled/prefabs/autospawn/resource/v3_tundra_forest/pine_dead_a.prefab", "assets/bundled/prefabs/autospawn/resource/v3_tundra_forest/pine_dead_b.prefab"
}
, [BiomeType.Arctic] = new List<string>() {
"assets/bundled/prefabs/autospawn/resource/v3_arctic_forest/pine_a_snow.prefab", "assets/bundled/prefabs/autospawn/resource/v3_arctic_forest/pine_c_snow.prefab", "assets/bundled/prefabs/autospawn/resource/v3_arctic_forest/pine_dead_snow_b.prefab", "assets/bundled/prefabs/autospawn/resource/v3_arctic_forest/pine_dead_snow_c.prefab", "assets/bundled/prefabs/autospawn/resource/v3_arctic_forestside/pine_a_snow.prefab", "assets/bundled/prefabs/autospawn/resource/v3_arctic_forestside/pine_b snow.prefab", "assets/bundled/prefabs/autospawn/resource/v3_arctic_forestside/pine_d_snow.prefab", "assets/bundled/prefabs/autospawn/resource/v3_arctic_forestside/pine_dead_snow_e.prefab",
}
}
;
}
}
Dictionary<BiomeType, List<string>> DefaultBiomeBushes {
get {
return new Dictionary<BiomeType, List<string>>() {
[BiomeType.Arid]
= new List<string>() {
"assets/bundled/prefabs/autospawn/resource/v3_bushes_arid_desert/creosote_bush_c.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_arid_desert/creosote_bush_d.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_arid_desert/mormon_tea_a.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_arid_desert/mormon_tea_b.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_arid_desert/mormon_tea_c.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_arid_desert/mormon_tea_d.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_arid_dry/creosote_bush_dry_a.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_arid_dry/creosote_bush_dry_b.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_arid_grass/creosote_bush_a.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_arid_grass/creosote_bush_b.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_arid_grass/creosote_bush_c.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_arid_grass/creosote_bush_d.prefab", "assets/bundled/prefabs/autospawn/resource/v3_arid_cactus/cactus-1.prefab", "assets/bundled/prefabs/autospawn/resource/v3_arid_cactus/cactus-2.prefab", "assets/bundled/prefabs/autospawn/resource/v3_arid_cactus/cactus-3.prefab", "assets/bundled/prefabs/autospawn/resource/v3_arid_cactus/cactus-4.prefab", "assets/bundled/prefabs/autospawn/resource/v3_arid_cactus/cactus-5.prefab", "assets/bundled/prefabs/autospawn/resource/v3_arid_cactus/cactus-6.prefab", "assets/bundled/prefabs/autospawn/resource/v3_arid_cactus/cactus-7.prefab"
}
, [BiomeType.Temperate] = new List<string>() {
"assets/bundled/prefabs/autospawn/resource/v3_bushes_temp/bush_spicebush_a.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_temp/bush_spicebush_b.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_temp/bush_spicebush_c.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_temp/bush_spicebush_d.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_temp/bush_willow_a.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_temp/bush_willow_b.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_temp/bush_willow_c.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_temp/bush_willow_d.prefab"
}
, [BiomeType.Tundra] = new List<string>() {
"assets/bundled/prefabs/autospawn/resource/v3_bushes_tundra/bush_spicebush_a.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_tundra/bush_spicebush_b.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_tundra/bush_spicebush_c.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_tundra/bush_spicebush_d.prefab"
}
, [BiomeType.Arctic] = new List<string>() {
"assets/bundled/prefabs/autospawn/resource/v3_bushes_arctic/bush_willow_snow_a.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_arctic/bush_willow_snow_b.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_arctic/bush_willow_snow_c.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_arctic/bush_willow_snow_d.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_arctic/bush_willow_snow_small_a.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_arctic_forest/bush_spicebush_a_snow.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_arctic_forest/bush_spicebush_c_snow.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_arctic_forest/bush_willow_snow_a.prefab", "assets/bundled/prefabs/autospawn/resource/v3_bushes_arctic_forest/bush_willow_snow_b.prefab"
}
}
;
}
}
Dictionary<BiomeType, List<string>> DefaultBiomeLogs {
get {
return new Dictionary<BiomeType, List<string>>() {
[BiomeType.Arid]
= new List<string>() {
"assets/bundled/prefabs/autospawn/resource/logs_dry/dead_log_a.prefab", "assets/bundled/prefabs/autospawn/resource/logs_dry/dead_log_b.prefab", "assets/bundled/prefabs/autospawn/resource/logs_dry/dead_log_c.prefab"
}
, [BiomeType.Temperate] = new List<string>() {
"assets/bundled/prefabs/autospawn/resource/logs_dry/dead_log_a.prefab", "assets/bundled/prefabs/autospawn/resource/logs_dry/dead_log_b.prefab", "assets/bundled/prefabs/autospawn/resource/logs_dry/dead_log_c.prefab"
}
, [BiomeType.Tundra] = new List<string>() {
"assets/bundled/prefabs/autospawn/resource/logs_dry/dead_log_a.prefab", "assets/bundled/prefabs/autospawn/resource/logs_dry/dead_log_b.prefab", "assets/bundled/prefabs/autospawn/resource/logs_dry/dead_log_c.prefab"
}
, [BiomeType.Arctic] = new List<string>() {
"assets/bundled/prefabs/autospawn/resource/logs_snow/dead_log_b.prefab", "assets/bundled/prefabs/autospawn/resource/logs_snow/dead_log_c.prefab", "assets/bundled/prefabs/autospawn/resource/logs_snow/dead_log_a.prefab"
}
}
;
}
}
Dictionary<string, LootSettings> DefaultLootSettings {
get {
return new Dictionary<string, LootSettings>() {
["PrimitiveLoot"]
= new LootSettings(2, 4, new List<LootInfo>() {
new LootInfo("attire.hide.pants", 1, 1), new LootInfo("attire.hide.poncho", 1, 1), new LootInfo("attire.hide.skirt", 1, 1), new LootInfo("attire.hide.vest", 1, 1), new LootInfo("attire.hide.helterneck", 1, 1), new LootInfo("attire.hide.boots", 1, 1), new LootInfo("grenade.beancan", 1, 1), new LootInfo("hat.wolf", 1, 1), new LootInfo("spear.stone", 1, 1), new LootInfo("spear.wooden", 1, 1), new LootInfo("arrow.bone", 10, 20), new LootInfo("arrow.fire", 3, 6), new LootInfo("arrow.hv", 5, 12), new LootInfo("arrow.wooden", 5, 20), new LootInfo("longsword", 1, 1), new LootInfo("salvaged.sword", 1, 1), new LootInfo("machete", 1, 1), new LootInfo("bow.compound", 1, 1), new LootInfo("crossbow", 1, 1), new LootInfo("bow.hunting", 1, 1), new LootInfo("grenade.f1", 1, 3), new LootInfo("pistol.revolver", 1, 1), new LootInfo("ammo.pistol", 5, 15), new LootInfo("pistol.nailgun", 1, 1), new LootInfo("bandage", 1, 6), new LootInfo("syringe.medical", 1, 2), new LootInfo("bone.armor.suit", 1, 1), new LootInfo("bone.club", 1, 1), new LootInfo("deer.skull.mask", 1, 1), new LootInfo("knife.bone", 1, 1), new LootInfo("wood.armor.helmet", 1, 1), new LootInfo("wood.armor.pants", 1, 1), new LootInfo("wood.armor.jacket", 1, 1), new LootInfo("hat.boonie", 1, 1), new LootInfo("bucket.helmet", 1, 1), new LootInfo("riot.helmet", 1, 1), new LootInfo("burlap.gloves.new", 1, 1), new LootInfo("burlap.headwrap", 1, 1), new LootInfo("burlap.shirt", 1, 1), new LootInfo("burlap.shoes", 1, 1), new LootInfo("burlap.trousers", 1, 1), new LootInfo("knife.butcher", 1, 1), new LootInfo("knife.combat", 1, 1), new LootInfo("shotgun.waterpipe", 1, 1), new LootInfo("ammo.handmade.shell", 1, 5), new LootInfo("stonehatchet", 1, 1), new LootInfo("mace", 1, 1), new LootInfo("salvaged.cleaver", 1, 1), new LootInfo("rock", 1, 1), new LootInfo("sickle", 1, 1),
}
), ["GunLoot"] = new LootSettings(2, 4, new List<LootInfo>() {
new LootInfo("weapon.mod.8x.scope", 1, 1), new LootInfo("weapon.mod.small.scope", 1, 1), new LootInfo("crossbow", 1, 1), new LootInfo("weapon.mod.holosight", 1, 1), new LootInfo("longsword", 1, 1), new LootInfo("machete", 1, 1), new LootInfo("weapon.mod.muzzleboost", 1, 1), new LootInfo("weapon.mod.muzzlebrake", 1, 1), new LootInfo("salvaged.cleaver", 1, 1), new LootInfo("weapon.mod.silencer", 1, 1), new LootInfo("weapon.mod.simplesight", 1, 1), new LootInfo("tactical.gloves", 1, 1), new LootInfo("weapon.mod.lasersight", 1, 1), new LootInfo("ammo.shotgun", 5, 10), new LootInfo("ammo.shotgun.fire", 5, 10), new LootInfo("ammo.shotgun.slug", 2, 7), new LootInfo("ammo.grenadelauncher.he", 2, 5), new LootInfo("ammo.rifle", 20, 40), new LootInfo("ammo.rifle.explosive", 5, 10), new LootInfo("ammo.handmade.shell", 10, 20), new LootInfo("ammo.rocket.hv", 1, 2), new LootInfo("ammo.rifle.hv", 5, 10), new LootInfo("ammo.pistol.fire", 5, 10), new LootInfo("ammo.nailgun.nails", 20, 40), new LootInfo("ammo.pistol", 20, 40), new LootInfo("ammo.pistol.hv", 10, 20), new LootInfo("ammo.rifle.incendiary", 10, 15), new LootInfo("rifle.ak", 1, 1), new LootInfo("rifle.bolt", 1, 1), new LootInfo("rifle.l96", 1, 1), new LootInfo("rifle.lr300", 1, 1), new LootInfo("rifle.m39", 1, 1), new LootInfo("rifle.semiauto", 1, 1), new LootInfo("pistol.eoka", 1, 1), new LootInfo("pistol.m92", 1, 1), new LootInfo("pistol.nailgun", 1, 1), new LootInfo("pistol.python", 1, 1), new LootInfo("pistol.revolver", 1, 1), new LootInfo("pistol.semiauto", 1, 1), new LootInfo("arrow.bone", 10, 40), new LootInfo("arrow.fire", 5, 10), new LootInfo("arrow.hv", 10, 40), new LootInfo("arrow.wooden", 20, 60), new LootInfo("jumpsuit.suit.blue", 1, 1), new LootInfo("bone.armor.suit", 1, 1), new LootInfo("hazmatsuit", 1, 1), new LootInfo("hazmatsuit.nomadsuit", 1, 1), new LootInfo("hazmatsuit.spacesuit", 1, 1), new LootInfo("roadsign.jacket", 1, 1), new LootInfo("roadsign.kilt", 1, 1), new LootInfo("wood.armor.helmet", 1, 1), new LootInfo("wood.armor.pants", 1, 1), new LootInfo("wood.armor.jacket", 1, 1), new LootInfo("deer.skull.mask", 1, 1), new LootInfo("bucket.helmet", 1, 1), new LootInfo("coffeecan.helmet", 1, 1), new LootInfo("heavy.plate.helmet", 1, 1), new LootInfo("riot.helmet", 1, 1), new LootInfo("shotgun.double", 1, 1), new LootInfo("shotgun.pump", 1, 1), new LootInfo("shotgun.spas12", 1, 1), new LootInfo("shotgun.waterpipe", 1, 1), new LootInfo("smg.2", 1, 1), new LootInfo("smg.mp5", 1, 1), new LootInfo("smg.thompson", 1, 1), new LootInfo("grenade.f1", 2, 5), new LootInfo("multiplegrenadelauncher", 1, 1), new LootInfo("grenade.smoke", 1, 2), new LootInfo("grenade.beancan", 1, 1), new LootInfo("rocket.launcher", 1, 1), new LootInfo("jacket", 1, 1), new LootInfo("burlap.gloves.new", 1, 1), new LootInfo("burlap.gloves", 1, 1), new LootInfo("roadsign.gloves", 1, 1), new LootInfo("shoes.boots", 1, 1), new LootInfo("boots.frog", 1, 1), new LootInfo("attire.hide.boots", 1, 1), new LootInfo("attire.hide.pants", 1, 1), new LootInfo("attire.hide.poncho", 1, 1), new LootInfo("attire.hide.skirt", 1, 1), new LootInfo("attire.hide.vest", 1, 1), new LootInfo("pants", 1, 1), new LootInfo("pants.shorts", 1, 1), new LootInfo("hoodie", 1, 1), new LootInfo("syringe.medical", 1, 3), new LootInfo("bandage", 3, 6), new LootInfo("largemedkit", 1, 2), new LootInfo("metal.plate.torso", 1, 1), new LootInfo("metal.facemask", 1, 1)
}
)
}
;
}
}
List<PrizeInfo> DefaultPrizes {
get {
return new List<PrizeInfo>() {
new PrizeInfo("scrap", 300, 600)
}
;
}
}
#endregion
#region Localization
protected override void LoadDefaultMessages() {
lang.RegisterMessages(new Dictionary<string, string> {
["NoPerms"]
= "You do not have permission to use this command.", ["EventRunning"] = "The event is already running.", ["SurvivalArenaStartingBeginIn"] = "Game will start in <color=#ffb600>{0}</color> seconds.Type <color=#00ff00>/{1}</color> to join.", ["Cancelled"] = "Survival Arena has been cancelled due to lack of players.", ["DoorsOpeningSoon"] = "Doors opening in <color=#ffb600>5</color> seconds.", ["Prefix"] = "[<color=#ffae00>SurvivalArena</color>] ", ["CircleClosingStarted"] = "<color=#0094c8>The circle has started to close!</color>", ["CircleClosingFinished"] = "<color=#0094c8>The final circle has been formed!</color>", ["AnnounceWinner"] = "{0} has won the event!", ["MessageWinner"] = "Type <color=#23f207>/sprize</color> to claim your prize.Prizes remaining: <color=#23f207>{0}</color>.\n", ["MsgToWinner"] = "You have won the event!\n", ["NobodyWon"] = "Nobody won the event.", ["EconomicsWon"] = "<color=#23f207>${0}</color> has been added to your account for winning.\n", ["ServerRewardsWon"] = "<color=#23f207>{0} points</color> were added to your account for winning.\n", ["SkillTreeXPWon"] = "You gained <color=#23f207>{0} xp</color> for winning.\n", ["FailedJoin_Closed"] = "Unable to join - Joining has closed.", ["FailedJoin_EventHelper"] = "Unable to join - Check the message from EventHelper.", ["FailedJoin_Enrolled"] = "Unable to join - You are already in this competition.", ["JoinAnnounce"] = "{0} joined the event [<color=#ffb600>{1}</color>/<color=#ffb600>{2}</color>]", ["LeftCompetition"] = "You left the arena.", ["NotAtEvent"] = "You are not at the event.", ["AddEntityEventRunning"] = "Event needs to be running to use this command.", ["AddEntityElevation"] = "Arena must not be above default elevation when adding spawns.", ["NullInvalidEntity"] = "Invalid entity targeted.Tried to target a rock, player or gates.", ["EntityRemoved"] = "Removed entity: {0} [POS: {1} - ROT: {2}]", ["EntityNotFoundInData"] = "Entity: {0} [POS: {1} - ROT: {2}] was not found in arena data.", ["EntityAddedTree"] = "Added new tree spawn at {0}", ["EntityAddedBush"] = "Added new bush spawn at {0}", ["EntityAddedLoot"] = "Added new loot spawn spawn at {0}", ["EntityAddedLog"] = "Added new log spawn at {0}", ["EntityAddInvalidType"] = "Invalid type selected.", ["InRadZone"] = "YOU ARE IN THE RADIATION ZONE!", ["UIPlayersRemaining"] = "Players remaining: <color=#ffae00>{0}</color>", ["UILootProfile"] = "Loot Profile", ["UIProfSelected"] = "<color=#ffae00>{0}</color>", ["UIHeightMod"] = "Height Mod", ["UILobbyTime"] = "Lobby Time", ["UISTOP"] = "<color=#f22407>STOP</color>", ["UISTART"] = "<color=#00be06>START</color>", ["UICLOSE"] = "CLOSE", ["UIEndedEvent"] = "Ended the event.", ["UIStartingEvent"] = "Starting event with the following parameters:\n- Lobby time: {0}\n- Height: {1}\n- Profile: {2}", ["_UILobbyTime"] = "GAME STARTING IN <color=#ffae00>{0}</color> SECONDS.\n<size=10>Type <color=#ffae00>/{1}</color> to leave the event.</size>", ["NoPrize"] = "You have no prizes left to claim.", ["PrizeGiven"] = "You received {0}x {1}.", ["JoinedTheEvent"] = "You joined the Survival Arena event!\nType <color=#00ff00>/{0}</color> if you wish to leave the event.", ["KillMessage1"] = "<color=#ffae00>{0}</color> stood no chance against <color=#ffae00>{1}</color>!", ["KillMessage2"] = "<color=#ffae00>{0}</color> was killed by magic...Or was it <color=#ffae00>{1}</color>?", ["KillMessage3"] = "<color=#ffae00>{0}</color> was escorted out of the arena by <color=#ffae00>{1}</color>.", ["KillMessage4"] = "<color=#ffae00>{0}</color> was slain by <color=#ffae00>{1}</color>.", ["KillMessage5"] = "<color=#ffae00>{0}</color> misplaced their weapon inside of <color=#ffae00>{1}</color>.", ["DeathMessage1"] = "<color=#ffae00>{0}</color> tripped on a branch and died.", ["DeathMessage2"] = "A cold breeze got the better of <color=#ffae00>{0}</color>!", ["DeathMessage3"] = "<color=#ffae00>{0}</color> decided that they no longer wish to play, so they died.", ["EventStillDespawning"] = "The arena is still being cleared from the last event.Please try again in a few seconds.", ["InvalidProfile"] = "You have specified an invalid loot profile [{0}].Valid profiles:\n- {1}", ["PrizesDisabled"] = "This command is not enabled as there are no prizes specified in the config.", ["CircleStatusUpdate"] = "Circle status: {0}", ["CircleStatusMOVING"] = "<color=#fff700>MOVING</color>", ["CircleStatusSTOPPED"] = "<color=#00ff00>STOPPED</color>", ["CircleStatusINACTIVE"] = "<color=#ff0000>INACTIVE</color>", ["UILeaveButton"] = "<color=#ff0000>LEAVE</color>"
}
, this);
}
#endregion
#region Data
PlayerEntity pcdData;
SpawnedEntities spawnData;
private DynamicConfigFile PCDDATA;
private DynamicConfigFile SPAWNDATA;
Dictionary<string, DynamicConfigFile> ARENASDATA = new Dictionary<string, DynamicConfigFile>();
Dictionary<string, ArenaData> Arenas = new Dictionary<string, ArenaData>();
public static Vector3 CurrentCentrePoint;
ArenaData CurrentArena;
const string subDirectory = "survivalArena/";
const string perm_admin = "survivalarena.admin";
void Init() {
UnsubHooks();
LoadData();
permission.RegisterPermission(perm_admin, this);
cmd.AddChatCommand(config.command_settings.join_command, this, nameof(JoinEvent));
cmd.AddChatCommand(config.command_settings.leave_command, this, nameof(LeaveEventCMD));
}
void Unload() {
SaveData();
try {
EndEvent(true);
}
catch {
}
try {
EventHelper.Call("EMRemoveEvent", this.Name);
}
catch {
}
cmd.RemoveChatCommand(config.command_settings.join_command, this);
cmd.RemoveChatCommand(config.command_settings.leave_command, this);
foreach (var player in BasePlayer.activePlayerList) {
try {
DestroyMonitor(player);
DestroyOutsiderMonitor(player);
}
catch {
}
}
if (Spawn_routine != null) ServerMgr.Instance.StopCoroutine(Spawn_routine);
Spawn_routine = null;
ServerMgr.Instance.StartCoroutine(DespawnEntities(0f, false, true));
foreach (var player in BasePlayer.activePlayerList) {
CuiHelper.DestroyUi(player, "GameStartUI");
CuiHelper.DestroyUi(player, "MenuBackground");
CuiHelper.DestroyUi(player, "STARTCountdownUI");
}
SaveData(SaveType.Spawn);
}
enum SaveType {
Both, Player, Arena, Spawn
}
void SaveData(SaveType saveType = SaveType.Player) {
if (saveType == SaveType.Both || saveType == SaveType.Player) PCDDATA.WriteObject(pcdData);
if (saveType == SaveType.Spawn) SPAWNDATA.WriteObject(spawnData);
if (saveType == SaveType.Both || saveType == SaveType.Arena) {
foreach (var DATA in ARENASDATA) {
ArenaData arenaData;
if (Arenas.TryGetValue(DATA.Key, out arenaData)) DATA.Value.WriteObject(arenaData);
}
//ARENADATA.WriteObject(arenaData);
}
}
bool HaveArenaFile = false;
void LoadData() {
try {
PCDDATA = Interface.Oxide.DataFileSystem.GetFile(subDirectory + "player_data");
pcdData = Interface.Oxide.DataFileSystem.ReadObject<PlayerEntity>(subDirectory + "player_data");
}
catch {
Puts("Couldn't load player data, creating new Playerfile");
pcdData = new PlayerEntity();
}
try {
SPAWNDATA = Interface.Oxide.DataFileSystem.GetFile(subDirectory + "spawn_data");
spawnData = Interface.Oxide.DataFileSystem.ReadObject<SpawnedEntities>(subDirectory + "spawn_data");
}
catch {
Puts("Could not load spawn_data file.");
spawnData = new SpawnedEntities();
}
//ARENADATA = Interface.Oxide.DataFileSystem.GetFile(subDirectory + "Arena");
foreach (var file in Interface.Oxide.DataFileSystem.GetFiles(subDirectory)) {
if (file.Contains("player_data") || file.Contains("spawn_data")) continue;
var name = file.Split('/')?.Last();
name = name.Replace(".json", "");
if (!ARENASDATA.ContainsKey(name)) {
var data = Interface.Oxide.DataFileSystem.GetFile(subDirectory + name);
if (data != null) {
//ARENADATA
try {
var arenaData = Interface.Oxide.DataFileSystem.ReadObject<ArenaData>(subDirectory + name);
if (arenaData != null) {
ARENASDATA.Add(name, data);
Arenas.Add(name, arenaData);
Puts($"Found and added arena: {name}");
HaveArenaFile = true;
SaveData(SaveType.Arena);
}
}
catch {
}
}
}
}
if (Arenas.Count == 0) {
Puts("Couldn't load arena data, creating new Arena data file");
AddArenaFile();
}
//if (Interface.Oxide.DataFileSystem.ExistsDatafile(subDirectory + "Arena"))
//{
// ARENADATA = Interface.Oxide.DataFileSystem.GetFile(subDirectory + "Arena");
// try
// {
// arenaData = Interface.Oxide.DataFileSystem.ReadObject<ArenaData>(subDirectory + "Arena");
// Puts($"Found and loaded arena data - Entities: {arenaData.entities?.Count}");
// HaveArenaFile = true;
// }
// catch
// {
// Puts("Couldn't load arena data, creating new Arena data file");
// AddArenaFile();
// }
//}
}
class ArenaData {
public float size = 210;
public Vector3 CenterPoint;
public List<EntityInfo> entities = new List<EntityInfo>();
}
public class EntityInfo {
public string prefab;
public Vector3 pos;
public Vector3 rot;
public EntityInfo(string prefab, Vector3 pos, Vector3 rot) {
this.prefab = prefab;
this.pos = pos;
this.rot = rot;
}
}
class SpawnedEntities {
public List<ulong> spawnedEntities = new List<ulong>();
}
class PlayerEntity {
public Dictionary<ulong, PCDInfo> pEntity = new Dictionary<ulong, PCDInfo>();
}
class PCDInfo {
public int rewards_remaining;
}
#endregion;
#region Get Arena
//[ConsoleCommand("getarena")]
//void GetArena(ConsoleSystem.Arg arg)
//{
// var player = arg.Player();
// if (player != null && !IsAdmin(player))
// {
// PrintToChat(player, lang.GetMessage("Prefix", this, player.UserIDString) + lang.GetMessage("NoPerms", this, player.UserIDString));
// return;
// }
// if (arg.Args == null || arg.Args.Length == 0)
// {
// arg.ReplyWith("You must specify the arena name");
// return;
// }
// GetArena((BasePlayer)null);
//}
[ChatCommand("getarena")]
void GetArena(BasePlayer player, string cmd, string[] args) {
if (player != null && !IsAdmin(player)) {
PrintToChat(player, lang.GetMessage("Prefix", this, player.UserIDString) + lang.GetMessage("NoPerms", this, player.UserIDString));
return;
}
if (string.IsNullOrEmpty(ConVar.Server.levelurl) || !ConVar.Server.levelurl.Contains("SurvivalArena")) {
if (player != null) PrintToChat(player, "The map file URL on your server must contain the name SurvivalArena in order to run this command.");
else Puts("The map file on your server must contain the name SurvivalArena in order to run this command.");
return;
}
if (args == null || args.Length == 0) {
if (player != null) PrintToChat(player, "You must specify a name for the arena");
else Puts("You must specify a name for the arena");
return;
}
var name = string.Join(" ", args);
name = name.Replace(" ", "_");
ArenaData arenaData = new ArenaData();
foreach (var entity in spawned_entities) {
entity?.KillMessage();
}
arenaData.entities.Clear();
foreach (var entity in BaseNetworkable.serverEntities) {
if (entity is BaseNpc || entity is BasePlayer) continue;
if (!IsWhitelisted(entity.PrefabName)) continue;
if (entity.PrefabName == "assets/prefabs/deployable/bbq/bbq.deployed.prefab") {
Puts("Found and stored center point.");
arenaData.CenterPoint = entity.transform.position;
continue;
}
// Replaces fire pit with wooden external gates
if (entity.PrefabName == "assets/prefabs/misc/halloween/skull_fire_pit/skull_fire_pit.prefab") {
arenaData.entities.Add(new EntityInfo("assets/prefabs/building/gates.external.high/gates.external.high.wood/gates.external.high.wood.prefab", entity.transform.position, entity.transform.rotation.eulerAngles));
continue;
}
// Replaces snow machine with roof triangles
if (entity.PrefabName == "assets/prefabs/misc/xmas/snow_machine/models/snowmachine.prefab") {
arenaData.entities.Add(new EntityInfo("assets/prefabs/building core/roof.triangle/roof.triangle.prefab", entity.transform.position, entity.transform.rotation.eulerAngles));
continue;
}
// Replaces carvable pumpkins with loot crates
if (entity.PrefabName == "assets/prefabs/misc/halloween/carvablepumpkin/carvable.pumpkin.prefab") {
arenaData.entities.Add(new EntityInfo("assets/bundled/prefabs/radtown/crate_normal_2.prefab", entity.transform.position, entity.transform.rotation.eulerAngles));
continue;
}
arenaData.entities.Add(new EntityInfo(entity.PrefabName, entity.transform.position, entity.transform.rotation.eulerAngles));
}
if (Arenas.ContainsKey(name)) {
Arenas[name] = arenaData;
PrintToChat(player, $"Overwrote old arena: {name}");
}
else {
Arenas.Add(name, arenaData);
PrintToChat(player, $"Added new arena: {name}");
}
SaveData(SaveType.Arena);
}
[ChatCommand("spawnarena")]
void SpawnArena(BasePlayer player, string cmd, string[] args) {
if (!IsAdmin(player)) {
PrintToChat(player, lang.GetMessage("Prefix", this, player.UserIDString) + lang.GetMessage("NoPerms", this, player.UserIDString));
return;
}
if (IsDespawning) {
PrintToChat(player, lang.GetMessage("Prefix", this, player?.UserIDString) + lang.GetMessage("EventStillDespawning", this, player.UserIDString));
return;
}
if (args == null || args.Length == 0) {
PrintToChat(player, $"You must specify the arena.Available arenas:\n{string.Join("\n", Arenas.Keys)}");
return;
}
string arenaName = args[0];
if (!Arenas.ContainsKey(arenaName)) {
PrintToChat(player, $"{arenaName} is not a valid arena! Valid arenas:\n{string.Join("\n", Arenas.Keys)}");
return;
}
float heightMod = args != null && args.Length > 1 ? Convert.ToSingle(args[1]) : 0f;
CurrentArena = Arenas[arenaName];
StartSpawnSequence(heightMod, false);
DevMode = true;
}
[ChatCommand("cleararena")]
void ClearArena(BasePlayer player) {
if (!IsAdmin(player)) {
PrintToChat(player, lang.GetMessage("Prefix", this, player.UserIDString) + lang.GetMessage("NoPerms", this, player.UserIDString));
return;
}
EndEvent();
}
bool IsWhitelisted(string prefab) {
foreach (var item in prefab_whitelist) {
if (prefab.StartsWith(item)) return true;
}
return false;
}
List<string> prefab_whitelist = new List<string>() {
"assets/bundled/prefabs/modding/admin/", "assets/bundled/prefabs/autospawn/resource/", "assets/prefabs/misc/xmas/", "assets/prefabs/deployable/", "assets/prefabs/building/", "assets/prefabs/building core/", "assets/prefabs/misc/halloween/"
}
;
[ChatCommand("setcentrepoint")]
void SetCentrePoint(BasePlayer player, string cmd, string[] args) {
if (!IsAdmin(player)) {
PrintToChat(player, lang.GetMessage("Prefix", this, player.UserIDString) + lang.GetMessage("NoPerms", this, player.UserIDString));
return;
}
// ... [Code preview truncated due to length. Full source in attached file] ...