C#:
using System.Collections.Generic;
using Oxide.Core;
using Network;
using Network.Visibility;
using UnityEngine;
namespace Oxide.Plugins {
[Info("AdminSleigh", "k1lly0u", "0.1.2")]
class AdminSleigh : RustPlugin {
#region Fields
private static AdminSleigh ins;
private List<SleighController> controllers = new List<SleighController>();
private const string SLEIGH_ENTITY = "assets/prefabs/misc/xmas/sleigh/santasleigh.prefab";
private const string CHAIR_PREFAB = "assets/prefabs/deployable/chair/chair.deployed.prefab";
private const string ITEM_SMALLPRESENT = "xmas.present.small";
private const string ITEM_MEDIUMPRESENT = "xmas.present.medium";
private const string ITEM_LARGEPRESENT = "xmas.present.large";
#endregion
#region Oxide Hooks
private void Loaded() {
ins = this;
permission.RegisterPermission("adminsleigh.use", this);
lang.RegisterMessages(Messages, this);
}
private void OnEntityDismounted(BaseMountable mountable, BasePlayer player) {
SleighController controller = mountable.GetComponentInParent<SleighController>();
if (controller != null) {
controllers.Remove(controller);
UnityEngine.Object.Destroy(controller);
}
}
private void OnPlayerDisconnected(BasePlayer player) {
if (player.isMounted) {
BaseMountable mountable = player.GetMounted();
if (mountable != null) {
OnEntityDismounted(mountable, player);
}
}
}
private void Unload() {
for (int i = controllers.Count - 1; i >= 0; i--) UnityEngine.Object.Destroy(controllers[i]);
controllers.Clear();
ins = null;
}
#endregion
#region Functions
private void CreateSleigh(BasePlayer player) {
BaseEntity sleigh = GameManager.server.CreateEntity(SLEIGH_ENTITY, player.transform.position);
sleigh.enableSaving = false;
sleigh.Spawn();
SleighController controller = sleigh.gameObject.AddComponent<SleighController>();
controller.MountSleigh(player);
controllers.Add(controller);
}
#endregion
#region Controller
public enum LootType {
SmallPresent, MediumPresent, LargePresent, MassivePresent
}
private class SleighController : MonoBehaviour {
private SantaSleigh sleigh;
private BasePlayer player;
private BaseMountable mountable;
private LootType lootType = LootType.SmallPresent;
private float nextDropTime;
private float nextEffectTime;
private float nextLootCycleTime;
private float currentSpeed;
private float currentRotationSpeed;
private float acceleration = 0.25f;
private float maxSpeed = 5f;
private float maxRotationSpeed = 3f;
private float tiltForce;
private void Awake() {
sleigh = GetComponent<SantaSleigh>();
sleigh.enabled = false;
enabled = false;
CreateMountable();
}
private void FixedUpdate() {
if (player == null) return;
if (currentSpeed != 0) {
if (currentRotationSpeed != 0) {
float adjRotationSpeed = currentRotationSpeed * (currentSpeed / maxSpeed);
tiltForce = Mathf.Lerp(tiltForce, currentRotationSpeed * 4, Time.fixedDeltaTime);
sleigh.transform.rotation = sleigh.transform.rotation * Quaternion.Euler(0, adjRotationSpeed, 0);
sleigh.transform.localRotation = Quaternion.Euler(0, sleigh.transform.localEulerAngles.y, -tiltForce);
}
Vector3 target = sleigh.transform.position + (sleigh.transform.forward * currentSpeed);
float height = TerrainMeta.HeightMap.GetHeight(sleigh.transform.position + target);
float height1 = TerrainMeta.HeightMap.GetHeight(sleigh.transform.position);
float single2 = Mathf.Max(height, height1);
target.y = Mathf.Max(SantaSleigh.desiredAltitude, single2 + SantaSleigh.altitudeAboveTerrain);
sleigh.gameObject.transform.position = target;
sleigh.transform.hasChanged = true;
//player.SendNetworkUpdateImmediate();
}
}
private void LateUpdate() {
if (player == null) return;
if (player.serverInput.WasJustPressed(BUTTON.JUMP)) {
enabled = false;
player.DismountObject();
player.MovePosition(sleigh.transform.position);
player.SendNetworkUpdateImmediate(false);
player.ClientRPCPlayer(null, player, "ForcePositionTo", sleigh.transform.position);
mountable._mounted = null;
player.EnsureDismounted();
Interface.Call("OnEntityDismounted", mountable, player);
return;
}
float turn = player.serverInput.IsDown(BUTTON.LEFT) ? -1f : player.serverInput.IsDown(BUTTON.RIGHT) ? 1f : 0;
float forward = player.serverInput.IsDown(BUTTON.FORWARD) ? 1f : player.serverInput.IsDown(BUTTON.BACKWARD) ? -1f : 0;
if (forward > 0) currentSpeed = Mathf.Clamp(currentSpeed += (Time.fixedDeltaTime * acceleration), 0, maxSpeed);
else if (forward < 0) currentSpeed = Mathf.Clamp(currentSpeed -= Time.fixedDeltaTime, 0, maxSpeed);
else currentSpeed = Mathf.Clamp(currentSpeed -= (Time.fixedDeltaTime * acceleration), 0, maxSpeed);
if (turn > 0) currentRotationSpeed = Mathf.Clamp(currentRotationSpeed += (Time.fixedDeltaTime * maxRotationSpeed), -maxRotationSpeed, maxRotationSpeed);
else if (turn < 0) currentRotationSpeed = Mathf.Clamp(currentRotationSpeed -= (Time.fixedDeltaTime * maxRotationSpeed), -maxRotationSpeed, maxRotationSpeed);
else currentRotationSpeed = Mathf.Clamp(currentRotationSpeed > 0 ? currentRotationSpeed -= Time.fixedDeltaTime : currentRotationSpeed += Time.fixedDeltaTime, -maxRotationSpeed, maxRotationSpeed);
if (player.serverInput.WasJustReleased(BUTTON.FIRE_PRIMARY)) DropPresent();
if (player.serverInput.WasJustPressed(BUTTON.FIRE_SECONDARY)) PlayEffects();
if (player.serverInput.WasJustPressed(BUTTON.RELOAD)) CycleLootType();
}
private void OnDestroy() {
if (player != null) player.DismountObject();
if (mountable != null && !mountable.IsDestroyed) mountable.Kill();
if (sleigh != null && !sleigh.IsDestroyed) sleigh.Kill();
}
private void CreateMountable() {
mountable = GameManager.server.CreateEntity(CHAIR_PREFAB, sleigh.transform.position) as BaseMountable;
mountable.enableSaving = false;
mountable.pickup.enabled = false;
mountable.skinID = (ulong)1169930802;
mountable.Spawn();
mountable.maxMountDistance = 2f;
mountable.isMobile = true;
mountable.canWieldItems = false;
Destroy(mountable.GetComponent<DestroyOnGroundMissing>());
Destroy(mountable.GetComponent<GroundWatch>());
mountable.GetComponent<MeshCollider>().convex = true;
mountable.SetParent(sleigh);
mountable.transform.localPosition = new Vector3(0f, 0.34f, -3.3f);
mountable.transform.localRotation = Quaternion.Euler(0, 0, 0);
}
public void MountSleigh(BasePlayer player) {
this.player = player;
sleigh.CancelInvoke(sleigh.SendHoHoHo);
Vector3 spawnPosition = new Vector3(player.transform.position.x, TerrainMeta.HeightMap.GetHeight(player.transform.position) + SantaSleigh.altitudeAboveTerrain, player.transform.position.z);
sleigh.transform.position = spawnPosition;
player.MountObject(mountable);
enabled = true;
sleigh.enabled = false;
player.ChatMessage(msg("Help.Controls", player.userID));
InvokeHandler.InvokeRepeating(this, UpdateNetworkGroup, 0, 1.5f);
}
private void UpdateNetworkGroup() {
Group group = Net.sv.visibility.GetGroup(sleigh.transform.position);
if (mountable?.net?.group != group) mountable.net.SwitchGroup(group);
if (player?.net?.group != group) player.net.SwitchGroup(group);
}
private void CycleLootType() {
float time = Time.realtimeSinceStartup;
if (nextLootCycleTime > time) return;
int nextType = (int)lootType + 1;
if (nextType > 3) nextType = 0;
lootType = (LootType)nextType;
player.ChatMessage(string.Format(msg("Msg.LootTypeChanged", player.userID), lootType));
nextLootCycleTime = time + 0.25f;
}
private void DropPresent() {
float time = Time.realtimeSinceStartup;
if (nextDropTime > time) return;
Item item = null;
switch (lootType) {
case LootType.SmallPresent : item = ItemManager.CreateByName(ITEM_SMALLPRESENT);
item.Drop(mountable.transform.position + (Vector3.up * 1.25f), player.eyes.HeadForward() * 15f);
break;
case LootType.MediumPresent : item = ItemManager.CreateByName(ITEM_MEDIUMPRESENT);
item.Drop(mountable.transform.position + (Vector3.up * 1.25f), player.eyes.HeadForward() * 15f);
break;
case LootType.LargePresent : item = ItemManager.CreateByName(ITEM_LARGEPRESENT);
item.Drop(mountable.transform.position + (Vector3.up * 1.25f), player.eyes.HeadForward() * 15f);
break;
case LootType.MassivePresent : BaseEntity baseEntity = GameManager.server.CreateEntity(sleigh.prefabDrop.resourcePath, sleigh.dropOrigin.transform.position, sleigh.transform.rotation, true);
if (baseEntity) {
baseEntity.globalBroadcast = true;
baseEntity.Spawn();
}
break;
}
player.ChatMessage(string.Format(msg("Msg.PresentDropped", player.userID), lootType));
nextDropTime = time + 0.25f;
}
private void PlayEffects() {
float time = Time.realtimeSinceStartup;
if (nextEffectTime > time) return;
sleigh.ClientRPC(null, "ClientPlayHoHoHo");
nextEffectTime = time + 5f;
}
}
#endregion
#region Commands
[ChatCommand("sleigh")]
private void cmdSleigh(BasePlayer player, string command, string[] args) {
if (!permission.UserHasPermission(player.UserIDString, "adminsleigh.use")) {
SendReply(player, msg("Error.NoPermission", player.userID));
return;
}
if (player.isMounted) {
SendReply(player, msg("Error.Mounted", player.userID));
return;
}
CreateSleigh(player);
}
#endregion
#region Localization
private static string msg(string key, ulong playerId = 0U) => ins.lang.GetMessage(key, ins, playerId == 0U ? null : playerId.ToString());
private Dictionary<string, string> Messages = new Dictionary<string, string> {
["Msg.LootTypeChanged"]
= "You have changed loot drop to <color=#ce422b>{0}</color>", ["Msg.PresentDropped"] = "You just dropped a <color=#ce422b>{0}</color>", ["Error.NoPermission"] = "You do not have permission to use this command", ["Error.Mounted"] = "You can not ride a sleigh when your are mounted", ["Help.Controls"] = "-- <color=#ce422b>AdminSleigh</color> - Controls --\n<color=#ce422b>Forward/Backward</color> - Accelerate and brake\n<color=#ce422b>Left/Right</color> - Turn Left and right\n<color=#ce422b>Fire1</color> - Drop Gift\n<color=#ce422b>Fire2</color> - Play Sound Effect\n<color=#ce422b>Jump</color> - Exit Sleigh\n<color=#ce422b>Reload</color> - Switch loot drop type"
}
;
#endregion
}
}