C#:
using System.Collections.Generic;
using Oxide.Core;
using Network;
using Network.Visibility;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("AdminSleigh", "k1lly0u (control-fix)", "0.3.0")]
[Description("Admin Santa Sleigh with full manual control")]
class AdminSleigh : RustPlugin
{
private static AdminSleigh ins;
private const string SLEIGH_PREFAB = "assets/prefabs/misc/xmas/sleigh/santasleigh.prefab";
private const string CHAIR_PREFAB = "assets/prefabs/deployable/chair/chair.deployed.prefab";
private const string PERM_USE = "adminsleigh.use";
private readonly List<SleighController> controllers = new();
#region Oxide
private void Loaded()
{
ins = this;
permission.RegisterPermission(PERM_USE, this);
}
private void Unload()
{
foreach (var c in controllers)
UnityEngine.Object.Destroy(c);
controllers.Clear();
ins = null;
}
#endregion
#region Command
[ChatCommand("sleigh")]
private void SleighCmd(BasePlayer player)
{
if (!permission.UserHasPermission(player.UserIDString, PERM_USE))
{
player.ChatMessage("Нет прав");
return;
}
if (player.isMounted)
{
player.ChatMessage("Слезь с маунта");
return;
}
SpawnSleigh(player);
}
#endregion
#region Core
private void SpawnSleigh(BasePlayer player)
{
Vector3 pos = player.transform.position + player.eyes.BodyForward() * 3f;
pos.y = TerrainMeta.HeightMap.GetHeight(pos) + SantaSleigh.altitudeAboveTerrain;
BaseEntity ent = GameManager.server.CreateEntity(SLEIGH_PREFAB, pos);
ent.enableSaving = false;
ent.Spawn();
SleighController controller = ent.gameObject.AddComponent<SleighController>();
controller.Mount(player);
controllers.Add(controller);
}
#endregion
#region Controller
private class SleighController : MonoBehaviour
{
private SantaSleigh sleigh;
private BaseMountable seat;
private BasePlayer player;
private float speed;
private float rotation;
private const float MAX_SPEED = 7f;
private const float ACCEL = 0.25f;
private const float ROT_SPEED = 3f;
private void Awake()
{
sleigh = GetComponent<SantaSleigh>();
sleigh.enabled = false; // 🔥 важно
CreateSeat();
}
private void CreateSeat()
{
seat = GameManager.server.CreateEntity(CHAIR_PREFAB) as BaseMountable;
seat.enableSaving = false;
seat.isMobile = true;
seat.canWieldItems = false;
seat.Spawn();
Destroy(seat.GetComponent<GroundWatch>());
Destroy(seat.GetComponent<DestroyOnGroundMissing>());
seat.SetParent(sleigh, true);
seat.transform.localPosition = new Vector3(0f, 0.6f, -2.6f);
}
public void Mount(BasePlayer ply)
{
player = ply;
seat.MountPlayer(player);
InvokeRepeating(nameof(UpdateNetworkGroup), 0f, 1.5f);
player.ChatMessage(
"🎅 Управление санями:\n" +
"W / S — газ / тормоз\n" +
"A / D — поворот\n" +
"ЛКМ — подарок\n" +
"ПКМ — HO HO HO\n" +
"Прыжок — выйти"
);
}
private void FixedUpdate()
{
if (player == null) return;
float forward =
player.serverInput.IsDown(BUTTON.FORWARD) ? 1f :
player.serverInput.IsDown(BUTTON.BACKWARD) ? -1f : 0f;
float turn =
player.serverInput.IsDown(BUTTON.LEFT) ? -1f :
player.serverInput.IsDown(BUTTON.RIGHT) ? 1f : 0f;
if (forward != 0f)
speed = Mathf.Clamp(speed + (forward * ACCEL), 0f, MAX_SPEED);
else
speed = Mathf.Clamp(speed - ACCEL, 0f, MAX_SPEED);
rotation = Mathf.Lerp(rotation, turn * ROT_SPEED, Time.fixedDeltaTime);
sleigh.transform.Rotate(0f, rotation, 0f);
Vector3 target = sleigh.transform.position + sleigh.transform.forward * speed;
float terrain = TerrainMeta.HeightMap.GetHeight(target);
target.y = Mathf.Max(
SantaSleigh.desiredAltitude,
terrain + SantaSleigh.altitudeAboveTerrain
);
sleigh.transform.position = target;
}
private void Update()
{
if (player == null) return;
if (player.serverInput.WasJustPressed(BUTTON.JUMP))
Exit();
if (player.serverInput.WasJustPressed(BUTTON.FIRE_PRIMARY))
DropGift();
if (player.serverInput.WasJustPressed(BUTTON.FIRE_SECONDARY))
sleigh.ClientRPC(null, "ClientPlayHoHoHo");
}
private void DropGift()
{
Item item = ItemManager.CreateByName("xmas.present.small");
item?.Drop(
sleigh.transform.position + Vector3.down,
player.eyes.HeadForward() * 12f
);
}
private void Exit()
{
CancelInvoke(nameof(UpdateNetworkGroup));
if (player.isMounted)
seat.DismountPlayer(player);
Destroy(this);
}
private void UpdateNetworkGroup()
{
Group g = Net.sv.visibility.GetGroup(sleigh.transform.position);
sleigh.net.SwitchGroup(g);
seat.net.SwitchGroup(g);
player.net.SwitchGroup(g);
}
private void OnDestroy()
{
CancelInvoke(nameof(UpdateNetworkGroup));
if (player != null && player.isMounted)
seat.DismountPlayer(player);
seat?.Kill();
sleigh?.Kill();
}
}
#endregion
}
}