Иконка ресурса

FREE WoundedTrain : 1.2.0 1.2.0

Нет прав для скачивания
C#:
using Oxide.Core;
using Oxide.Core.Plugins;
using UnityEngine;
using System.Collections.Generic;

namespace Oxide.Plugins
{
    [Info("WoundedTrain", "Jess", "1.2.0")]
    [Description("Creates a human train that you can sit on and steer.")]
    public class WoundedTrain : RustPlugin
    {
        // --- Permissions & Config ---
        private const string PermUse = "woundedtrain.use";
        private const int TrainLength = 30; 
        private const float MoveSpeed = 30f; 
        private const float TurnSpeed = 15f; 
        
        // --- Data ---
        private List<BasePlayer> activeTrainNPCs = new List<BasePlayer>();
        private BaseEntity ghostEngine = null;
        private BaseMountable captainChair = null;
        private Timer controlTimer;
        
        // Input tracking
        private bool isMovingForward = false;
        private bool isTurningLeft = false;
        private bool isTurningRight = false;
        
        // --- Prefabs ---
        // UPDATED: Using the path you suggested
        private const string ScientistPrefab = "assets/content/vehicles/horse/horse.corpse.prefab";
        private const string GhostPrefab = "assets/prefabs/visualization/sphere.prefab"; 
        private const string ChairPrefab = "assets/prefabs/deployable/chair/chair.deployed.prefab";

        private void Init()
        {
            permission.RegisterPermission(PermUse, this);
        }

        private void Unload()
        {
            CleanupTrain();
        }

        object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info)
        {
            if (entity is BasePlayer player && activeTrainNPCs.Contains(player)) return true;
            if (entity == captainChair) return true; 
            return null;
        }

        object OnWoundedRecover(BasePlayer player)
        {
            if (activeTrainNPCs.Contains(player)) return true; 
            return null;
        }

        void OnPlayerInput(BasePlayer player, InputState input)
        {
            if (captainChair == null || !player.GetMounted() || player.GetMounted() != captainChair)
                return;

            isMovingForward = input.IsDown(BUTTON.FORWARD);
            isTurningLeft = input.IsDown(BUTTON.LEFT);
            isTurningRight = input.IsDown(BUTTON.RIGHT);
        }

        [ChatCommand("humantrain")]
        private void CmdHumanTrain(BasePlayer player, string command, string[] args)
        {
            if (!permission.UserHasPermission(player.UserIDString, PermUse))
            {
                SendReply(player, "No permission.");
                return;
            }

            CleanupTrain();
            Puts("Starting Human Train creation..."); // Debug Log

            // 1. Spawn the "Ghost Engine"
            Vector3 spawnPos = player.transform.position + (player.transform.forward * 3f);
            spawnPos.y = GetGroundY(spawnPos) + 0.5f; // Lift it slightly so it doesn't clip underground
            
            ghostEngine = GameManager.server.CreateEntity(GhostPrefab, spawnPos);
            if (ghostEngine == null)
            {
                Puts("ERROR: Could not spawn Ghost Engine!");
                return;
            }
            ghostEngine.Spawn();
            Puts("Ghost Engine Spawned.");

            // 2. Spawn the Captain's Chair
            SpawnChair(ghostEngine);

            // 3. Spawn the Line of Crawlers
            for (int i = 0; i < TrainLength; i++)
            {
                Vector3 offset = new Vector3(0, 0, -2f - (i * 1.5f)); 
                SpawnCrawler(ghostEngine, offset);
            }

            SendReply(player, "<color=#ff0000><b>[Killa Dome]</b></color> The Train is ready! Mount the chair to steer!");

            // 4. Start Physics Loop
            controlTimer = timer.Repeat(0.1f, -1, () =>
            {
                if (ghostEngine == null || ghostEngine.IsDestroyed) 
                {
                    CleanupTrain();
                    return;
                }

                if (isMovingForward)
                {
                    Vector3 currentPos = ghostEngine.transform.position;
                    Vector3 moveDir = ghostEngine.transform.forward * MoveSpeed * 0.1f;
                    Vector3 newPos = currentPos + moveDir;
                    newPos.y = GetGroundY(newPos) + 0.5f; // Keep it above ground
                    ghostEngine.transform.position = newPos;
                    ghostEngine.SendNetworkUpdate();
                }

                if (isTurningLeft)
                {
                    ghostEngine.transform.Rotate(Vector3.up, -TurnSpeed * 5f);
                    ghostEngine.SendNetworkUpdate();
                }
                else if (isTurningRight)
                {
                    ghostEngine.transform.Rotate(Vector3.up, TurnSpeed * 5f);
                    ghostEngine.SendNetworkUpdate();
                }
            });
        }

        [ChatCommand("finale")]
        private void CmdFinale(BasePlayer player, string command, string[] args)
        {
            if (activeTrainNPCs.Count == 0) return;

            if (controlTimer != null) controlTimer.Destroy();
            if (ghostEngine != null) ghostEngine.Kill(); 

            foreach (var npc in activeTrainNPCs)
            {
                if (npc == null) continue;

                npc.SetParent(null, true, true);

                Rigidbody rb = npc.GetComponent<Rigidbody>();
                if (rb != null)
                {
                    rb.isKinematic = false; 
                    rb.useGravity = true;
                    Vector3 randomSpread = UnityEngine.Random.onUnitSphere * 100f;
                    rb.AddForce(Vector3.up * 800f + randomSpread, ForceMode.Impulse); 
                }
                Effect.server.Run("assets/bundled/prefabs/fx/gestures/guitarpluck.prefab", npc.transform.position);
            }

            SendReply(player, "<color=orange>GRAND FINALE!</color>");
            timer.Once(5f, () => CleanupTrain());
        }

        private void SpawnChair(BaseEntity parent)
        {
            captainChair = GameManager.server.CreateEntity(ChairPrefab, parent.transform.position) as BaseMountable;
            if (captainChair == null)
            {
                Puts("ERROR: Could not spawn Chair!");
                return;
            }
            
            captainChair.SetParent(parent);
            captainChair.transform.localPosition = new Vector3(0, 0, 0); 
            captainChair.Spawn();
            Puts("Chair Spawned.");
        }

        private void SpawnCrawler(BaseEntity parent, Vector3 localPos)
        {
            var npc = GameManager.server.CreateEntity(ScientistPrefab, parent.transform.position) as BasePlayer;
            if (npc == null)
            {
                Puts($"ERROR: Could not spawn Scientist! Check Prefab Path: {ScientistPrefab}");
                return;
            }

            npc.Spawn();
            
            // Force Wounded
            npc.SetPlayerFlag(BasePlayer.PlayerFlags.Wounded, true);
            npc.health = 5f; 
            
            npc.SetParent(parent);
            npc.transform.localPosition = localPos;
            npc.transform.localRotation = Quaternion.Euler(0, 0, 0); 
            
            activeTrainNPCs.Add(npc);
        }

        private float GetGroundY(Vector3 pos)
        {
            RaycastHit hit;
            if (Physics.Raycast(new Vector3(pos.x, pos.y + 50f, pos.z), Vector3.down, out hit, 100f, LayerMask.GetMask("Terrain", "World", "Construction")))
            {
                return hit.point.y;
            }
            return pos.y; 
        }

        private void CleanupTrain()
        {
            if (controlTimer != null) controlTimer.Destroy();

            foreach (var npc in activeTrainNPCs)
            {
                if (npc != null && !npc.IsDestroyed) npc.Kill();
            }
            activeTrainNPCs.Clear();

            if (ghostEngine != null && !ghostEngine.IsDestroyed)
            {
                ghostEngine.Kill();
            }
        }
    }
}

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок
Сверху