using System; using System.Collections; using System.Collections.Generic; using System.Linq; using MessagePack; using Newtonsoft.Json; using RethinkDb.Driver.Ast; using Unity.Mathematics; using static Unity.Mathematics.math; [MessagePackObject, JsonObject(MemberSerialization.OptIn), EntityTypeRestriction(HullType.Ship), Order(-100)] public class SurveyControllerData : ControllerData { public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item) { return new SurveyController(context, this, entity, item); } } public class SurveyController : ControllerBase, IBehavior, IPersistentBehavior, IInitializableBehavior { public override TaskType TaskType => TaskType.Explore; public BehaviorData Data => _data; private SurveyControllerData _data; private GameContext _context; private Entity _entity; private Gear _item; private bool _taskStarted; private ResourceScanner _scanningTool; private Switch _toolSwitch; private Guid _targetPlanet; private int _asteroid = -1; public SurveyController(GameContext context, SurveyControllerData data, Entity entity, Gear item) : base(context, data, entity) { _context = context; _data = data; _entity = entity; _item = item; } public new void Initialize() { _scanningTool = _entity.GetBehavior(); _toolSwitch = _entity.GetSwitch(); base.Initialize(); } public new bool Update(float delta) { var surveyTask = _context.Cache.Get(Task); var corporation = _context.Cache.Get(_entity.Corporation); if (surveyTask != null) { if (!_taskStarted) { if (surveyTask.Planets.Any()) { _entity.SetMessage("Moving to survey target."); NextPlanet(); _scanningTool.ScanTarget = _targetPlanet; _scanningTool.Asteroid = _asteroid; if (!corporation.PlanetSurveyFloor.ContainsKey(_targetPlanet) || corporation.PlanetSurveyFloor[_targetPlanet] + .5f < _scanningTool.MinimumDensity) { var planetData = _context.Cache.Get(_targetPlanet); MoveTo(() => { var target = GetPosition(planetData, _asteroid); var targetToUs = _entity.Position - target; return target + normalize(targetToUs) * _scanningTool.Range / 2; }, () => GetVelocity(planetData, _asteroid), () => _entity.SetMessage("Arrived at target. Scanning for resources.")); _taskStarted = true; } else surveyTask.Planets.Remove(_targetPlanet); } else { _entity.SetMessage("Survey complete. Returning Home."); FinishTask(); } } else { if (!Moving) { var planetData = _context.Cache.Get(_targetPlanet); if ((!corporation.PlanetSurveyFloor.ContainsKey(_targetPlanet) || corporation.PlanetSurveyFloor[_targetPlanet] + .5f < _scanningTool.MinimumDensity) && length(_entity.Position - GetPosition(planetData, _asteroid)) < _scanningTool.Range) { _toolSwitch.Activated = true; Aim.Objective = GetPosition(planetData, _asteroid); Aim.Update(delta); } else { _toolSwitch.Activated = false; _taskStarted = false; } } } } return base.Update(delta); } private void NextPlanet() { var surveyTask = _context.Cache.Get(Task); var planets = surveyTask.Planets.Select(id => Zone.Planets[id]); var nearestPlanet = planets.MinBy(p => lengthsq(_entity.Position - GetPosition(p))); _asteroid = nearestPlanet is AsteroidBeltData ? Zone.NearestAsteroid(nearestPlanet.ID, _entity.Position) : -1; _targetPlanet = nearestPlanet.ID; } private float2 GetPosition(BodyData planet, int asteroid = -1) { if (planet is AsteroidBeltData) { if(asteroid == -1) asteroid = Zone.NearestAsteroid(planet.ID, _entity.Position); return Zone.GetAsteroidTransform(planet.ID, asteroid).xy; } return Zone.GetOrbitPosition(planet.Orbit); } private float2 GetVelocity(BodyData planet, int asteroid = -1) { if (planet is AsteroidBeltData) { if(asteroid == -1) asteroid = Zone.NearestAsteroid(planet.ID, _entity.Position); return Zone.GetAsteroidVelocity(planet.ID, asteroid); } return Zone.GetOrbitVelocity(planet.Orbit); } public PersistentBehaviorData Store() { return new SurveyControllerPersistence { Task = Task }; } public void Restore(PersistentBehaviorData data) { var surveyControllerPersistence = data as SurveyControllerPersistence; Task = surveyControllerPersistence.Task; } } public class SurveyControllerPersistence : PersistentBehaviorData { [JsonProperty("task"), Key(0)] public Guid Task; }