C#:
using System;
using System.Linq;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Plugins;
using UnityEngine;
using Oxide.Game.Rust.Cui;
using System.Globalization;
namespace Oxide.Plugins {
[Info("RustyTeleport", "__red", "1.27.3140")]
class RustyTeleport : RustPlugin {
#region References
[PluginReference]
Plugin Clans;
[PluginReference]
Plugin Friends;
[PluginReference]
Plugin NoEscape;
[PluginReference]
Plugin Duel;
#endregion
#region Variables
private RustyTeleportConfig m_Config;
private Dictionary<int, TeleportObject> m_TeleportToPlayerWaiters;
private Dictionary<string, PlayerPluginData> m_ActivePlayers;
private Dictionary<int, HomeTeleportObject> m_TeleportToHomeWaiters;
#endregion
#region Configuration
public enum Settings {
SaveHomeLimit, TeleportToHomeLimit, TeleportToPlayerLimit, WaitToTeleportTime, WaitToHomeTeleportTime, WaitAfterTeleport, WaitAfterTeleportHome
}
private class RustyTeleportConfig {
[JsonProperty("Префикс плагина для отображения в чате")]
public string PluginPrefix {
get;
set;
}
[JsonProperty("Включить префикс плагина ?")]
public bool EnablePluginPrefix {
get;
set;
}
[JsonProperty("Включить вывод информации о привилегиях в консоль ?")]
public bool EnablePrintPermissionsInfo {
get;
set;
}
[JsonProperty("Включить GUI в плагине ?")]
public bool EnableGUI {
get;
set;
}
[JsonProperty("Включить логирование использования команд администраторами ?")]
public bool EnableAdminCommandsLogging {
get;
set;
}
[JsonProperty("Файл логирования команд администраторами")]
public string AdminCommandsLoggingFile {
get;
set;
}
[JsonProperty("Включить логирование использования команд игроками ?")]
public bool EnableUsersCommandsLogging {
get;
set;
}
[JsonProperty("Файл логирования команд игроками")]
public string UserCommandsLoggingFile {
get;
set;
}
[JsonProperty("Включить систему домов ?")]
public bool AllowHomeSystem {
get;
set;
}
[JsonProperty("Включить систему телепортации ?")]
public bool AllowTeleportSystem {
get;
set;
}
[JsonProperty("Разрешить использовать систему телепорта во время блока NoEscape ?")]
public bool AllowTeleportInEscapeBlock {
get;
set;
}
[JsonProperty("Разрешить использовать систему телепорта во время рейда ?")]
public bool AllowTeleportInRaidBlock {
get;
set;
}
[JsonProperty("Разрешить использовать систему телепорта во время боя ?")]
public bool AllowTeleportInCombatBlock {
get;
set;
}
[JsonProperty("Разрешить использовать систему телепорта в воде ?")]
public bool AllowTeleportInWater {
get;
set;
}
[JsonProperty("Уровень воды для отмены телепорта")]
public double CancelTeleportWaterFactor {
get;
set;
}
[JsonProperty("Разрешить телепортироваться в ванише ?")]
public bool AllowTeleportInVanish {
get;
set;
}
[JsonProperty("Разрешить телепорт из РТ ?")]
public bool AllowTeleportInRT {
get;
set;
}
[JsonProperty("Дальность от РТ для проверки")]
public float ToRTDistance {
get;
set;
}
[JsonProperty("Разрешить использовать систему телепорта во время крафта ?")]
public bool AllowTeleportInCraft {
get;
set;
}
[JsonProperty("Разрешить использовать систему телепорта при ваунде ?")]
public bool AllowTeleportInWounded {
get;
set;
}
[JsonProperty("Разрешить использовать систему телепорта после смерти ?")]
public bool AllowTeleportAfterDeath {
get;
set;
}
[JsonProperty("Разрешить использовать систему телепорта во время действия радиации ?")]
public bool AllowTeleportInRadiation {
get;
set;
}
[JsonProperty("Уровень радиации для отмены телепорта")]
public int CancelTeleportRadiationFactor {
get;
set;
}
[JsonProperty("Разрешить использовать систему телепорта во время действия кровотечения ?")]
public bool AllowTeleportInBleeding {
get;
set;
}
[JsonProperty("Уровень кровотечения для отмены телепорта")]
public int CancelTeleportBleedingFactor {
get;
set;
}
[JsonProperty("Разрешить использовать систему телепорта при получении урона ?")]
public bool AllowTeleportAfterDamage {
get;
set;
}
[JsonProperty("Разрешить использовать систему телепорта во время охлаждения ?")]
public bool AllowTeleportInFreezing {
get;
set;
}
[JsonProperty("Уровень холода для отмены телепорта")]
public int CancelTeleportFreezeFactor {
get;
set;
}
[JsonProperty("Разрешить использовать систему телепорта в зоне действия чужого шкафа ?")]
public bool AllowTeleportInBBZone {
get;
set;
}
[JsonProperty("Разрешить использовать систему телепорта только друзьям ?")]
public bool AllowTeleportOnlyFriends {
get;
set;
}
[JsonProperty("Разрешить использовать систему телепорта только соклановцам ?")]
public bool AllowTeleportOnlyClan {
get;
set;
}
[JsonProperty("Разрешить телепорт при получении урона ?")]
public bool AllowTeleportAfterRCVDamage {
get;
set;
}
[JsonProperty("Разрешить сохранять дом только на фундаменте ?")]
public bool AllowSaveHomeOnlyFundament {
get;
set;
}
[JsonProperty("Создавать спальный мешок после сохранения дома ?")]
public bool CreateBagAfterHomeSave {
get;
set;
}
[JsonProperty("Разрешить сохранять дом в зоне действия чужого шкафа ?")]
public bool AllowSaveHomeOnBB {
get;
set;
}
[JsonProperty("Разрешить сохранять дом только на фундаменте соклановцев ?")]
public bool AllowSaveHomeOnClanFundament {
get;
set;
}
[JsonProperty("Разрешить сохранять дом только на фундаменте друзей ?")]
public bool AllowSaveHomeOnFriendFundament {
get;
set;
}
[JsonProperty("Время ожидания телепорта по умолчанию")]
public int DefaultTimeToTeleport {
get;
set;
}
[JsonProperty("Время ожидания телепорта домой по умолчанию")]
public int DefaultTimeToTeleportHome {
get;
set;
}
[JsonProperty("Время восстановление телепорта по умолчанию")]
public int DefaultRemainingAfterTeleport {
get;
set;
}
[JsonProperty("Время восстановления телепорта домой по умолчанию")]
public int DefaultRemainingAfterHomeTeleport {
get;
set;
}
[JsonProperty("Количество сохраняемых домов по умолчанию")]
public int DefaultSaveHomeLimit {
get;
set;
}
[JsonProperty("Количество телепортов к игроку в сутки ?")]
public int DefaultTTPOneDay {
get;
set;
}
[JsonProperty("Количество телепортов домой в сутки ?")]
public int DefaultTTHOneDay {
get;
set;
}
[JsonProperty("Время, через которое запрос будет отменен автоматически, если игрок на него не ответил")]
public int DefaultRequestCancelledTime {
get;
set;
}
[JsonProperty("Время, через которое лимиты будут обновлены автоматически (По умолчанию = 24 часа)")]
public int DefaultLimitsUpdated {
get;
set;
}
[JsonProperty("Название уведомления о телепортации.(По умолчанию: ЗАПРОС:)")]
public string DefaultHeaderTeleportNotify {
get;
set;
}
[JsonProperty("Сообщение о запросе на телепорт.(По умолчанию {0} хочет телепортироваться к Вам)")]
public string DefaultFromTeleportNotify {
get;
set;
}
[JsonProperty("Включить звуковое уведомление")]
public bool EnableSoundEffects {
get;
set;
}
[JsonProperty("Кастомные пути к звуковому файлу, для воспроизведения.Если парааметр: 'Включить звуковое уведомление' включен")]
public Dictionary<string, string> SoundsFotNotify {
get;
set;
}
[JsonProperty("Динамическая система привилегий.Указывайте настройки для каждой привилегии.Пример указан.")]
public Dictionary<string, Dictionary<string, Dictionary<string, int>>> PermissionSettings {
get;
set;
}
public static RustyTeleportConfig Prototype() {
return new RustyTeleportConfig() {
PluginPrefix = "[RustyTP]", EnableGUI = true, AllowTeleportAfterRCVDamage = false, DefaultHeaderTeleportNotify = "ЗАПРОС:", DefaultFromTeleportNotify = "{0} хочет телепортироваться к Вам", EnablePrintPermissionsInfo = true, EnablePluginPrefix = true, EnableAdminCommandsLogging = true, AdminCommandsLoggingFile = "Admin_Teleports_log", EnableUsersCommandsLogging = true, UserCommandsLoggingFile = "User_Teleports_log", AllowHomeSystem = true, AllowTeleportInCombatBlock = false, AllowTeleportInEscapeBlock = false, AllowTeleportInRaidBlock = false, AllowTeleportInVanish = true, AllowTeleportInRT = false, ToRTDistance = 150f, CancelTeleportBleedingFactor = 5, CancelTeleportFreezeFactor = 5, CancelTeleportRadiationFactor = 5, CancelTeleportWaterFactor = 0.2, AllowTeleportSystem = true, AllowTeleportInWounded = false, AllowTeleportInWater = false, AllowTeleportInCraft = false, AllowTeleportAfterDeath = false, AllowTeleportAfterDamage = false, AllowTeleportInRadiation = false, AllowTeleportInBleeding = false, AllowTeleportInFreezing = false, AllowTeleportInBBZone = false, AllowTeleportOnlyFriends = false, AllowTeleportOnlyClan = false, AllowSaveHomeOnlyFundament = true, CreateBagAfterHomeSave = true, AllowSaveHomeOnBB = false, AllowSaveHomeOnClanFundament = false, AllowSaveHomeOnFriendFundament = false, DefaultSaveHomeLimit = 3, DefaultTimeToTeleport = 15, DefaultTimeToTeleportHome = 15, DefaultRemainingAfterTeleport = 120, DefaultRemainingAfterHomeTeleport = 120, DefaultTTPOneDay = 30, DefaultTTHOneDay = 15, DefaultRequestCancelledTime = 15, DefaultLimitsUpdated = 86400, EnableSoundEffects = true, SoundsFotNotify = new Dictionary<string, string>() {
["tp_request"]
= "assets/prefabs/locks/keypad/effects/lock.code.denied.prefab", ["tp_receive"] = "assets/prefabs/locks/keypad/effects/lock.code.denied.prefab", ["home_teleport"] = "assets/prefabs/locks/keypad/effects/lock.code.denied.prefab",
}
, PermissionSettings = new Dictionary<string, Dictionary<string, Dictionary<string, int>>>() {
["rustyteleport.vip"]
= new Dictionary<string, Dictionary<string, int>>() {
["Settings"]
= new Dictionary<string, int>() {
["SaveHomeLimit"]
= 3, ["TeleportToHomeLimit"] = 20, ["TeleportToPlayerLimit"] = 40, ["WaitToTeleportTime"] = 10, ["WaitToHomeTeleportTime"] = 10, ["WaitAfterTeleport"] = 60, ["WaitAfterTeleportHome"] = 60
}
}
, ["rustyteleport.admin"] = new Dictionary<string, Dictionary<string, int>>() {
["Settings"]
= new Dictionary<string, int>() {
["SaveHomeLimit"]
= 999, ["TeleportToHomeLimit"] = 999, ["TeleportToPlayerLimit"] = 999, ["WaitToTeleportTime"] = 1, ["WaitToHomeTeleportTime"] = 1, ["WaitAfterTeleport"] = 1, ["WaitAfterTeleportHome"] = 1
}
}
}
}
;
}
}
protected override void LoadDefaultConfig() {
m_Config = RustyTeleportConfig.Prototype();
PrintWarning("Creating default a configuration file...");
RegisterPermissions();
}
protected override void LoadConfig() {
base.LoadConfig();
m_Config = Config.ReadObject<RustyTeleportConfig>();
RegisterPermissions();
}
protected override void SaveConfig() => Config.WriteObject(m_Config);
#endregion
#region Localize
protected override void LoadDefaultMessages() {
lang.RegisterMessages(new Dictionary<string, string>() {
["error_player_in_bleeding"]
= "<color=#ba2c2c>Нельзя использовать телепорт если у вас кровотечение</color>", ["error_target_in_bleeding"] = "<color=#ba2c2c>У игрока, которому вы отправляете запрос, кровотечение</color>", ["error_player_in_freezing"] = "<color=#4acce2>Нельзя использовать телепорт, когда вы замерзаете</color>", ["error_target_in_freezing"] = "<color=#4acce2>Игрок, которому вы отправляете запрос, замерзает</color>", ["error_player_in_wounded"] = "<color=#d8e82e>Нельзя использовать телепорт в ваунде</color>", ["error_target_in_wounded"] = "<color=#d8e82e>Игрок, которому вы отправляете запрос в ваунде</color>", ["error_player_in_water"] = "<color=#0571ba>Нельзя использовать телепорт находясь в воде</color>", ["error_target_in_water"] = "<color=#0571ba>Игрок, которому вы отправляете запрос находится в воде</color>", ["error_player_in_radiation"] = "<color=#ddf21f>Нельзя использовать телепорт во время действия радиации</color>", ["error_target_in_radiation"] = "<color=#ddf21f>Игрок, которому вы отправляете запрос находится под воздействием радиации</color>", ["error_player_in_already_teleported"] = "<color=#f11f1f>Вы уже телепортируетесь</color>", ["error_target_in_already_teleported"] = "<color=#f11f1f>Игрок, которому вы отправляете запрос уже телепортируется</color>", ["error_player_in_bb"] = "<color=#f11f1f>Нельзя использовать телепорт в зоне действия чужого шкафа</color>", ["error_target_in_bb"] = "<color=#f11f1f>Игрок, которому вы отправляете запрос находится в зоне действия чужого шкафа</color>", ["error_ttp_cooldown"] = "<color=#f0761e>Невозможно отправить запрос.Попробуйте через {0} секунд</color>", ["info_ttp_cooldown_reseted"] = "<color=#49b50a>Теперь вы снова можете телепортироватся к другим</color>", ["error_tth_cooldown"] = "<color=#f0761e>Невозможно отправить запрос.Попробуйте через {0} секунд</color>", ["info_tth_cooldown_reseted"] = "<color=#49b50a>Теперь вы снова можете телепортироватся домой</color>", ["error_ttp_only_friend"] = "<color=#ba2c2c>Телепортироваться можно только к друзьям</color>", ["error_ttp_only_clan"] = "<color=#ba2c2c>Телепортироваться можно только к члену вашего клана</color>", ["error_ttp_incorrect_target"] = "<color=#ba2c2c>Запрашиваемый игрок не найден</color>", ["error_ttp_self"] = "<color=#ba2c2c>Серьезно? К самому себе?</color>", ["error_ttp_player_already_wait"] = "<color=#ba2c2c>Вы уже ожидаете телепортации</color>", ["error_ttp_target_already_wait"] = "<color=#ba2c2c>Ваша цель уже находится в очереди на телепортацию</color>", ["info_ttp_request_cancelled"] = "<color=#49b50a>Запрос на телепортацию был отменен</color>", ["info_ttp_request_notfound"] = "<color=#ba2c2c>Отсутствуют доступные запросы для совершения этого действия</color>", ["info_ttp_request_player_appended"] = "<color=#ffa500ff>Игрок '{0}' принял ваш запрос.Вы будете телепортированы через {1} секунд</color>", ["info_ttp_request_target_appended"] = "<color=#ffa500ff>Вы приняли запрос от игрока '{0}'.Он появится возле вас черех {1} секунд</color>", ["info_ttp_request_player_finished"] = "<color=#49b50a>Игрок '{0}' успешно телепортировался к вам</color>", ["info_ttp_request_target_finished"] = "<color=#49b50a>Вы успешно телепортированы к игроку '{0}'.Осталось телепортов: {1}</color>", ["info_ttp_request_player_created"] = "<color=#49b50a>Запрос на телепортацию к игроку '{0}' создан успешно.Ожидайте ответа</color>", ["info_ttp_request_target_created"] = "<color=#49b50a>Игрок '{0}' хочет к вам телепортироваться.Чтобы принять введите /tpa и /tpc чтобы отклонить.Он будет автоматически отклонен, если вы не ответите в течении 15 секунд</color>", ["whose_from_waiter_already_wait"] = "<color=#ba2c2c>Ктото из участников уже ожидает телепортации.Если это вы, то введите /tpc для отмены запроса</color>", ["error_command_sethome_incorrect"] = "<color=#ba2c2c>Неверный синтакисис.Используйте команду следующим образом /sethome [name]</color>", ["error_home_already_exists"] = "<color=#ba2c2c>Дом с таким именем уже существует</color>", ["error_max_home_limits"] = "<color=#ba2c2c>Вы установили максимальное число домов для себя</color>", ["info_ttp_limit_reseted"] = "<color=#49b50a>Лимит использования телепортов к игрокам для Вас обновлен !</color>", ["info_tth_limit_reseted"] = "<color=#49b50a>Лимит использования телепортов домой для Вас обновлен !</color>", ["error_ttp_unlimited"] = "<color=#ba2c2c>Лимит использований исчерпан.Попробуйте через: {0}ч.{1}м.{2}с.</color>", ["error_teleport_system_disabled"] = "<color=#ba2c2c>Система телепортации временно отключена</color>", ["error_player_received_damage"] = "<color=#ba2c2c>Вы получили урон</color>", ["error_target_received_damage"] = "<color=#ba2c2c>Ваша цель получила урон</color>", ["error_player_start_damage"] = "<color=#ba2c2c>Вы вступили в бой</color>", ["error_target_start_damage"] = "<color=#ba2c2c>Ваша цель вступила в бой</color>", ["error_player_is_death"] = "<color=#ba2c2c>Вы умерли</color>", ["error_target_is_death"] = "<color=#ba2c2c>Ваша цель умерла</color>", ["error_command_tpr_incorrect"] = "<color=#ba2c2c>Неправильное использование команды.Пример /tpr [nickname]</color>", ["error_tth_received_damage"] = "<color=#ba2c2c>Вы получили повреждения</color>", ["error_tth_start_damage"] = "<color=#ba2c2c>Вы вступили в бой</color>", ["error_tth_player_die"] = "<color=#ba2c2c>Вас убили</color>", ["info_home_deleted_by_demolish"] = "<color=#ba2c2c>Блок на котором стоял Ваш дом уничтожен.Дом был удален</color>", ["error_rename_other_bags"] = "<color=#ba2c2c>Нельзя переименовывать чужие дома</color>", ["error_ttp_cancelled_player_after_wounded"] = "<color=#ba2c2c>Вы получили критические ранения</color>", ["error_ttp_cancelled_target_after_wounded"] = "<color=#ba2c2c>Игрок, который к Вам телепортируется получил критические ранения</color>", ["error_tth_cancelled_after_wounded"] = "<color=#ba2c2c>Вы получили критические повреждения</color>", ["info_home_created"] = "<color=#49b50a>Дом: '{0}' успешно сохранен</color>", ["error_sethome_save_only_clan_foundation"] = "<color=#ba2c2c>Сохранять дом разрешено только на фундаменте членов клана</color>", ["error_sethome_save_only_friend_foundation"] = "<color=#ba2c2c>Сохранять дом разрешено только на фундаменте друзей</color>", ["error_home_system_disabled"] = "<color=#ba2c2c>Система домов временно недоступна.Попробуйте позже</color>", ["error_command_sethome_incorrect"] = "<color=#ba2c2c>Неверный синтаксис для команды.Пример: /sethome [homename]</color>", ["error_max_home_limits"] = "<color=#ba2c2c>Вы уже сохранили максимальное количество домов</color>", ["error_home_already_exists"] = "<color=#ba2c2c>Дом с таким названием уже существует</color>", ["error_sethome_only_foundation"] = "<color=#ba2c2c>Сохранять дома разрешено только на фундаменте !</color>", ["error_sethome_save_on_bb"] = "<color=#ba2c2c>Нельзя сохранять дом в зоне действия чужого шкафа</color>", ["error_command_removehome_incorrect"] = "<color=#ba2c2c>Некорректный синтаксис для команды.Пример: /removehome 1</color>", ["error_saved_home_notfound"] = "<color=#ba2c2c>Дом: '{0}' не найден.Проверьте корректность ввода</color>", ["error_home_killed_automatic_deleted"] = "<color=#ba2c2c>Этот дом был уничтожен и поэтому он был удален</color>", ["error_home_deleted_cancelled_teleport"] = "<color=#ba2c2c>Дом был удален</color>", ["info_home_deleted"] = "<color=#49b50a>Дом: '{0}' был успешно удален</color>", ["info_command_homelist"] = "<color=#f11f1f>Дом: '{0}'(ID:{1}).Позиция: {2}</color>", ["info_command_homelist_home_dexists"] = "<color=#49b50a>У вас нет сохраненных домов.Используйте /sethome [homename]</color>", ["error_coomand_tphome_incorrect"] = "<color=#ba2c2c>Неверный синтаксис.Пример: /home [homename]</color>", ["error_home_does_not_exists"] = "<color=#ba2c2c>Дома с именем: '{0}' не существует.</color>", ["info_home_deleted_other_bb"] = "<color=#ba2c2c>Этот дом Вам больше не принадлежит.Дом удален</color>", ["info_tth_request_created"] = "<color=#f11f1f>Запрос принят.Вы будете телепортированы домой через {0} секунд</color>", ["info_tth_already_wait"] = "<color=#ba2c2c>В данный момент вы уже ожидаете телепортации домой</color>", ["info_tth_request_finished"] = "<color=#49b50a>Вы были возвращены домой.Осталось возвращений: {0}</color>", ["info_tth_request_cancelled"] = "<color=#ba2c2c>Телепорт домой был отменен</color>", ["info_tth_request_notfound"] = "<color=#ba2c2c>Доступные запросы отсутствуют</color>", ["error_tth_unlimited"] = "<color=#ba2c2c>Лимит использований исчерпан.Попробуйте через: {0}ч.{1}м.{2}с.</color>", ["error_pickup_registered_home"] = "<color=#ba2c2c>Нельзя подобрать спальный мешок, привязанный к дому.Используйте /removehome [homename]</color>", ["error_pickup_other_bag"] = "<color=#ba2c2c>Нельзя подбирать чужие спальные мешки</color>", ["error_decline_assign_bed"] = "<color=#ba2c2c>Нельзя дарить спальные мешки привязанные к дому</color>", ["info_home_destroyed"] = "<color=#ba2c2c>Один из ваших домов был уничтожен</color>", ["error_player_in_rt"] = "<color=#ba2c2c>Нельзя телепортироваться в зоне РТ</color>", ["error_target_in_rt"] = "<color=#ba2c2c>Ваша цель находится в зоне РТ</color>", ["error_player_in_noescape"] = "<color=#ba2c2c>Вам запрещено сейчас телепортироваться</color>", ["error_target_in_noescape"] = "<color=#ba2c2c>Вашей цели запрещено сейчас телепортироваться</color>", ["error_player_in_raidblock"] = "<color=#ba2c2c>Запрещено использовать телепорт во время рейда</color>", ["error_target_in_raidblocked"] = "<color=#ba2c2c>Ваша цель учавствует в рейде, попробуйте позже</color>", ["error_player_in_combatblock"] = "<color=#ba2c2c>В бою запрещено использовать телепорт</color>", ["error_target_in_combatblock"] = "<color=#ba2c2c>Ваша цель в бою, попробуйте позже</color>", ["info_create_tth_remaining"] = "<color=#ba2c2c>Лимит на использование телепортов домой был полностью израсходован</color>", ["info_create_ttp_remaining"] = "<color=#ba2c2c>Лимит телепортов к игрокам был полностью израсходован</color>", ["incorrect_command_tp"] = "<color=#ba2c2c>Некорректное использование команды /tp.Ознакомьтесь с документацией плагина на https://whiteplugins.ru</color>", ["error_player_isnt_admin"] = "<color=#ba2c2c>Для использования этой команды Вы должны обладать правами администратора</color>", ["error_parse_coords_failed_self"] = "<color=#ba2c2c>Не удалось распознать введенные координаты.Проверьте корректность ввода</color>", ["info_gui_enabled"] = "<color=#49b50a>Вы включили GUI уведомления</color>", ["info_gui_disabled"] = "<color=#ba2c2c>Вы отключили GUI уведомления</color>", ["info_all_enabled"] = "<color=#49b50a>Теперь все игроки могут отправить Вам запрос на телепортацию</color>", ["info_all_disabled"] = "<color=#ba2c2c>Вы недоступны для запроса на телепортацию для всех</color>", ["info_clan_enabled"] = "<color=#49b50a>Теперь соклановцы могут отправлять Вам запрос на телепортацию</color>", ["info_clan_disabled"] = "<color=#ba2c2c>Вы не доступны для запросов на телепортацию от соклановцев</color>", ["info_friend_enabled"] = "<color=#49b50a>Теперь друзья могут отправлять Вам запросы на телепортацию</color>", ["info_friend_disabled"] = "<color=#ba2c2c>Вы недоступны для запроса на телепортацию для друзей</color>", ["player_disabled_all_teleport"] = "<color=#ba2c2c>Игрок запретил отправлять ему запросы на телепортацию</color>", ["player_disabled_clan_teleport"] = "<color=#ba2c2c>Игрок запретил соклановцам телепортироваться к нему</color>", ["player_disabled_friend_teleport"] = "<color=#ba2c2c>Игрок запретил друзья телепортироваться к нему</color>", ["error_target_in_duel"] = "<color=#ba2c2c>В данный момент ваша цель принимает участие в дуэли.Попробуйте позже</color>", ["error_player_in_duel"] = "<color=#ba2c2c>Вы не можете использовать систему телепорта во время дуэли</color>",
}
, this);
}
#endregion
#region Custom Structs
public enum Remainings {
TeleportToHome, TeleportToPlayer, NextTTPLimit, NextTTHLimit
}
private class PlayerPluginData {
public string ID {
get;
set;
}
public string Name {
get;
set;
}
public int TTPLimit {
get;
set;
}
public int TTHLimit {
get;
set;
}
public bool GuiEnabled {
get;
set;
}
public bool FriendsEnabled {
get;
set;
}
public bool ClanEnabled {
get;
set;
}
public bool AllEnabled {
get;
set;
}
public Dictionary<string, HomeObject> Homes {
get;
set;
}
public TimerBase NextTeleportRemaining {
get;
set;
}
public TimerBase NextHomeTeleportRemaining {
get;
set;
}
public TimerBase NextTTPLimitRemaining {
get;
set;
}
public TimerBase NextTTHLimitRemaining {
get;
set;
}
public PlayerPluginData() : this("-1", "-1", -1, -1, new Dictionary<string, HomeObject>(), new TimerBase(), new TimerBase(), new TimerBase(), new TimerBase()) {
}
public PlayerPluginData(string id, string name, int ttpl, int tthl, Dictionary<string, HomeObject> homes, TimerBase nextTR, TimerBase nextHTR, TimerBase nttp, TimerBase ntth) {
ID = id;
Name = name;
Homes = homes;
TTPLimit = ttpl;
TTHLimit = tthl;
NextTeleportRemaining = nextTR;
NextHomeTeleportRemaining = nextHTR;
NextTTPLimitRemaining = nttp;
NextTTHLimitRemaining = ntth;
GuiEnabled = true;
FriendsEnabled = true;
ClanEnabled = true;
AllEnabled = true;
}
public void CreateRemaining(Remainings type, PluginTimers timer, int seconds, Action callback) {
if(type == Remainings.TeleportToHome) {
NextHomeTeleportRemaining.Instantiate(timer, seconds, callback);
}
else if (type == Remainings.TeleportToPlayer) {
NextTeleportRemaining.Instantiate(timer, seconds, callback);
}
else if(type == Remainings.NextTTPLimit) {
NextTTPLimitRemaining.Instantiate(timer, seconds, callback);
}
else if(type == Remainings.NextTTHLimit) {
NextTTHLimitRemaining.Instantiate(timer, seconds, callback);
}
else {
return;
}
}
public void CreateHome(int id, string name, BasePlayer player, int limit, bool createBag) {
if(Homes.Count >= limit) {
return;
}
if(Homes.ContainsKey(name)) {
return;
}
Homes.Add(name, new HomeObject(id, name, player.transform.position, player, createBag));
}
public void RestoreHome(string name, SleepingBag bag) {
if(Homes.ContainsKey(name)) {
Homes[name].Bag = bag;
}
}
public void RemoveHome(string name) {
if(!Homes.ContainsKey(name)) {
return;
}
if (Homes[name].Bag != null) {
Homes[name].Bag.enabled = false;
Homes[name].Bag.Kill();
Homes[name].Bag = null;
Homes.Remove(name);
}
}
public void PrepareToSave() {
NextHomeTeleportRemaining.Destroy();
NextTeleportRemaining.Destroy();
NextTTPLimitRemaining.Destroy();
NextTTHLimitRemaining.Destroy();
foreach(var home in Homes) {
home.Value.Bag = null;
}
}
}
private class TeleportObject {
public int ID {
get;
set;
}
public int Seconds {
get;
set;
}
public bool Accepted {
get;
set;
}
public PlayerPluginData Initiator {
get;
private set;
}
public PlayerPluginData Target {
get;
private set;
}
public TimerBase Remaining {
get;
private set;
}
public TeleportObject(PlayerPluginData init, PlayerPluginData target, int secs) {
Initiator = init;
Target = target;
Seconds = secs;
Remaining = new TimerBase();
}
public void Instantiate(PluginTimers timer, Action callback, Action onTick = null) {
Remaining.Instantiate(timer, Seconds, callback, onTick);
}
}
private class HomeObject {
public int ID {
get;
set;
}
public string Name {
get;
set;
}
public Vector3 Position {
get;
set;
}
public SleepingBag Bag {
get;
set;
}
public HomeObject() {
ID = -1;
Name = "-1";
Position = new Vector3();
Bag = null;
}
public HomeObject(int id, string name, Vector3 pos, BasePlayer player, bool createBag) {
ID = id;
Name = name;
Position = pos;
if (createBag) Bag = CreateSleepingBag(player);
}
private SleepingBag CreateSleepingBag(BasePlayer player) {
SleepingBag sleepingBag = GameManager.server.CreateEntity("assets/prefabs/deployable/sleeping bag/sleepingbag_leather_deployed.prefab", player.transform.position, player.transform.localRotation) as SleepingBag;
if (sleepingBag == null) return null;
sleepingBag.transform.Rotate(player.transform.localEulerAngles);
sleepingBag.deployerUserID = player.userID;
sleepingBag.niceName = Name;
sleepingBag.OwnerID = player.userID;
sleepingBag.Spawn();
return sleepingBag;
}
}
private class HomeTeleportObject {
public int ID {
get;
set;
}
public int Seconds {
get;
set;
}
public TimerBase Remaining {
get;
set;
}
public PlayerPluginData Owner {
get;
set;
}
public Vector3 Position {
get;
set;
}
public HomeTeleportObject(PlayerPluginData owner, int secs, Vector3 pos) {
Owner = owner;
Seconds = secs;
Remaining = new TimerBase();
Position = pos;
}
public void Instantiate(PluginTimers timer, Action callback, Action onTick = null) {
Remaining.Instantiate(timer, Seconds, callback, onTick);
}
}
private class TimerBase {
public Timer Object {
get;
set;
}
public int Remaining {
get;
set;
}
public bool IsEnabled {
get;
set;
}
public TimerBase() {
Remaining = 0;
IsEnabled = false;
}
public void Instantiate(PluginTimers @object, int secs, Action callBackAction, Action onTick = null) {
Object = @object.Repeat(1, secs, () => {
secs--;
Remaining = secs;
if (onTick != null) onTick();
if (secs == 0) {
IsEnabled = false;
callBackAction();
}
else IsEnabled = true;
}
);
}
public void Destroy() {
if (Object != null) {
Object.Destroy();
Object = null;
}
IsEnabled = false;
}
}
#endregion
#region Initialization
public RustyTeleport() {
m_ActivePlayers = new Dictionary<string, PlayerPluginData>();
m_TeleportToPlayerWaiters = new Dictionary<int, TeleportObject>();
m_TeleportToHomeWaiters = new Dictionary<int, HomeTeleportObject>();
}
private void RegisterPermissions() {
foreach(var perm in m_Config.PermissionSettings) {
if(!permission.PermissionExists(perm.Key, this)) {
permission.RegisterPermission(perm.Key, this);
if (m_Config.EnablePrintPermissionsInfo) {
PrintWarning($"Create new permission: '{perm.Key}' with settings:");
foreach (var prefix in perm.Value) {
foreach (var settings in prefix.Value) {
PrintWarning($"[{settings.Key}] => {settings.Value}");
}
}
}
}
}
}
#endregion
#region Hooks
void Loaded() {
LoadAllPlayers();
}
/// <summary>
/// Происходит при выгрузке плагина
/// </summary>
void Unload() {
SaveAllPlayers();
}
/// <summary>
/// Происходит при инициализации игрока
/// </summary>
/// <param name="player"></param>
void OnPlayerInit(BasePlayer player) {
LoadPlayer(player);
}
/// <summary>
/// Происходит при отключении игрока от сервера
/// </summary>
/// <param name="player"></param>
/// <param name="reason"></param>
void OnPlayerDisconnected(BasePlayer player, string reason) {
if(IsAlreadyWait(player, true) || IsAlreadyWait(player, false)) {
CancelTTPRequest(player.UserIDString);
}
if(IsWaitTeleportToHome(player)) {
CancelTTHRequest(player.UserIDString);
}
SavePlayer(player);
}
void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
if (entity == null && info == null) {
return;
}
BasePlayer victim = entity?.ToPlayer();
BasePlayer attacker = info?.InitiatorPlayer;
if (victim == null) {
return;
}
if (attacker == null) {
return;
}
if (m_Config.AllowTeleportAfterDamage) {
return;
}
if (IsAlreadyWait(victim, true) || IsAlreadyWait(victim, false)) {
TeleportObject data = GetTeleportData(GetPlayerFromActive(victim.UserIDString));
if (data == null) {
data = GetTeleportData(GetPlayerFromActive(victim.UserIDString), false);
}
if(victim.UserIDString == data.Initiator.ID) {
SendReply(FindPlayer(data.Initiator.ID), GetMessage("error_player_received_damage", this));
SendReply(FindPlayer(data.Target.ID), GetMessage("error_target_received_damage", this));
}
else {
SendReply(FindPlayer(data.Initiator.ID), GetMessage("error_target_received_damage", this));
SendReply(FindPlayer(data.Target.ID), GetMessage("error_player_received_damage", this));
}
CancelTTPRequest(victim.UserIDString);
}
if (IsAlreadyWait(attacker, false) || IsAlreadyWait(attacker, true)) {
try {
TeleportObject data = GetTeleportData(GetPlayerFromActive(attacker.UserIDString));
if (data == null) {
data = GetTeleportData(GetPlayerFromActive(attacker.UserIDString), false);
}
if(attacker.UserIDString == data.Initiator.ID) {
SendReply(FindPlayer(data.Initiator.ID), GetMessage("error_player_start_damage", this));
SendReply(FindPlayer(data.Target.ID), GetMessage("error_target_start_damage", this));
}
else {
SendReply(FindPlayer(data.Initiator.ID), GetMessage("error_target_start_damage", this));
SendReply(FindPlayer(data.Target.ID), GetMessage("error_player_start_damage", this));
}
CancelTTPRequest(attacker.UserIDString);
}
catch(Exception ex) {
PrintError(ex.Message);
}
}
if(IsWaitTeleportToHome(victim)) {
HomeTeleportObject obj = GetHomeObjectFromWaiters(victim.UserIDString);
SendReply(victim, GetMessage("error_tth_received_damage", this));
CancelTTHRequest(victim.UserIDString);
}
if(IsWaitTeleportToHome(attacker)) {
HomeTeleportObject obj = GetHomeObjectFromWaiters(attacker.UserIDString);
SendReply(attacker, GetMessage("error_tth_start_damage", this));
CancelTTHRequest(attacker.UserIDString);
}
}
object OnPlayerDie(BasePlayer player, HitInfo info) {
if (player == null) {
return null;
}
if (m_Config.AllowTeleportAfterDeath) {
return null;
}
if (IsAlreadyWait(player, false) || IsAlreadyWait(player, true)) {
TeleportObject data = GetTeleportData(GetPlayerFromActive(player.UserIDString));
if(data == null) {
data = GetTeleportData(GetPlayerFromActive(player.UserIDString), false);
}
SendReply(FindPlayer(data.Initiator.ID), GetMessage("error_player_is_death", this));
SendReply(FindPlayer(data.Target.ID), GetMessage("error_target_is_death", this));
CancelTTPRequest(player.UserIDString);
}
if (IsWaitTeleportToHome(player)) {
HomeTeleportObject obj = GetHomeObjectFromWaiters(player.UserIDString);
SendReply(player, GetMessage("error_tth_player_die", this));
CancelTTHRequest(player.UserIDString);
}
return null;
}
void OnEntityKill(BaseNetworkable entity) {
if(entity.ShortPrefabName.Contains("foundation")) {
RaycastHit hit;
if (Physics.Raycast(entity.transform.position, Vector3.up, out hit)) {
BaseEntity bagEntity = hit.GetEntity();
if (bagEntity != null) {
if(bagEntity as SleepingBag) {
string name = string.Empty;
foreach(var player in m_ActivePlayers) {
if(bagEntity.OwnerID == FindPlayer(player.Value.ID).userID) {
bagEntity.Kill();
break;
}
}
}
}
}
}
return;
}
void OnEntityDeath(BaseCombatEntity entity, HitInfo info) {
if (entity is SleepingBag) {
SleepingBag bagEntity = (SleepingBag)entity;
string name = string.Empty;
foreach (var player in m_ActivePlayers) {
if (bagEntity.OwnerID == FindPlayer(player.Value.ID).userID) {
if (player.Value.Homes.Any((x) => x.Value.Position == bagEntity.transform.position)) {
if (IsWaitTeleportToHome(FindPlayer(player.Value.ID))) {
CancelTTHRequest(player.Key);
}
var finded = player.Value.Homes.Where((x) => x.Value.Position == bagEntity.transform.position)?.First();
if (finded == null) {
return;
}
name = finded.Value.Value?.Name;
if (name == null) {
return;
}
bagEntity.enabled = false;
bagEntity.enableSaving = false;
bagEntity.Kill();
player.Value.RemoveHome(name);
SendReply(FindPlayer(player.Value.ID), GetMessage("info_home_destroyed", this));
break;
}
}
}
}
}
object CanRenameBed(BasePlayer player, SleepingBag bed, string bedName) {
if(bed.OwnerID != player.userID) {
SendReply(player, GetMessage("error_rename_other_bags", this));
return player;
}
return null;
}
bool CanBeWounded(BasePlayer player, HitInfo info) {
if (player == null) return false;
if (m_Config.AllowTeleportInWounded) return false;
if(IsAlreadyWait(player, true) || IsAlreadyWait(player, false)) {
var data = GetTeleportData(GetPlayerFromActive(player.UserIDString));
if(data == null) {
data = GetTeleportData(GetPlayerFromActive(player.UserIDString), false);
}
SendReply(player, GetMessage("error_ttp_cancelled_player_after_wounded", this));
SendReply(FindPlayer(data.Target.ID), GetMessage("error_ttp_cancelled_target_after_wounded", this));
CancelTTPRequest(player.UserIDString);
}
if(IsWaitTeleportToHome(player)) {
SendReply(player, GetMessage("error_tth_cancelled_after_wounded", this));
CancelTTHRequest(player.UserIDString);
}
return false;
}
bool CanPickupEntity(BasePlayer basePlayer, BaseCombatEntity entity) {
if (basePlayer == null) return true;
if (entity as SleepingBag) {
if(entity.OwnerID != basePlayer.userID) {
SendReply(basePlayer, GetMessage("error_pickup_other_bag", this));
return false;
}
string name = string.Empty;
foreach (var player in m_ActivePlayers) {
if (entity.OwnerID == FindPlayer(player.Value.ID).userID) {
if (player.Value.Homes.Any((x) => x.Value.Position == entity.transform.position)) {
var temp = player.Value.Homes.Where((x) => x.Value.Position == entity.transform.position)?.First();
if (temp == null) {
return false;
}
name = temp.Value.Value.Name;
SendReply(basePlayer, GetMessage("error_pickup_registered_home", this));
return fa
// ... [Code preview truncated due to length. Full source in attached file] ...