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

FREE MiniCopterDrone : 1.2.2 1.2.2

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Plugins;
using Oxide.Core.Libraries.Covalence;
using System.Linq;
using System.Collections.Generic;
using Newtonsoft.Json;
using System.Text.RegularExpressions;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("Minicopter Drone", "Andrew", "1.2.2")]
    [Description("Turns the minicopter into a programmable drone")]
    public class MiniCopterDrone : RustPlugin {
        static MiniCopterDrone plugin = null;
        DroneManager droneManager = null;
        static ConfigData config;
        static Compiler compiler = null;
        const string calibratePerm = "minicopterdrone.calibrate.allowed";
        const int maxAvgCharsPerLine = 32;

        class ConfigData {
            [JsonProperty(PropertyName = "maxProgramInstructions")]
            public int maxProgramInstructions;
            [JsonProperty(PropertyName = "gridPositionCorrection")]
            public Vector3 gridPositionCorrection;
            [JsonProperty(PropertyName = "maxInstructionsPerCycle")]
            public int maxInstructionsPerCycle;
            [JsonProperty(PropertyName = "gridSize")]
            public float gridSize;
            [JsonProperty(PropertyName = "droneCPUFreq")]
            public float droneCPUFreq;
        }

        protected override void LoadDefaultMessages() {
            lang.RegisterMessages(new Dictionary<string, string> {
                ["must_run_as_player"] = "this command must be run as a player",
                //["need_calibrate_perm"] = "error: you need the {0} permission to use this command",
                ["grid_pos_corr_saved"] = "grid position correction saved",
                ["calibrate_invalid_arg"] = "invalid argument format <grid_col><grid_row> ex: J13",
                ["var_already_declared"] = "line {0}: variable already declared ({1})",
                ["invalid_label"] = "line {0}: invalid label ({1})",
                ["var_not_declared"] = "line {0}: variable has not been declared ({1})",
                ["incompat_arg_type"] = "line {0}: incompatible argument type ({1}:{2}) for instruction ({3})",
                ["invalid_arg"] = "line {0}: invalid argument ({1}) for ({2}) spec: {2} {3}",
                ["invalid_instruction"] = "line {0}: invalid instruction ({1})",
                ["wrong_num_args"] = "line {0}: wrong number of arguments for ({1}) spec: {1} {2}",
                ["over_char_limit"] = "max program length is {0} characters",
                ["over_instruction_limit"] = "max program length is {0} instructions",
                ["compiler_error"] = "[error] {0}",
                ["no_prefab"] = "Error creating prefab \"{0}\""
            }, this);
        }

        protected override void LoadDefaultConfig() {
            var config = new ConfigData {
                maxProgramInstructions = 512,
                gridPositionCorrection = new Vector3(1, 0, 75),
                maxInstructionsPerCycle = 32,
                gridSize = 146.33f,
                droneCPUFreq = 10
            };

            Config.WriteObject(config, true);
        }

        void Init() {
            config = Config.ReadObject<ConfigData>();
            plugin = this;
            compiler = new Compiler();
            AddCovalenceCommand("minicopterdrone.calibrate", nameof(Calibrate), calibratePerm);
        }

        void Calibrate(IPlayer player, string command, string[] args) {
            if(player.Object == null) {
                Puts(lang.GetMessage("must_run_as_player", this));
                return;
            }

            Vector3 pos;
            if(args.Length == 1 && TryMapGridToPosition(args[0], out pos, false)) {
                var basePlayer = player.Object as BasePlayer;
                var actualPos = basePlayer.transform.position;
                config.gridPositionCorrection = new Vector3(actualPos.x, 0, actualPos.z) - pos;
                Config.WriteObject(config, true);
                player.Reply(lang.GetMessage("grid_pos_corr_saved", this, player.Id));
            } else {
                player.Reply(lang.GetMessage("calibrate_invalid_arg", this, player.Id));
            }
        }

        static void Print(string str) {
            Interface.Oxide.LogInfo(str, new object[]{});
        }

        class DroneManager : MonoBehaviour {
            public const string Guid = "918729b6-ca44-46c6-8ad6-1722abff10d4";
            Dictionary<uint, Drone> drones = new Dictionary<uint, Drone>();

            public static HashSet<int> activeFrequencies = new HashSet<int>();
            public static HashSet<int> risingEdgeFrequencies = new HashSet<int>();
            public static HashSet<int> fallingEdgeFrequencies = new HashSet<int>();
            List<int> removeActiveList = new List<int>();
            List<uint> removeDroneList = new List<uint>();

            public void Init() {
                float period = 1.0f / config.droneCPUFreq;
                InvokeRepeating(nameof(CycleDroneCPUs), period, period);
            }

            void CycleDroneCPUs() {
                if(drones.Count == 0) {
                    return;
                }

                risingEdgeFrequencies.Clear();
                fallingEdgeFrequencies.Clear();
                removeActiveList.Clear();
                removeDroneList.Clear();

                foreach(var freq in RFManager._broadcasters) {
                    if(freq.Value.Count > 0) {
                        if(!activeFrequencies.Contains(freq.Key)) {
                            risingEdgeFrequencies.Add(freq.Key);
                            activeFrequencies.Add(freq.Key);
                        }
                    }
                }

                foreach(var freq in activeFrequencies) {
                    List<IRFObject> list;

                    if(!RFManager._broadcasters.TryGetValue(freq, out list)) {
                        removeActiveList.Add(freq);
                        fallingEdgeFrequencies.Add(freq);
                    } else {
                        if(list.Count == 0) {
                            removeActiveList.Add(freq);
                            fallingEdgeFrequencies.Add(freq);
                        }
                    }
                }

                foreach(var freq in removeActiveList) {
                    activeFrequencies.Remove(freq);
                }

                foreach(var value in drones) {
                    var drone = value.Value;
                    
                    if(!drone.miniCopterRef.Get(true)) {
                        removeDroneList.Add(value.Key);
                        continue;
                    }

                    if(drone.active) {
                        drone.CycleCPU();
                    }
                }

                foreach(var id in removeDroneList) {
                    drones.Remove(id);
                }
            }

            void FixedUpdate() {
                foreach(var value in drones) {
                    var drone = value.Value;
                    
                    if(!drone.miniCopterRef.Get(true)) {
                        continue;
                    }

                    if(drone.active) {
                        drone.FixedUpdate();
                    }
                }
            }

            public Drone AddDrone(MiniCopter miniCopter, StorageContainer storage) {
                var drone = new Drone();
                drone.miniCopterRef.Set(miniCopter);
                drone.instanceId = miniCopter.net.ID;
                drone.storage = storage;
                drone.manager = this;
                drones.Add(drone.instanceId, drone);
                return drone;
            }

            public void OnItemAddedOrRemoved(MiniCopter miniCopter, StorageContainer storage, Item item, bool added) {
                Drone drone = null;

                if(!drones.TryGetValue(miniCopter.net.ID, out drone)) {
                    drone = AddDrone(miniCopter, storage);
                }

                drone.OnItemAddedOrRemoved(storage, item, added);
            }

            void Reset() {
                foreach(var drone in drones) {
                    drone.Value.Reset();
                }
            }
        }

        class DroneCPU {
            List<Compiler.Instruction> instructions = new List<Compiler.Instruction>();
            public Dictionary<string, int> isrs = new Dictionary<string, int>();
            public Queue<string> interrupts = new Queue<string>();
            public List<int> picStack = new List<int>();
            int pic = 0;
            bool abort = false;
            string abortReason = null;
            Dictionary<string, Compiler.Instruction.Argument> numVariables = new Dictionary<string, Compiler.Instruction.Argument>();
            List<float> stack = new List<float>();
            public int maxStackSize = 64;

            public void Reset() {
                pic = 0;
                interrupts.Clear();
                picStack.Clear();
                numVariables.Clear();
            }

            public void LoadInstructions(List<Compiler.Instruction> instructions) {
                this.instructions = instructions;
                isrs.Clear();
                interrupts.Clear();
                picStack.Clear();
                numVariables.Clear();
                stack.Clear();
                pic = 0;

                for(int i = 0; i < instructions.Count; i++) {
                    var instr = instructions[i];

                    if(instr.name == "isr") {
                        isrs.Add(instr.args[0].stringValue, i);
                    } else if(instr.name == "num") {
                        numVariables.Add(instr.args[0].stringValue, instr.args[0]);
                    }
                }
            }

            public void Jump(int addr) {
                pic = addr;
            }

            public void Call(int addr) {
                picStack.Add(pic);
                pic = addr;
            }

            public bool Ret() {
                if(picStack.Count == 0) {
                    return false;
                }

                Jump(picStack[picStack.Count - 1]);
                picStack.RemoveAt(picStack.Count - 1);

                return true;
            }

            public void Interrupt(string name) {
                if(isrs.ContainsKey(name)) {
                    interrupts.Enqueue(name);
                }
            }

            public bool WriteVariable(string name, float value) {
                Compiler.Instruction.Argument arg;
                if(numVariables.TryGetValue(name, out arg)) {
                    arg.floatValue = value;
                    arg.intValue = (int)value;
                    return true;
                }

                return false;
            }

            public bool HandlePendingInterrupt() {
                if(interrupts.Count == 0) {
                    return false;
                }

                var isr = interrupts.Dequeue();
                int addr;
                isrs.TryGetValue(isr, out addr);
                Call(addr);

                return true;
            }

            public void Abort(string reason) {
                abort = true;
                abortReason = reason;
            }

            public bool Cycle(out Compiler.Instruction instr, out string failReason) {
                if(instructions == null || pic < 0 || pic >= instructions.Count) {
                    instr = null;
                    failReason = "out of instructions";
                    return false;
                }

                if(abort) {
                    instr = null;
                    failReason = abortReason;
                    return false;
                }

                instr = instructions[pic++];

                // if maybe one arg instruction
                if(instr.args.Count == 1) {
                    bool isOneOfThese = true;

                    switch(instr.name) {
                        case "jmp":
                            Jump(instr.args[0].intValue);
                            break;
                        case "call":
                            Call(instr.args[0].intValue);
                            break;
                        case "int":
                            Interrupt(instr.args[0].stringValue);
                            break;
                        case "ret":
                            if(!Ret()) {
                                failReason = "no address to return from";
                                return false;
                            }

                            break;
                        case "push":
                            if(stack.Count == maxStackSize) {
                                failReason = $"maximum stack size exceeded ({maxStackSize})";
                                return false;
                            }

                            stack.Add(instr.args[0].floatValue);
                            break;
                        default:
                            isOneOfThese = false;
                            break;
                    }

                    if(isOneOfThese) {
                        failReason = null;
                        return true;
                    }
                }

                // if maybe instruction that assigns to variable as first arg
                if(instr.args.Count > 0 && instr.args[0].paramType == Compiler.ParamType.NumVariable) {
                    bool isOneOfThese = true;
                    float result = 0;

                    switch(instr.name) {
                        case "pop":
                            if(stack.Count == 0) {
                                failReason = "stack empty";
                                return false;
                            }

                            result = stack[stack.Count - 1];
                            stack.RemoveAt(stack.Count - 1);
                            break;
                        case "mov":
                            result = instr.args[1].floatValue;
                            break;
                        default:
                            isOneOfThese = false;
                            break;
                    }

                    if(isOneOfThese) {
                        instr.args[0].floatValue = result;
                        instr.args[0].intValue = (int)result;
                        failReason = null;
                        return true;
                    }
                }

                // if might be one arg math instruction
                if(instr.args.Count == 1 && instr.args[0].paramType == Compiler.ParamType.Num) {
                    var valueArg = instr.args[0];
                    float result = 0;
                    bool isOneOfThese = true;
                    
                    try {
                        switch(instr.name) {
                            case "abs":
                                result = Mathf.Abs(valueArg.floatValue);
                                break;
                            case "sign":
                                result = Mathf.Sign(valueArg.floatValue);
                                break;
                            case "sqrt":
                                result = Mathf.Sqrt(valueArg.floatValue);
                                break;
                            case "round":
                                result = Mathf.Round(valueArg.floatValue);
                                break;
                            case "floor":
                                result = Mathf.Floor(valueArg.floatValue);
                                break;
                            case "ceil":
                                result = Mathf.Ceil(valueArg.floatValue);
                                break;
                            default:
                                isOneOfThese = false;
                                break;
                        }

                        if(isOneOfThese) {
                            if(!float.IsFinite(result)) {
                                failReason = $"math error: {instr.name} {String.Join(" ", instr.args.Select(x => x.rawValue))} => {result}";
                                return false;
                            }

                            WriteVariable("rslt", result);
                            failReason = null;
                            return true;
                        }
                    } catch(ArithmeticException e) {
                        failReason = e.ToString();
                        return false;
                    }
                }

                // if might be two arg math instruction
                if(instr.args.Count == 2 && instr.args[0].paramType == Compiler.ParamType.Num && instr.args[1].paramType == Compiler.ParamType.Num) {
                    var lhsArg = instr.args[0];
                    var rhsArg = instr.args[1];
                    float result = 0;
                    bool isOneOfThese = true;
                    
                    try {
                        switch(instr.name) {
                            case "add":
                                result = lhsArg.floatValue + rhsArg.floatValue;
                                break;
                            case "sub":
                                result = lhsArg.floatValue - rhsArg.floatValue;
                                break;
                            case "mul":
                                result = lhsArg.floatValue * rhsArg.floatValue;
                                break;
                            case "div":
                                result = lhsArg.floatValue / rhsArg.floatValue;
                                break;
                            case "pow":
                                result = Mathf.Pow(lhsArg.floatValue, rhsArg.floatValue);
                                break;
                            case "min":
                                result = Mathf.Min(lhsArg.floatValue, rhsArg.floatValue);
                                break;
                            case "max":
                                result = Mathf.Max(lhsArg.floatValue, rhsArg.floatValue);
                                break;
                            default:
                                isOneOfThese = false;
                                break;
                        }

                        if(isOneOfThese) {
                            if(!float.IsFinite(result)) {
                                failReason = $"math error: {instr.name} {String.Join(" ", instr.args.Select(x => x.rawValue))} => {result}";
                                return false;
                            }

                            WriteVariable("rslt", result);
                            failReason = null;
                            return true;
                        }
                    } catch(ArithmeticException e) {
                        failReason = e.ToString();
                        return false;
                    }
                }

                if(instr.name == "lerp") {
                    float result = Mathf.Lerp(instr.args[0].floatValue, instr.args[1].floatValue, instr.args[2].floatValue);
                    WriteVariable("rslt", result);
                    failReason = null;
                    return true;
                }

                // if might be conditional jump instruction
                if(instr.args.Count == 3 && instr.args[0].paramType == Compiler.ParamType.Num && instr.args[1].paramType == Compiler.ParamType.Num && instr.args[2].paramType == Compiler.ParamType.Address) {
                    float lhs = instr.args[0].floatValue;
                    float rhs = instr.args[1].floatValue;
                    int addr = instr.args[2].intValue;
                    bool jump = false;

                    switch(instr.name) {
                        case "ja":
                            jump = Mathf.Approximately(lhs, rhs);
                            break;
                        case "je":
                            jump = lhs == rhs;
                            break;
                        case "jne":
                            jump = lhs != rhs;
                            break;
                        case "jna":
                            jump = !Mathf.Approximately(lhs, rhs);
                            break;
                        case "jg":
                            jump = lhs > rhs;
                            break;
                        case "jge":
                            jump = lhs >= rhs;
                            break;
                        case "jl":
                            jump = lhs < rhs;
                            break;
                        case "jle":
                            jump = lhs <= rhs;
                            break;
                    }

                    if(jump) {
                        Jump(addr);
                        failReason = null;
                        return true;
                    }
                }

                failReason = null;
                return true;
            }
        }

        class Drone {
            public DroneManager manager;
            public EntityRef miniCopterRef;
            public uint instanceId;
            public DroneCPU cpu = new DroneCPU();
            public StorageContainer storage = null;

            public PIDController.Angular cyclicController = new PIDController.Angular {
                p = 0.5f,
                i = 0,
                d = 1,
                dRC = 0.5f
            };

            public PIDController.Linear throttleController = new PIDController.Linear {
                p = 1f,
                i = 0,
                d = 1f,
                spRC = 1f
            };

            public PIDController.Vector headingController = new PIDController.Vector {
                p = 1f,
                i = 0,
                d = 2.5f,
                spRC = 1.0f,
                dRC = 0.5f
            };

            [Flags]
            public enum Flag {
                EngineOn = 1 << 0,
                EngineStarting = 1 << 1,
                HasTarget = 1 << 2,
                HasTargetAltitude = 1 << 3,
                Flying = 1 << 4,
                ExecutingInstruction = 1 << 5,
                Landing = 1 << 6,
                SeekingTarget = 1 << 7,
                SeekingTargetFlythrough = 1 << 8,
                SeekingTargetAltitude = 1 << 9
            }

            public Flag flags;

            List<Vector3> targetStack = new List<Vector3>();
            List<float> targetAltStack = new List<float>();

            bool HasFlag(Flag f) {
                return (this.flags & f) == f;
            }

            public void SetFlag(Flag f, bool set) {
                if(set) {
                    this.flags |= f;
                    return;
                }

                this.flags &= ~f;
            }

            public bool active = false;
            Compiler.Instruction currentInstruction = null;
            float desiredAltitude = 0;
            Vector3 target = Vector3.zero;
            float sleepTime = -1;
            float engineStartTime = -1;
            float landingSpeed = 0;
            float landingTime;
            float desiredPitch = 0;
            int waitRF;

            public void Reset() {
                active = false;
                currentInstruction = null;
                desiredAltitude = 0;
                target = Vector3.zero;
                sleepTime = -1;
                flags = 0;
                landingSpeed = 0;
                desiredPitch = 0;

                var copter = miniCopterRef.Get(true) as MiniCopter;

                engineStartTime = -1;

                if(copter) {
                    StopEngine();
                    UpdateEngine();
                }

                targetStack.Clear();
                targetAltStack.Clear();
                
                cpu.Reset();
            }

            float GetTerrainHeight(Vector3 position) {
                return Mathf.Max(TerrainMeta.HeightMap.GetHeight(position), TerrainMeta.WaterMap.GetHeight(position));
            }

            float GetAltitude(Vector3 position) {
                return position.y - GetTerrainHeight(position);
            }

            public void OnItemAddedOrRemoved(StorageContainer storage, Item item, bool added) {
                string message;

                if(item.info.shortname == "note" && item.text != null) {
                    var maxProgramCharLength = config.maxProgramInstructions * maxAvgCharsPerLine;

                    if(item.text.Length > maxProgramCharLength) {
                        message = string.Format(plugin.lang.GetMessage("over_char_limit", plugin), maxProgramCharLength);
                        message = string.Format(plugin.lang.GetMessage("compiler_error", plugin), message);
                        item.text += "\n" + message;
                        return;
                    }

                    var lines = item.text.ToLower().Split(new[] {"\r\n", "\r", "\n", ";"}, StringSplitOptions.RemoveEmptyEntries);

                    if(lines.Length >= 1) {
                        if(lines[0] == "#droneasm") {
                            if(added) {
                                if(lines.Length < config.maxProgramInstructions) {
                                    Reset();
                                    bool success = compiler.Compile(item.text);

                                    if(!success) { 
                                        item.text += "\n" + String.Join("\n", compiler.errors.Select(x => {
                                            return string.Format(plugin.lang.GetMessage("compiler_error", plugin), x);
                                        }));
                                    } else {
                                        cpu.LoadInstructions(compiler.instructions);
                                        active = true;
                                    }
                                } else {
                                    message = string.Format(plugin.lang.GetMessage("over_instruction_limit", plugin), config.maxProgramInstructions);
                                    message = string.Format(plugin.lang.GetMessage("compiler_error", plugin), message);
                                    item.text += "\n" + message;
                                }
                            } else {
                                Reset();
                            }
                        }
                    }
                }
            }

            void ControlAltitude(float desiredAltitude, float currentAltitude) {
                var copter = miniCopterRef.Get(true) as MiniCopter;

                var throttleControl = throttleController.Update(desiredAltitude, currentAltitude, Time.fixedDeltaTime);
                float bias = (copter.rigidBody.mass * Physics.gravity.magnitude) / copter.engineThrustMax;
                throttleControl = Mathf.Clamp(throttleControl + bias, -1.0f, 1.0f);

                Vector3 copterUp = copter.transform.rotation * Vector3.up;
                Vector3 thrust = copterUp * (copter.engineThrustMax * throttleControl);

                copter.rigidBody.AddForce(thrust, ForceMode.Force);
            }

            void CyclicControl(Vector3 desired) {
                var copter = miniCopterRef.Get(true) as MiniCopter;
                var pv = copter.transform.rotation * Vector3.up;
                var control = cyclicController.Update(desired, pv, Time.fixedDeltaTime);

                if(control.magnitude > 1e-6f) {
                    copter.rigidBody.AddTorque(control, ForceMode.Acceleration);
                }
            }

            Vector3 HeadingControl(Vector3 target, float desiredPitch) {
                var copter = miniCopterRef.Get(true) as MiniCopter;
                
                var headingControl = headingController.Update(target, copter.transform.position, Time.fixedDeltaTime);
                float pitchAngle = Mathf.Clamp(headingControl.magnitude, -desiredPitch, desiredPitch);
                headingControl = headingControl.normalized * pitchAngle;

                var axis = Vector3.Cross(Vector3.up, headingControl).normalized;
                var rot = Quaternion.AngleAxis(pitchAngle, axis);

                return rot * Vector3.up;
            }

            void TailFinTorque() {
                var copter = miniCopterRef.Get(true) as MiniCopter;
                var tailForce = Vector3.Project(copter.GetWorldVelocity(), copter.transform.right);
                var dot = Vector3.Dot(copter.GetWorldVelocity(), copter.transform.right);
                tailForce *= tailForce.magnitude;
                copter.rigidBody.AddRelativeTorque(new Vector3(0, tailForce.magnitude * Mathf.Sign(dot), 0), ForceMode.Force);
            }

            void StartEngine() {
                var copter = miniCopterRef.Get(true) as MiniCopter;

                if(!HasFlag(Flag.EngineOn) && !HasFlag(Flag.EngineStarting) && !copter.Waterlogged()) {
                    engineStartTime = Time.fixedTime;
                    SetFlag(Flag.EngineStarting, true);
                    copter.EngineStartup();
                }
            }

            void StopEngine() {
                var copter = miniCopterRef.Get(true) as MiniCopter;

                SetFlag(Flag.EngineOn, false);
                SetFlag(Flag.EngineStarting, false);
                copter.EngineOff();
            }

            void UpdateEngine() {
                var copter = miniCopterRef.Get(true) as MiniCopter;

                if(!copter.HasFuel()) {
                    StopEngine();
                }

                if(HasFlag(Flag.EngineStarting) && Time.fixedTime > engineStartTime + 5.0f) {
                    SetFlag(Flag.EngineOn, true);
                    SetFlag(Flag.EngineStarting, false);
                }

                if(HasFlag(Flag.EngineOn)) {
                    copter.UseFuel(Time.fixedDeltaTime);

                    if(!copter.HasFlag(MiniCopter.Flag_EngineStart)) {
                        copter.SetFlag(MiniCopter.Flag_EngineStart, true);
                    }
                }
            }

            void ResetControl() {
                headingController.Reset();
                throttleController.Reset();
                cyclicController.Reset();
            }

            void Fly() {
                var copter = miniCopterRef.Get(true) as MiniCopter;

                if(!copter) {
                    return;
                }

                var currentAltitude = GetAltitude(copter.transform.position);

                if(HasFlag(Flag.Landing)) {
                    this.desiredAltitude = Mathf.Max(0, this.desiredAltitude - (this.landingSpeed * Time.fixedDeltaTime));
                }

                this.target.y = this.desiredAltitude + GetTerrainHeight(this.target);

                if(HasFlag(Flag.EngineOn)) {
                    if(HasFlag(Flag.Flying)) {
                        if(HasFlag(Flag.HasTargetAltitude)) {
                            ControlAltitude(desiredAltitude, currentAltitude);
                        }

                        Vector3 copterUp = Vector3.up;

                        if(HasFlag(Flag.HasTarget)) {
                            copterUp = HeadingControl(this.target, this.desiredPitch);
                        }

                        CyclicControl(copterUp);
                    }
                }
            }

            bool TryGetRFPosition(int freq, Vector3 closestTo, out Vector3 position) {
                var list = new List<IRFObject>();

                if(RFManager._broadcasters.TryGetValue(freq, out list)) {
                    if(list.Count == 0) {
                        position = Vector3.zero;
                        return false;
                    }

                    float closest = float.MaxValue;
                    Vector3 pos = Vector3.zero;

                    foreach(var irfObject in list) {
                        float dist = (irfObject.GetPosition() - closestTo).magnitude;

                        if(dist <= irfObject.GetMaxRange()) {
                            if(dist < closest) {
                                pos = irfObject.GetPosition();
                                closest = dist;
                            }
                        }
                    }

                    if(closest != float.MaxValue) {
                        position = pos;
                        return true;
                    }
                }

                position = Vector3.zero;
                return false;
            }

            public void FixedUpdate() {
                MiniCopter copter = miniCopterRef.Get(true) as MiniCopter;

                if(!copter) {
                    Reset();
                    return;
                }

                UpdateEngine();
                TailFinTorque();

                if(!active) {
                    StopEngine();
                    return;
                }

                Fly();
            }

            public void CycleCPU() {
                MiniCopter copter = miniCopterRef.Get(true) as MiniCopter;

                if(!copter) {
                    Reset();
                    return;
                }

                var currentAltitude = GetAltitude(copter.transform.position);

                foreach(var freq in DroneManager.risingEdgeFrequencies) {
                    string isrName = "rfa" + freq;
                    cpu.Interrupt(isrName);
                }

                foreach(var freq in DroneManager.fallingEdgeFrequencies) {
                    string isrName = "rfna" + freq;
                    cpu.Interrupt(isrName);
                }

                if(HasFlag(Flag.Landing)) {
                    if(currentAltitude < 2 || (Time.fixedTime - this.landingTime > 5.0f && copter.rigidBody.velocity.magnitude < 0.1f)) {
                        SetFlag(Flag.Landing, false);
                        SetFlag(Flag.Flying, false);
                        cpu.Interrupt("landed");
                    }
                }

                if(HasFlag(Flag.HasTarget) && HasFlag(Flag.SeekingTarget)) {
                    Vector3 offset = this.target - copter.transform.position;

                    if(offset.magnitude < 1 && copter.rigidBody.velocity.magnitude < 1) {
                        SetFlag(Flag.SeekingTarget, false);
                        cpu.Interrupt("at_target");
                    }
                }

                if(HasFlag(Flag.HasTarget) && HasFlag(Flag.SeekingTargetFlythrough)) {
                    Vector3 offset = this.target - copter.transform.position;

                    if(offset.magnitude < 10.0f) {
                        SetFlag(Flag.SeekingTargetFlythrough, false);
                        cpu.Interrupt("almost_at_target");
                    }
                }

                if(HasFlag(Flag.HasTargetAltitude) && HasFlag(Flag.SeekingTargetAltitude)) {
                    if(Mathf.Abs(currentAltitude - this.desiredAltitude) < 1 && copter.rigidBody.velocity.magnitude < 1) {
                        SetFlag(Flag.SeekingTargetAltitude, false);
                        cpu.Interrupt("at_altitude");
                    }
                }

                // this checks if the executing instruction has finished
                if(this.currentInstruction != null && HasFlag(Flag.ExecutingInstruction)) {
                    switch(this.currentInstruction.name) {
                        case "sleep":
                            if(Time.fixedTime > this.sleepTime) {
                                this.sleepTime = -1;
                                SetFlag(Flag.ExecutingInstruction, false);
                            }

                            break;
                        case "startengine":
                            if(HasFlag(Flag.EngineOn)) {
                                SetFlag(Flag.ExecutingInstruction, false);
                            }

                            break;
                        case "waitrf":
                            if(DroneManager.activeFrequencies.Contains(this.waitRF)) {
                                SetFlag(Flag.ExecutingInstruction, false);
                            }

                            break;
                        case "land":
                            if(!HasFlag(Flag.Landing)) {
                                SetFlag(Flag.ExecutingInstruction, false);
                            }

                            break;
                        case "flyto":
                            if(!HasFlag(Flag.SeekingTarget)) {
                                SetFlag(Flag.ExecutingInstruction, false);
                            }

                            break;
                        case "flythrough":
                            if(!HasFlag(Flag.SeekingTargetFlythrough)) {
                                SetFlag(Flag.ExecutingInstruction, false);
                            }

                            break;
                    }
                }

                if(cpu.HandlePendingInterrupt()) {
                    SetFlag(Flag.ExecutingInstruction, false);
                }

                int numInstructionsExecuted = 0;
                string failReason;
                while(numInstructionsExecuted < config.maxInstructionsPerCycle && !HasFlag(Flag.ExecutingInstruction)) {
                    // these need to stay synced
                    this.target.y = this.desiredAltitude + GetTerrainHeight(this.target);

                    if(!cpu.Cycle(out this.currentInstruction, out failReason)) {
                        Reset();
                        return;
                    }

                    numInstructionsExecuted++;

                    switch(this.currentInstruction.name) {
                        case "sleep":
                            var seconds = currentInstruction.args[0].floatValue;
                            
                            if(this.sleepTime == -1) {
                                this.sleepTime = Time.fixedTime + seconds;
                            }
                            
                            SetFlag(Flag.ExecutingInstruction, true);
                            break;
                        case "startengine":
                            if(!HasFlag(Flag.EngineStarting)) {
                                StartEngine();
                                SetFlag(Flag.ExecutingInstruction, true);
                            }

                            break;
                        case "stopengine":
                            StopEngine();
                            break;
                        case "target":
                            var mapCol = currentInstruction.args[0].floatValue;
                            var mapRow = currentInstruction.args[1].floatValue;
                            var desiredAltitude = currentInstruction.args[2].floatValue;

                            Vector3 pos1;
                            pos1 = MapGridToPosition(mapCol, mapRow);
                            this.target = pos1;
                            this.desiredAltitude = desiredAltitude;
                            SetFlag(Flag.HasTarget, true);
                            SetFlag(Flag.HasTargetAltitude, true);
                            ResetControl();

                            break;
                        case "targetalt":
                            this.desiredAltitude = currentInstruction.args[0].floatValue;
                            SetFlag(Flag.HasTargetAltitude, true);
                            ResetControl();
                            break;
                        case "targetrf":
                            var freq = currentInstruction.args[0].intValue;

                            Vector3 pos2;
                            if(TryGetRFPosition(freq, copter.transform.position, out pos2)) {
                                this.target = pos2;
                                this.desiredAltitude = this.target.y - GetTerrainHeight(this.target);
                                SetFlag(Flag.HasTarget, true);
                                SetFlag(Flag.HasTargetAltitude, true);
                                ResetControl();
                            }
                            
                            break;
                        case "targethere":
                            this.target = copter.transform.position;
                            this.desiredAltitude = this.target.y - GetTerrainHeight(this.target);
                            SetFlag(Flag.HasTarget, true);
                            SetFlag(Flag.HasTargetAltitude, true);
                            ResetControl();
                            break;
                        case "land":
                            var speed = currentInstruction.args[0].floatValue;

                            if(HasFlag(Flag.Flying)) {
                                this.landingSpeed = speed;
                                this.landingTime = Time.fixedTime;
                                SetFlag(Flag.Landing, true);
                                SetFlag(Flag.ExecutingInstruction, true);
                            }

                            break;
                        case "flyto":
                        case "flythrough":
                            if(HasFlag(Flag.HasTarget) || HasFlag(Flag.HasTargetAltitude)) {
                                SetFlag(Flag.Flying, true);
                                SetFlag(Flag.ExecutingInstruction, true);

                                if(HasFlag(Flag.HasTarget)) {
                                    SetFlag(Flag.SeekingTarget, true);
                                }

                                if(HasFlag(Flag.HasTargetAltitude)) {
                                    SetFlag(Flag.SeekingTargetAltitude, false);
                                }
                            }

                            break;
                        case "drop":
                            var slot = currentInstruction.args[0].intValue;

                            for(int i = 0; i < storage.inventory.itemList.Count; i++) {
                                var item = storage.inventory.itemList[i];
                                
                                if(item.position == slot) {
                                    Vector3 randomVector = new Vector3(UnityEngine.Random.Range(-0.5f, 0.5f), 0, UnityEngine.Random.Range(-0.5f, 0.5f));
                                    item.Drop(storage.GetDropPosition() + Vector3.down * 2 + randomVector, storage.GetDropVelocity());
                                }
                            }

                            break;
                        case "pushtarget":
                            targetStack.Add(this.target);
                            
                            if(targetStack.Count > 32) {
                                Reset();
                                return;
                            }
                            
                            break;
                        case "poptarget":                           
                            if(targetStack.Count == 0) {
                                Reset();
                                return;
                            }

                            this.target = targetStack[targetStack.Count - 1];
                            targetStack.RemoveAt(targetStack.Count - 1);
                            ResetControl();
                            
                            break;
                        case "pushtargetalt":
                            targetAltStack.Add(this.desiredAltitude);
                            
                            if(targetAltStack.Count > 32) {
                                Reset();
                                return;
                            }
                            
                            break;
                        case "poptargetalt":                           
                            if(targetAltStack.Count == 0) {
                                Reset();
                                return;
                            }

                            this.desiredAltitude = targetAltStack[targetAltStack.Count - 1];
                            targetAltStack.RemoveAt(targetAltStack.Count - 1);
                            ResetControl();
                            
                            break;
                        case "gettarget":
                            var stackPos = this.currentInstruction.args[0].intValue;
                            var xVar = this.currentInstruction.args[1].stringValue;
                            var yVar = this.currentInstruction.args[2].stringValue;
                            var zVar = this.currentInstruction.args[3].stringValue;
                            Vector3 targetToUse = Vector3.zero;

                            if(stackPos == -1) {
                                targetToUse = this.target;
                            } else {
                                if(this.targetStack.Count >= stackPos + 1) {
                                    targetToUse = this.targetStack[stackPos];
                                }
                            }

                            cpu.WriteVariable(xVar, targetToUse.x);
                            cpu.WriteVariable(yVar, targetToUse.y);
                            cpu.WriteVariable(zVar, targetToUse.z);
                            break;
                        case "getalt":
                            var stackPos2 = this.currentInstruction.args[0].intValue;
                            var altVar = this.currentInstruction.args[1].stringValue;
                            float altToUse = 0;

                            if(stackPos2 == -1) {
                                altToUse = this.desiredAltitude;
                            } else {
                                if(this.targetAltStack.Count >= stackPos2 + 1) {
                                    altToUse = this.targetAltStack[stackPos2];
                                }
                            }

                            cpu.WriteVariable(altVar, altToUse);
                            break;
                        case "settarget":
                            var stackPos3 = this.currentInstruction.args[0].intValue;
                            var xVal = this.currentInstruction.args[1].floatValue;
                            var yVal = this.currentInstruction.args[2].floatValue;
                            var zVal = this.currentInstruction.args[3].floatValue;

                            if(stackPos3 == -1) {
                                this.target = new Vector3(xVal, yVal, zVal);
                                this.desiredAltitude = this.target.y - GetTerrainHeight(this.target);
                                SetFlag(Flag.HasTarget, true);
                                SetFlag(Flag.HasTargetAltitude, true);
                                ResetControl();
                            } else {
                                if(this.targetStack.Count >= stackPos3 + 1) {
                                    this.targetStack[stackPos3] = new Vector3(xVal, yVal, zVal);
                                    this.desiredAltitude = this.target.y - GetTerrainHeight(this.target);
                                    SetFlag(Flag.HasTarget, true);
                                    SetFlag(Flag.HasTargetAltitude, true);
                  
// ... [Code preview truncated due to length. Full source in attached file] ...

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