C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
#if REIGNOFKINGS
using CodeHatch;
using CodeHatch.Engine.Networking;
#endif
using Oxide.Core.Libraries.Covalence;
using System.Collections.Generic;
using System.Linq;
#if HURTWORLD || REIGNOFKINGS || RUST || THEFOREST
using UnityEngine;
#endif
#if HURTWORLD
using uLink;
#endif
// TODO: Protect players from damage (in all games) until second after teleporting
namespace Oxide.Plugins
{
[Info("Portgun", "Wulf/lukespragg", "3.3.2")]
[Description("Teleports players with permission to object or terrain they are looking at")]
public class Portgun : CovalencePlugin
{
#region Localization
private new void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
["CommandPort"] = "port",
["NoDestination"] = "Could not find a valid destination to port to",
["NotAllowed"] = "You are not allowed to use the '{0}' command",
["OutOfBounds"] = "The location you're aiming at is outside the map's boundaries",
["PlayersOnly"] = "Command '{0}' can only be used by a player"
}, this);
}
#endregion Localization
#region Initialization
private readonly HashSet<string> protection = new HashSet<string>();
private const string permUse = "portgun.use";
private float mapSize;
private int layers;
private void OnServerInitialized()
{
permission.RegisterPermission(permUse, this);
AddCovalenceCommand("portgun", "PortCommand");
AddLocalizedCommand("CommandPort", "PortCommand");
#if HURTWORLD
layers = LayerMaskManager.TerrainConstructionsMachines;
#elif REIGNOFKINGS
layers = LayerMask.GetMask("Cubes", "Environment", "Terrain");
#elif RUST
mapSize = TerrainMeta.Size.x / 2;
layers = LayerMask.GetMask("Construction", "Default", "Deployed", "Resource", "Terrain", "Water", "World");
#elif THEFOREST
layers = 67108864;
#endif
}
#endregion Initialization
#region Port Command
private void PortCommand(IPlayer player, string command, string[] args)
{
if (player.IsServer)
{
player.Reply(Lang("PlayersOnly", player.Id, command));
return;
}
if (!player.HasPermission(permUse))
{
player.Reply(Lang("NotAllowed", player.Id, command));
return;
}
#if HURTWORLD || REIGNOFKINGS || RUST || THEFOREST
RaycastHit hit = new RaycastHit();
#endif
#if HURTWORLD
EntityReferenceCache entity = (player.Object as PlayerSession).WorldPlayerEntity;
CamData simData = entity.GetComponent<PlayerStatManager>().RefCache.PlayerCamera.SimData;
CharacterController controller = entity.GetComponent<CharacterController>();
Vector3 point1 = simData.FirePositionWorldSpace + controller.center + Vector3.up * -controller.height * 0.5f;
Vector3 point2 = point1 + Vector3.up * controller.height;
Vector3 direction = simData.FireRotationWorldSpace * Vector3.forward;
if (!Physics.CapsuleCast(point1, point2, controller.radius, direction, out hit, float.MaxValue, layers))
#elif REIGNOFKINGS
CodeHatch.Engine.Core.Cache.Entity entity = (player.Object as Player).Entity;
if (!Physics.Raycast(entity.Position, entity.GetOrCreate<LookBridge>().Forward, out hit, float.MaxValue, layers))
#elif RUST
BasePlayer basePlayer = player.Object as BasePlayer;
if (basePlayer != null && !Physics.Raycast(basePlayer.eyes.HeadRay(), out hit, float.MaxValue, layers))
#elif THEFOREST
BoltEntity entity = player.Object as BoltEntity;
Physics.Raycast(entity.transform.position, entity.transform.rotation * Vector3.forward, out hit, float.MaxValue, layers);
if (hit.collider != null && !hit.collider.CompareTag("TerrainMain") && !hit.collider.CompareTag("structure"))
#endif
{
player.Reply(Lang("NoDestination", player.Id));
return;
}
#if HURTWORLD
Vector3 safePos = simData.FirePositionWorldSpace + direction * hit.distance;
GenericPosition destination = new GenericPosition(safePos.x, safePos.y, safePos.z);
#elif REIGNOFKINGS || RUST || THEFOREST
GenericPosition destination = new GenericPosition(hit.point.x, hit.point.y, hit.point.z);
#else
GenericPosition destination = new GenericPosition();
#endif
if (!IsValidMapCoordinates(destination.X, destination.Y, destination.Z))
{
player.Reply(Lang("OutOfBounds", player.Id));
return;
}
#if DEBUG
player.Reply($"Current position: {player.Position()}");
player.Reply($"Destination: {destination}");
#endif
protection.Add(player.Id); // TODO: Remove to reset before adding if using timer?
player.Teleport(destination.X, destination.Y, destination.Z);
}
#endregion Port Command
#region Damage Protection
#if HURTWORLD
private void OnPlayerTakeDamage(PlayerSession session, EntityEffectSourceData source)
{
string id = session.SteamId.ToString();
if (protection.Contains(id))
{
source.Value = 0f;
timer.Once(10f, () => protection.Remove(id)); // TODO: Detect ground instead of timer
}
}
#elif RUST
private void OnEntityTakeDamage(BaseEntity entity, HitInfo info)
{
BasePlayer basePlayer = entity as BasePlayer;
if (basePlayer != null && protection.Contains(basePlayer.UserIDString))
{
info.damageTypes = new Rust.DamageTypeList();
info.HitMaterial = 0;
info.PointStart = Vector3.zero;
timer.Once(10f, () => protection.Remove(basePlayer.UserIDString)); // TODO: Detect ground instead of timer
}
}
#endif
#endregion Damage Protection
#region Helpers
private bool IsValidMapCoordinates(float x, float y, float z)
{
#if RUST
return x <= mapSize && x >= -mapSize && y < 2000 && y >= -100 && z <= mapSize && z >= -mapSize;
#else
return true; // Return true for unsupported games
#endif
}
private void AddLocalizedCommand(string key, string command)
{
foreach (string language in lang.GetLanguages(this))
{
Dictionary<string, string> messages = lang.GetMessages(language, this);
foreach (KeyValuePair<string, string> message in messages.Where(m => m.Key.Equals(key)))
{
if (!string.IsNullOrEmpty(message.Value))
{
AddCovalenceCommand(message.Value, command);
}
}
}
}
private string Lang(string key, string id = null, params object[] args)
{
return string.Format(lang.GetMessage(key, this, id), args);
}
#endregion Helpers
}
}