C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
// #define DEBUG
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Facepunch;
using Network;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust;
using Rust;
using Rust.Modular;
using UnityEngine;
using Debug = UnityEngine.Debug;
using Random = UnityEngine.Random;
// TODO: Fix mincopters spawning above user.namespace Oxide.Plugins
{
[Info("Vehicle Licence", "Sorrow/TheDoc/Arainrr", "1.8.5")]
[Description("Allows players to buy vehicles and then spawn or store it")]
public class VehicleLicence : RustPlugin {
#region Fields
[PluginReference]
private readonly Plugin Economics, ServerRewards, Friends, Clans, NoEscape, LandOnCargoShip, RustTranslationAPI, ZoneManager;
private readonly string PERMISSION_USE = "vehiclelicence.use";
private readonly string PERMISSION_ALL = "vehiclelicence.all";
private readonly string PERMISSION_ADMIN = "vehiclelicence.admin";
private readonly string PERMISSION_BYPASS_COST = "vehiclelicence.bypasscost";
private readonly string PERMISSION_NO_DAMAGE = "vehiclelicence.nodamage";
private readonly string PERMISSION_NO_COLLISION_DAMAGE = "vehiclelicence.nocollisiondamage";
private const int ITEMID_FUEL = -946369541;
private const int ITEMID_HOTAIRBALLOON_ARMOR = -1989600732;
private const string PREFAB_ITEM_DROP = "assets/prefabs/misc/item drop/item_drop.prefab";
//BIKES
private const string PREFAB_PEDALBIKE = "assets/content/vehicles/bikes/pedalbike.prefab";
private const string PREFAB_PEDALTRIKE = "assets/content/vehicles/bikes/pedaltrike.prefab";
private const string PREFAB_MOTORBIKE = "assets/content/vehicles/bikes/motorbike.prefab";
private const string PREFAB_MOTORBIKE_SIDECAR = "assets/content/vehicles/bikes/motorbike_sidecar.prefab";
//OTHER
private const string PREFAB_TUGBOAT = "assets/content/vehicles/boats/tugboat/tugboat.prefab";
private const string PREFAB_ROWBOAT = "assets/content/vehicles/boats/rowboat/rowboat.prefab";
private const string PREFAB_RHIB = "assets/content/vehicles/boats/rhib/rhib.prefab";
private const string PREFAB_SEDAN = "assets/content/vehicles/sedan_a/sedantest.entity.prefab";
private const string PREFAB_HOTAIRBALLOON = "assets/prefabs/deployable/hot air balloon/hotairballoon.prefab";
private const string PREFAB_MINICOPTER = "assets/content/vehicles/minicopter/minicopter.entity.prefab";
private const string PREFAB_ATTACKHELICOPTER = "assets/content/vehicles/attackhelicopter/attackhelicopter.entity.prefab";
private const string PREFAB_TRANSPORTCOPTER = "assets/content/vehicles/scrap heli carrier/scraptransporthelicopter.prefab";
private const string PREFAB_CHINOOK = "assets/prefabs/npc/ch47/ch47.entity.prefab";
private const string PREFAB_RIDABLEHORSE = "assets/rust.ai/nextai/testridablehorse.prefab";
private const string PREFAB_WORKCART = "assets/content/vehicles/trains/workcart/workcart.entity.prefab";
private const string PREFAB_SEDANRAIL = "assets/content/vehicles/sedan_a/sedanrail.entity.prefab";
private const string PREFAB_MAGNET_CRANE = "assets/content/vehicles/crane_magnet/magnetcrane.entity.prefab";
private const string PREFAB_SUBMARINE_DUO = "assets/content/vehicles/submarine/submarineduo.entity.prefab";
private const string PREFAB_SUBMARINE_SOLO = "assets/content/vehicles/submarine/submarinesolo.entity.prefab";
private const string PREFAB_CHASSIS_SMALL = "assets/content/vehicles/modularcar/car_chassis_2module.entity.prefab";
private const string PREFAB_CHASSIS_MEDIUM = "assets/content/vehicles/modularcar/car_chassis_3module.entity.prefab";
private const string PREFAB_CHASSIS_LARGE = "assets/content/vehicles/modularcar/car_chassis_4module.entity.prefab";
private const string PREFAB_SNOWMOBILE = "assets/content/vehicles/snowmobiles/snowmobile.prefab";
private const string PREFAB_SNOWMOBILE_TOMAHA = "assets/content/vehicles/snowmobiles/tomahasnowmobile.prefab";
// Train Engine
private const string PREFAB_TRAINENGINE = "assets/content/vehicles/trains/workcart/workcart_aboveground.entity.prefab";
private const string PREFAB_TRAINENGINE_COVERED = "assets/content/vehicles/trains/workcart/workcart_aboveground2.entity.prefab";
private const string PREFAB_TRAINENGINE_LOCOMOTIVE = "assets/content/vehicles/trains/locomotive/locomotive.entity.prefab";
// Train Car
private const string PREFAB_TRAINWAGON_A = "assets/content/vehicles/trains/wagons/trainwagona.entity.prefab";
private const string PREFAB_TRAINWAGON_B = "assets/content/vehicles/trains/wagons/trainwagonb.entity.prefab";
private const string PREFAB_TRAINWAGON_C = "assets/content/vehicles/trains/wagons/trainwagonc.entity.prefab";
private const string PREFAB_TRAINWAGON_UNLOADABLE = "assets/content/vehicles/trains/wagons/trainwagonunloadable.entity.prefab";
private const string PREFAB_TRAINWAGON_UNLOADABLE_FUEL = "assets/content/vehicles/trains/wagons/trainwagonunloadablefuel.entity.prefab";
private const string PREFAB_TRAINWAGON_UNLOADABLE_LOOT = "assets/content/vehicles/trains/wagons/trainwagonunloadableloot.entity.prefab";
private const string PREFAB_CABOOSE = "assets/content/vehicles/trains/caboose/traincaboose.entity.prefab";
// Defaults for Vehicle Modifications
private readonly float TUGBOAT_ENGINETHRUST = 200000f;
private readonly float HELICOPTER_LIFT = 0.25f;
private readonly Vector3 SCRAP_HELICOPTER_TORQUE = new Vector3(8000.0f, 8000.0f, 4000.0f);
private readonly Vector3 MINICOPTER_TORQUE = new Vector3(400.0f, 400.0f, 200.0f);
private readonly Vector3 ATTACK_HELICOPTER_TORQUE = new Vector3(8000.0f, 8000.0f, 5200.0f);
private const int LAYER_GROUND = Layers.Solid | Layers.Mask.Water;
private readonly object _false = false;
private bool finishedLoading = false;
public static VehicleLicence Instance {
get;
private set;
}
public readonly Dictionary<BaseEntity, Vehicle> vehiclesCache = new Dictionary<BaseEntity, Vehicle>();
public readonly Dictionary<string, BaseVehicleSettings> allVehicleSettings = new Dictionary<string, BaseVehicleSettings>();
public readonly Dictionary<string, string> commandToVehicleType = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
public enum NormalVehicleType {
Tugboat, Rowboat, RHIB, Sedan, HotAirBalloon, ArmoredHotAirBalloon, MiniCopter, AttackHelicopter, TransportHelicopter, Chinook, RidableHorse, WorkCart, SedanRail, MagnetCrane, SubmarineSolo, SubmarineDuo, Snowmobile, TomahaSnowmobile, PedalBike, PedalTrike, MotorBike, MotorBike_SideCar
}
[JsonConverter(typeof(StringEnumConverter))]
public enum ChassisType {
Small, Medium, Large
}
[JsonConverter(typeof(StringEnumConverter))]
public enum TrainComponentType {
Engine, CoveredEngine, Locomotive, WagonA, WagonB, WagonC, Unloadable, UnloadableLoot, UnloadableFuel, Caboose,
}
#endregion Fields
#region Oxide Hooks
private void Init() {
LoadData();
Instance = this;
permission.RegisterPermission(PERMISSION_USE, this);
permission.RegisterPermission(PERMISSION_ALL, this);
permission.RegisterPermission(PERMISSION_ADMIN, this);
permission.RegisterPermission(PERMISSION_BYPASS_COST, this);
permission.RegisterPermission(PERMISSION_NO_DAMAGE, this);
permission.RegisterPermission(PERMISSION_NO_COLLISION_DAMAGE, this);
foreach (NormalVehicleType value in Enum.GetValues(typeof(NormalVehicleType))) {
allVehicleSettings.Add(value.ToString(), GetBaseVehicleSettings(value));
}
foreach (var entry in configData.modularVehicles) {
allVehicleSettings.Add(entry.Key, entry.Value);
}
foreach (var entry in configData.trainVehicles) {
allVehicleSettings.Add(entry.Key, entry.Value);
}
foreach (var entry in allVehicleSettings) {
var settings = entry.Value;
if (settings.UsePermission && !string.IsNullOrEmpty(settings.Permission)) {
if (!permission.PermissionExists(settings.Permission, this)) {
permission.RegisterPermission(settings.Permission, this);
}
}
if (settings.UsePermission && !string.IsNullOrEmpty(settings.BypassCostPermission)) {
if (!permission.PermissionExists(settings.BypassCostPermission, this)) {
permission.RegisterPermission(settings.BypassCostPermission, this);
}
}
foreach (var perm in settings.CooldownPermissions.Keys) {
if (!permission.PermissionExists(perm, this)) {
permission.RegisterPermission(perm, this);
}
}
foreach (var command in settings.Commands) {
if (string.IsNullOrEmpty(command)) {
continue;
}
if (!commandToVehicleType.ContainsKey(command)) {
commandToVehicleType.Add(command, entry.Key);
}
else {
PrintError($"You have the same two commands({command}).");
}
if (configData.chat.useUniversalCommand) {
cmd.AddChatCommand(command, this, nameof(CmdUniversal));
}
if (!string.IsNullOrEmpty(configData.chat.customKillCommandPrefix)) {
cmd.AddChatCommand(configData.chat.customKillCommandPrefix + command, this, nameof(CmdCustomKill));
}
}
}
cmd.AddChatCommand(configData.chat.helpCommand, this, nameof(CmdLicenseHelp));
cmd.AddChatCommand(configData.chat.buyCommand, this, nameof(CmdBuyVehicle));
cmd.AddChatCommand(configData.chat.spawnCommand, this, nameof(CmdSpawnVehicle));
cmd.AddChatCommand(configData.chat.recallCommand, this, nameof(CmdRecallVehicle));
cmd.AddChatCommand(configData.chat.killCommand, this, nameof(CmdKillVehicle));
Unsubscribe(nameof(CanMountEntity));
Unsubscribe(nameof(OnEntityTakeDamage));
Unsubscribe(nameof(OnEntityDismounted));
Unsubscribe(nameof(OnEntityEnter));
Unsubscribe(nameof(CanLootEntity));
Unsubscribe(nameof(OnEntitySpawned));
Unsubscribe(nameof(OnRidableAnimalClaimed));
Unsubscribe(nameof(OnEngineStarted));
}
private void OnServerInitialized() {
ServerMgr.Instance.StartCoroutine(UpdatePlayerData(TimeEx.currentTimestamp));
if (configData.global.preventMounting) {
Subscribe(nameof(CanMountEntity));
}
if (configData.global.noDecay) {
Subscribe(nameof(OnEntityTakeDamage));
}
if (configData.global.preventDamagePlayer || configData.global.safeTrainDismount || configData.global.preventDamageNPCs) {
Subscribe(nameof(OnEntityEnter));
}
if (configData.global.preventLooting) {
Subscribe(nameof(CanLootEntity));
}
if (configData.global.autoClaimFromVendor) {
Subscribe(nameof(OnEntitySpawned));
Subscribe(nameof(OnRidableAnimalClaimed));
}
if (configData.global.checkVehiclesInterval > 0 && allVehicleSettings.Any(x => x.Value.WipeTime > 0)) {
Subscribe(nameof(OnEntityDismounted));
timer.Every(configData.global.checkVehiclesInterval, CheckVehicles);
}
else if (configData.normalVehicles.miniCopter.flyHackPause > 0 || configData.normalVehicles.transportHelicopter.flyHackPause > 0 || configData.normalVehicles.attackHelicopter.flyHackPause > 0) {
Subscribe(nameof(OnEntityDismounted));
}
if (configData.normalVehicles.miniCopter.instantTakeoff || configData.normalVehicles.attackHelicopter.instantTakeoff) {
Subscribe(nameof(OnEngineStarted));
}
}
private void Unload() {
if (!configData.global.storeVehicle) {
foreach (var entry in vehiclesCache) {
if (entry.Key != null && !entry.Key.IsDestroyed) {
RefundVehicleItems(entry.Value, isUnload : true);
entry.Key.Kill(BaseNetworkable.DestroyMode.Gib);
}
entry.Value.EntityId = 0;
}
}
SaveData();
Instance = null;
}
private void OnServerSave() {
timer.Once(Random.Range(0f, 60f), SaveData);
}
private void OnEntityDismounted(BaseMountable entity, BasePlayer player) {
if (entity == null) {
return;
}
if (player != null) {
BaseEntity vehicleEntity = entity.GetParentEntity();
if (configData.normalVehicles.miniCopter.flyHackPause > 0 && vehicleEntity is Minicopter) {
player.PauseFlyHackDetection(configData.normalVehicles.miniCopter.flyHackPause);
}
else if (configData.normalVehicles.transportHelicopter.flyHackPause > 0 && vehicleEntity is ScrapTransportHelicopter) {
player.PauseFlyHackDetection(configData.normalVehicles.transportHelicopter.flyHackPause);
}
else if (configData.normalVehicles.attackHelicopter.flyHackPause > 0 && vehicleEntity is AttackHelicopter) {
player.PauseFlyHackDetection(configData.normalVehicles.attackHelicopter.flyHackPause);
}
}
var vehicleParent = entity.VehicleParent();
if (vehicleParent == null || vehicleParent.IsDestroyed) {
return;
}
Vehicle vehicle;
if (!vehiclesCache.TryGetValue(vehicleParent, out vehicle)) {
return;
}
vehicle.OnDismount();
}
// TODO: Fix/finish
private void OnEngineStarted(BaseMountable entity, BasePlayer player) {
if (player == null || entity == null) return;
if (!permission.UserHasPermission(player.UserIDString, PERMISSION_USE)) return;
BaseVehicle mounted = player.GetMountedVehicle();
// Only allows vehicles spawned with the plugin to use instant take off.if (mounted == null || !vehiclesCache.ContainsKey(mounted)) return;
PlayerHelicopter heli = mounted as PlayerHelicopter;
NextTick(() => {
if (heli == null) return;
if (heli is Minicopter && configData.normalVehicles.miniCopter.instantTakeoff) {
heli.engineController.FinishStartingEngine();
return;
}
if (heli is AttackHelicopter && configData.normalVehicles.attackHelicopter.instantTakeoff) {
heli.engineController.FinishStartingEngine();
}
}
);
}
#region Mount
private object CanMountEntity(BasePlayer friend, BaseMountable entity) {
if (friend == null || entity == null) {
return null;
}
var vehicleParent = entity.VehicleParent();
if (vehicleParent == null || vehicleParent.IsDestroyed) {
return null;
}
Vehicle vehicle;
if (!vehiclesCache.TryGetValue(vehicleParent, out vehicle)) {
return null;
}
if (AreFriends(vehicle.PlayerId, friend.userID)) {
return null;
}
if (configData.global.preventDriverSeat && vehicleParent.HasMountPoints()) {
foreach (var mountPointInfo in vehicleParent.allMountPoints) {
if (mountPointInfo == null || mountPointInfo.mountable != entity) continue;
if (!mountPointInfo.isDriver) {
return null;
}
break;
}
}
if (HasAdminPermission(friend)) {
return null;
}
SendCantUseMessage(friend, vehicle);
return _false;
}
#endregion Mount
#region Loot
private object CanLootEntity(BasePlayer friend, RidableHorse horse) {
if (friend == null || horse == null) {
return null;
}
return CanLootEntityInternal(friend, horse);
}
private object CanLootEntity(BasePlayer friend, StorageContainer container) {
if (friend == null || container == null) return null;
var parentEntity = container.GetParentEntity();
if (parentEntity == null) return null;
return CanLootEntityInternal(friend, parentEntity);
}
private object CanLootEntityInternal(BasePlayer friend, BaseEntity parentEntity) {
Vehicle vehicle;
if (!TryGetVehicle(parentEntity, out vehicle)) {
return null;
}
if (AreFriends(vehicle.PlayerId, friend.userID)) return null;
if (HasAdminPermission(friend)) return null;
SendCantUseMessage(friend, vehicle);
return _false;
}
#endregion Loot
#region Decay
private void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo hitInfo) {
if (entity == null || hitInfo?.damageTypes == null) {
return;
}
Vehicle vehicle;
if (!TryGetVehicle(entity, out vehicle)) {
return;
}
if (permission.UserHasPermission(vehicle.PlayerId.ToString(), PERMISSION_NO_DAMAGE) && GetBaseVehicleDamage(vehicle.VehicleType)) {
hitInfo.damageTypes.ScaleAll(0);
return;
}
if (hitInfo.damageTypes.Has(DamageType.Collision) && permission.UserHasPermission(vehicle.PlayerId.ToString(), PERMISSION_NO_COLLISION_DAMAGE) && GetBaseVehicleCollisionDamage(vehicle.VehicleType)) {
hitInfo.damageTypes.Scale(DamageType.Collision, 0);
return;
}
if (!hitInfo.damageTypes.Has(DamageType.Decay)) return;
hitInfo.damageTypes.Scale(DamageType.Decay, 0);
}
#endregion Decay
#region Claim
private void OnEntitySpawned(Tugboat tugboat) {
TryClaimVehicle(tugboat);
}
private void OnEntitySpawned(BaseSubmarine baseSubmarine) {
TryClaimVehicle(baseSubmarine);
}
private void OnEntitySpawned(MotorRowboat motorRowboat) {
TryClaimVehicle(motorRowboat);
}
private void OnEntitySpawned(Minicopter miniCopter) {
TryClaimVehicle(miniCopter);
}
private void OnEntitySpawned(AttackHelicopter attackHelicopter) {
TryClaimVehicle(attackHelicopter);
}
private void OnRidableAnimalClaimed(BaseRidableAnimal ridableAnimal, BasePlayer player) {
TryClaimVehicle(ridableAnimal, player);
}
#endregion Claim
#region Damage
// ScrapTransportHelicopter / ModularCar / TrainEngine / MagnetCrane
private object OnEntityEnter(TriggerHurtNotChild triggerHurtNotChild, BasePlayer player) {
if (triggerHurtNotChild == null || player == null || triggerHurtNotChild.SourceEntity == null) {
return null;
}
var sourceEntity = triggerHurtNotChild.SourceEntity;
if (!vehiclesCache.ContainsKey(sourceEntity) || (!configData.global.preventDamageNPCs && !player.userID.IsSteamId())) return null;
var baseVehicle = sourceEntity as BaseVehicle;
if ((baseVehicle == null || player.userID.IsSteamId()) && configData.global.preventDamagePlayer) return _false;
if (configData.global.preventDamageNPCs && !player.userID.IsSteamId()) return _false;
if (baseVehicle is TrainEngine) {
if (!configData.global.safeTrainDismount && configData.global.preventDamagePlayer && player.userID.IsSteamId()) return _false;
if (!configData.global.safeTrainDismount) return null;
var transform = triggerHurtNotChild.transform;
MoveToPosition(player, transform.position + (Random.value >= 0.5f ? -transform.right : transform.right) * 2.5f);
return configData.global.preventDamagePlayer ? _false : null;
}
if (!configData.global.preventDamagePlayer) return null;
Vector3 pos;
if (GetDismountPosition(baseVehicle, player, out pos)) {
MoveToPosition(player, pos);
}
//triggerHurtNotChild.enabled = false;
return _false;
}
// HotAirBalloon
private object OnEntityEnter(TriggerHurt triggerHurt, BasePlayer player) {
if (triggerHurt == null || player == null) {
return null;
}
var sourceEntity = triggerHurt.gameObject.ToBaseEntity();
if (sourceEntity == null || !vehiclesCache.ContainsKey(sourceEntity)) return null;
if (configData.global.preventDamagePlayer && player.userID.IsSteamId() || (configData.global.preventDamageNPCs && !player.userID.IsSteamId())) {
MoveToPosition(player, sourceEntity.CenterPoint() + Vector3.down);
//triggerHurt.enabled = false;
return _false;
}
return null;
}
#endregion Damage
#region Destroy
private void OnEntityDeath(BaseCombatEntity entity, HitInfo info) {
OnEntityDeathOrKill(entity, true);
}
private void OnEntityKill(BaseCombatEntity entity) {
OnEntityDeathOrKill(entity);
}
#endregion Destroy
#region Reskin
private object OnEntityReskin(BaseEntity entity, ItemSkinDirectory.Skin skin, BasePlayer player) {
if (entity == null || player == null) {
return null;
}
Vehicle vehicle;
if (TryGetVehicle(entity, out vehicle)) {
return _false;
}
return null;
}
#endregion Reskin
#endregion Oxide Hooks
#region Methods
#region Message
private void SendCantUseMessage(BasePlayer friend, Vehicle vehicle) {
var settings = GetBaseVehicleSettings(vehicle.VehicleType);
if (settings != null) {
var player = RustCore.FindPlayerById(vehicle.PlayerId);
var playerName = player?.displayName ?? ServerMgr.Instance.persistance.GetPlayerName(vehicle.PlayerId) ?? "Unknown";
Print(friend, Lang("CantUse", friend.UserIDString, settings.DisplayName, $"<color=#{(player != null && player.IsConnected ? "69D214" : "FF6347")}>{playerName}</color>"));
}
}
#endregion Message
#region CheckEntity
private void OnEntityDeathOrKill(BaseCombatEntity entity, bool isCrash = false) {
if (entity == null) {
return;
}
Vehicle vehicle;
if (!vehiclesCache.TryGetValue(entity, out vehicle)) {
return;
}
RefundVehicleItems(vehicle, isCrash);
var settings = GetBaseVehicleSettings(vehicle.VehicleType);
if (isCrash && settings.RemoveLicenseOnceCrash) {
RemoveVehicleLicense(vehicle.PlayerId, vehicle.VehicleType);
}
vehicle.OnDeath();
vehiclesCache.Remove(entity);
}
#endregion CheckEntity
#region CheckVehicles
private void CheckVehicles() {
var currentTimestamp = TimeEx.currentTimestamp;
foreach (var entry in vehiclesCache.ToArray()) {
if (entry.Key == null || entry.Key.IsDestroyed) {
continue;
}
if (VehicleIsActive(entry.Key, entry.Value, currentTimestamp)) {
continue;
}
if (VehicleAnyMounted(entry.Key)) {
continue;
}
entry.Key.Kill(BaseNetworkable.DestroyMode.Gib);
}
}
private bool VehicleIsActive(BaseEntity entity, Vehicle vehicle, double currentTimestamp) {
var settings = GetBaseVehicleSettings(vehicle.VehicleType);
if (settings.WipeTime <= 0) {
return true;
}
if (settings.ExcludeCupboard && entity.GetBuildingPrivilege() != null) {
return true;
}
return currentTimestamp - vehicle.LastDismount < settings.WipeTime;
}
#endregion CheckVehicles
#region Refund
private void RefundVehicleItems(Vehicle vehicle, bool isCrash = false, bool isUnload = false) {
var entity = vehicle.Entity;
if (entity == null || entity.IsDestroyed) {
return;
}
var settings = GetBaseVehicleSettings(vehicle.VehicleType);
settings.RefundVehicleItems(vehicle, isCrash, isUnload);
}
private static void DropItemContainer(BaseEntity entity, ulong playerId, List<Item> collect) {
var droppedItemContainer = GameManager.server.CreateEntity(PREFAB_ITEM_DROP, entity.GetDropPosition(), entity.transform.rotation) as DroppedItemContainer;
if (droppedItemContainer != null) {
droppedItemContainer.inventory = new ItemContainer();
droppedItemContainer.inventory.ServerInitialize(null, Mathf.Min(collect.Count, droppedItemContainer.maxItemCount));
droppedItemContainer.inventory.GiveUID();
droppedItemContainer.inventory.entityOwner = droppedItemContainer;
droppedItemContainer.inventory.SetFlag(ItemContainer.Flag.NoItemInput, true);
for (var i = collect.Count - 1; i >= 0; i--) {
var item = collect[i];
if (!item.MoveToContainer(droppedItemContainer.inventory)) {
item.DropAndTossUpwards(droppedItemContainer.transform.position);
}
}
droppedItemContainer.OwnerID = playerId;
droppedItemContainer.Spawn();
}
}
#endregion Refund
#region TryPay
private bool TryPay(BasePlayer player, BaseVehicleSettings settings, Dictionary<string, PriceInfo> prices, out string resources) {
if (permission.UserHasPermission(player.UserIDString, PERMISSION_BYPASS_COST) || permission.UserHasPermission(player.UserIDString, settings.BypassCostPermission)) {
resources = null;
return true;
}
if (!CanPay(player, prices, out resources)) {
return false;
}
var collect = Pool.GetList<Item>();
foreach (var entry in prices) {
if (entry.Value.amount <= 0) {
continue;
}
var itemDefinition = ItemManager.FindItemDefinition(entry.Key);
if (itemDefinition != null) {
player.inventory.Take(collect, itemDefinition.itemid, entry.Value.amount);
player.Command("note.inv", itemDefinition.itemid, -entry.Value.amount);
continue;
}
switch (entry.Key.ToLower()) {
case "economics" : Economics?.Call("Withdraw", (ulong)player.userID, (double)entry.Value.amount);
continue;
case "serverrewards" : ServerRewards?.Call("TakePoints", (ulong)player.userID, entry.Value.amount);
continue;
}
}
foreach (var item in collect) {
item.Remove();
}
Pool.FreeList(ref collect);
resources = null;
return true;
}
private bool CanPay(BasePlayer player, Dictionary<string, PriceInfo> prices, out string resources) {
var entries = new Hash<string, int>();
var language = RustTranslationAPI != null ? lang.GetLanguage(player.UserIDString) : null;
foreach (var entry in prices) {
if (entry.Value.amount <= 0) {
continue;
}
int missingAmount;
var itemDefinition = ItemManager.FindItemDefinition(entry.Key);
if (itemDefinition != null) {
missingAmount = entry.Value.amount - player.inventory.GetAmount(itemDefinition.itemid);
}
else {
missingAmount = CheckBalance(entry.Key, entry.Value.amount, player.userID);
}
if (missingAmount <= 0) {
continue;
}
var displayName = GetItemDisplayName(language, entry.Key, entry.Value.displayName);
entries[displayName] += missingAmount;
}
if (entries.Count > 0) {
var stringBuilder = new StringBuilder();
foreach (var entry in entries) {
stringBuilder.AppendLine($"* {Lang("PriceFormat", player.UserIDString, entry.Key, entry.Value)}");
}
resources = stringBuilder.ToString();
return false;
}
resources = null;
return true;
}
private int CheckBalance(string key, int price, ulong playerId) {
switch (key.ToLower()) {
case "economics" : var balance = Economics?.Call("Balance", playerId);
if (balance is double) {
var n = price - (double)balance;
return n <= 0 ? 0 : (int)Math.Ceiling(n);
}
return price;
case "serverrewards" : var points = ServerRewards?.Call("CheckPoints", playerId);
if (points is int) {
var n = price - (int)points;
return n <= 0 ? 0 : n;
}
return price;
default : PrintError($"Unknown Currency Type '{key}'");
return price;
}
}
#endregion TryPay
#region AreFriends
private bool AreFriends(ulong playerId, ulong friendId) {
if (playerId == friendId) {
return true;
}
if (configData.global.useTeams && SameTeam(playerId, friendId)) {
return true;
}
if (configData.global.useFriends && HasFriend(playerId, friendId)) {
return true;
}
if (configData.global.useClans && SameClan(playerId, friendId)) {
return true;
}
return false;
}
private static bool SameTeam(ulong playerId, ulong friendId) {
if (!RelationshipManager.TeamsEnabled()) {
return false;
}
var playerTeam = RelationshipManager.ServerInstance.FindPlayersTeam(playerId);
if (playerTeam == null) {
return false;
}
var friendTeam = RelationshipManager.ServerInstance.FindPlayersTeam(friendId);
if (friendTeam == null) {
return false;
}
return playerTeam == friendTeam;
}
private bool HasFriend(ulong playerId, ulong friendId) {
if (Friends == null) {
return false;
}
return (bool)Friends.Call("HasFriend", playerId, friendId);
}
private bool SameClan(ulong playerId, ulong friendId) {
if (Clans == null) {
return false;
}
//Clans
var isMember = Clans.Call("IsClanMember", playerId.ToString(), friendId.ToString());
if (isMember != null) {
return (bool)isMember;
}
//Rust:IO Clans
var playerClan = Clans.Call("GetClanOf", playerId);
if (playerClan == null) {
return false;
}
var friendClan = Clans.Call("GetClanOf", friendId);
if (friendClan == null) {
return false;
}
return playerClan == friendClan;
}
#endregion AreFriends
#region IsPlayerBlocked
private bool IsPlayerBlocked(BasePlayer player) {
if (NoEscape == null) {
return false;
}
if (configData.global.useRaidBlocker && IsRaidBlocked(player.UserIDString)) {
Print(player, Lang("RaidBlocked", player.UserIDString));
return true;
}
if (configData.global.useCombatBlocker && IsCombatBlocked(player.UserIDString)) {
Print(player, Lang("CombatBlocked", player.UserIDString));
return true;
}
return false;
}
private bool IsRaidBlocked(string playerId) {
return (bool)NoEscape.Call("IsRaidBlocked", playerId);
}
private bool IsCombatBlocked(string playerId) {
return (bool)NoEscape.Call("IsCombatBlocked", playerId);
}
private bool InZone(BasePlayer player) {
if (ZoneManager == null || !ZoneManager.IsLoaded) return false;
return configData.AntiSpawnZones.Any(x => (bool)ZoneManager?.Call("PlayerHasFlag", player, x.ToLower()));
}
#endregion IsPlayerBlocked
#region GetSettings
private BaseVehicleSettings GetBaseVehicleSettings(string vehicleType) {
BaseVehicleSettings settings;
return allVehicleSettings.TryGetValue(vehicleType, out settings) ? settings : null;
}
private BaseVehicleSettings GetBaseVehicleSettings(NormalVehicleType normalVehicleType) {
switch (normalVehicleType) {
case NormalVehicleType.Tugboat : return configData.normalVehicles.tugboat;
case NormalVehicleType.Rowboat : return configData.normalVehicles.rowboat;
case NormalVehicleType.RHIB : return configData.normalVehicles.rhib;
case NormalVehicleType.Sedan : return configData.normalVehicles.sedan;
case NormalVehicleType.HotAirBalloon : return configData.normalVehicles.hotAirBalloon;
case NormalVehicleType.ArmoredHotAirBalloon : return configData.normalVehicles.armoredHotAirBalloon;
case NormalVehicleType.MiniCopter : return configData.normalVehicles.miniCopter;
case NormalVehicleType.AttackHelicopter : return configData.normalVehicles.attackHelicopter;
case NormalVehicleType.TransportHelicopter : return configData.normalVehicles.transportHelicopter;
case NormalVehicleType.Chinook : return configData.normalVehicles.chinook;
case NormalVehicleType.RidableHorse : return configData.normalVehicles.ridableHorse;
case NormalVehicleType.WorkCart : return configData.normalVehicles.workCart;
case NormalVehicleType.SedanRail : return configData.normalVehicles.sedanRail;
case NormalVehicleType.MagnetCrane : return configData.normalVehicles.magnetCrane;
case NormalVehicleType.SubmarineSolo : return configData.normalVehicles.submarineSolo;
case NormalVehicleType.SubmarineDuo : return configData.normalVehicles.submarineDuo;
case NormalVehicleType.Snowmobile : return configData.normalVehicles.snowmobile;
case NormalVehicleType.TomahaSnowmobile : return configData.normalVehicles.tomahaSnowmobile;
case NormalVehicleType.PedalBike : return configData.normalVehicles.pedalBike;
case NormalVehicleType.PedalTrike : return configData.normalVehicles.pedalTrike;
case NormalVehicleType.MotorBike : return configData.normalVehicles.motorBike;
case NormalVehicleType.MotorBike_SideCar : return configData.normalVehicles.motorBikeSidecar;
default : return null;
}
}
private bool GetBaseVehicleCollisionDamage(string vehicleType) {
BaseVehicleSettings settings;
return allVehicleSettings.TryGetValue(vehicleType, out settings) && settings.NoCollisionDamage;
}
// private bool GetBaseVehicleCollisionDamage(string vehicleType)
// {
// BaseVehicleSettings settings;
// return allVehicleSettings.TryGetValue(vehicleType, out settings) && settings.NoCollisionDamage;
// }
private bool GetBaseVehicleCollisionDamage(NormalVehicleType normalVehicleType) {
switch (normalVehicleType) {
case NormalVehicleType.Tugboat : return configData.normalVehicles.tugboat.NoCollisionDamage;
case NormalVehicleType.Rowboat : return configData.normalVehicles.rowboat.NoCollisionDamage;
case NormalVehicleType.RHIB : return configData.normalVehicles.rhib.NoCollisionDamage;
case NormalVehicleType.Sedan : return configData.normalVehicles.sedan.NoCollisionDamage;
case NormalVehicleType.HotAirBalloon : return configData.normalVehicles.hotAirBalloon.NoCollisionDamage;
case NormalVehicleType.ArmoredHotAirBalloon : return configData.normalVehicles.armoredHotAirBalloon.NoCollisionDamage;
case NormalVehicleType.MiniCopter : return configData.normalVehicles.miniCopter.NoCollisionDamage;
case NormalVehicleType.AttackHelicopter : return configData.normalVehicles.attackHelicopter.NoCollisionDamage;
case NormalVehicleType.TransportHelicopter : return configData.normalVehicles.transportHelicopter.NoCollisionDamage;
case NormalVehicleType.Chinook : return configData.normalVehicles.chinook.NoCollisionDamage;
case NormalVehicleType.RidableHorse : return configData.normalVehicles.ridableHorse.NoCollisionDamage;
case NormalVehicleType.WorkCart : return configData.normalVehicles.workCart.NoCollisionDamage;
case NormalVehicleType.SedanRail : return configData.normalVehicles.sedanRail.NoCollisionDamage;
case NormalVehicleType.MagnetCrane : return configData.normalVehicles.magnetCrane.NoCollisionDamage;
case NormalVehicleType.SubmarineSolo : return configData.normalVehicles.submarineSolo.NoCollisionDamage;
case NormalVehicleType.SubmarineDuo : return configData.normalVehicles.submarineDuo.NoCollisionDamage;
case NormalVehicleType.Snowmobile : return configData.normalVehicles.snowmobile.NoCollisionDamage;
case NormalVehicleType.TomahaSnowmobile : return configData.normalVehicles.tomahaSnowmobile.NoCollisionDamage;
case NormalVehicleType.PedalBike : return configData.normalVehicles.pedalBike.NoCollisionDamage;
case NormalVehicleType.PedalTrike : return configData.normalVehicles.pedalTrike.NoCollisionDamage;
case NormalVehicleType.MotorBike : return configData.normalVehicles.motorBike.NoCollisionDamage;
case NormalVehicleType.MotorBike_SideCar : return configData.normalVehicles.motorBikeSidecar.NoCollisionDamage;
default : return false;
}
}
private bool GetBaseVehicleDamage(string vehicleType) {
BaseVehicleSettings settings;
return allVehicleSettings.TryGetValue(vehicleType, out settings) && settings.NoDamage;
}
private bool GetBaseVehicleDamage(NormalVehicleType normalVehicleType) {
switch (normalVehicleType) {
case NormalVehicleType.Tugboat : return configData.normalVehicles.tugboat.NoDamage;
case NormalVehicleType.Rowboat : return configData.normalVehicles.rowboat.NoDamage;
case NormalVehicleType.RHIB : return configData.normalVehicles.rhib.NoDamage;
case NormalVehicleType.Sedan : return configData.normalVehicles.sedan.NoDamage;
case NormalVehicleType.HotAirBalloon : return configData.normalVehicles.hotAirBalloon.NoDamage;
case NormalVehicleType.ArmoredHotAirBalloon : return configData.normalVehicles.armoredHotAirBalloon.NoDamage;
case NormalVehicleType.MiniCopter : return configData.normalVehicles.miniCopter.NoDamage;
case NormalVehicleType.AttackHelicopter : return configData.normalVehicles.attackHelicopter.NoDamage;
case NormalVehicleType.TransportHelicopter : return configData.normalVehicles.transportHelicopter.NoDamage;
case NormalVehicleType.Chinook : return configData.normalVehicles.chinook.NoDamage;
case NormalVehicleType.RidableHorse : return configData.normalVehicles.ridableHorse.NoDamage;
case NormalVehicleType.WorkCart : return configData.normalVehicles.workCart.NoDamage;
case NormalVehicleType.SedanRail : return configData.normalVehicles.sedanRail.NoDamage;
case NormalVehicleType.MagnetCrane : return configData.normalVehicles.magnetCrane.NoDamage;
case NormalVehicleType.SubmarineSolo : return configData.normalVehicles.submarineSolo.NoDamage;
case NormalVehicleType.SubmarineDuo : return configData.normalVehicles.submarineDuo.NoDamage;
case NormalVehicleType.Snowmobile : return configData.normalVehicles.snowmobile.NoDamage;
case NormalVehicleType.TomahaSnowmobile : return configData.normalVehicles.tomahaSnowmobile.NoDamage;
case NormalVehicleType.PedalBike : return configData.normalVehicles.pedalBike.NoDamage;
case NormalVehicleType.PedalTrike : return configData.normalVehicles.pedalTrike.NoDamage;
case NormalVehicleType.MotorBike : return configData.normalVehicles.motorBike.NoDamage;
case NormalVehicleType.MotorBike_SideCar : return configData.normalVehicles.motorBikeSidecar.NoDamage;
default : return false;
}
}
#endregion GetSettings
#region Permission
private bool HasAdminPermission(BasePlayer player) {
return permission.UserHasPermission(player.UserIDString, PERMISSION_ADMIN);
}
private bool CanViewVehicleInfo(BasePlayer player, string vehicleType, BaseVehicleSettings settings) {
if (settings.Purchasable && settings.Commands.Count > 0) {
return HasVehiclePermission(player, vehicleType);
}
return false;
}
private bool HasVehiclePermission(BasePlayer player, string vehicleType) {
var settings = GetBaseVehicleSettings(vehicleType);
if (!settings.UsePermission || string.IsNullOrEmpty(settings.Permission)) {
return true;
}
return permission.UserHasPermission(player.UserIDString, PERMISSION_ALL) || permission.UserHasPermission(player.UserIDString, settings.Permission);
}
#endregion Permission
#region Claim
private void TryClaimVehicle(BaseVehicle baseVehicle) {
NextTick(() => {
if (baseVehicle == null) {
return;
}
var player = baseVehicle.creatorEntity as BasePlayer;
if (player == null || !player.userID.IsSteamId() || !baseVehicle.OnlyOwnerAccessible()) {
return;
}
var vehicleType = GetClaimableVehicleType(baseVehicle);
if (vehicleType.HasValue) {
TryClaimVehicle(player, baseVehicle, vehicleType.Value.ToString());
}
}
);
}
private void TryClaimVehicle(BaseVehicle baseVehicle, BasePlayer player) {
if (player == null || !player.userID.IsSteamId()) {
return;
}
var vehicleType = GetClaimableVehicleType(baseVehicle);
if (vehicleType.HasValue) {
TryClaimVehicle(player, baseVehicle, vehicleType.Value.ToString());
}
}
private bool TryClaimVehicle(BasePlayer player, BaseEntity entity, string vehicleType) {
Vehicle vehicle;
if (!storedData.IsVehiclePurchased(player.userID, vehicleType, out vehicle)) {
if (!configData.global.autoUnlockFromVendor) {
return false;
}
storedData.AddVehicleLicense(player.userID, vehicleType);
vehicle = storedData.GetVehicleLicense(player.userID, vehicleType);
}
if (vehicle.Entity == null || vehicle.Entity.IsDestroyed) {
var settings = GetBaseVehicleSettings(vehicle.VehicleType);
if (settings != null) {
settings.PreSetupVehicle(entity, vehicle, player);
settings.SetupVehicle(entity, vehicle, player, false);
}
CacheVehicleEntity(entity, vehicle, player);
return true;
}
return false;
}
#endregion Claim
private bool TryGetVehicle(BaseEntity entity, out Vehicle vehicle) {
if (!vehiclesCache.TryGetValue(entity, out vehicle)) {
var vehicleModule = entity as BaseVehicleModule;
if (vehicleModule == null) {
return false;
}
var parent = vehicleModule.Vehicle;
if (parent == null || !vehiclesCache.TryGetValue(parent, out vehicle)) {
return false;
}
}
return true;
}
private IEnumerator UpdatePlayerData(double currentTimestamp) {
foreach (var playerData in storedData.playerData) {
foreach (var entry in playerData.Value) {
entry.Value.PlayerId = playerData.Key;
entry.Value.VehicleType = entry.Key;
if (configData.global.storeVehicle) {
// ... [Code preview truncated due to length. Full source in attached file] ...