New Mining Controller Behavior and Mining Tool Behavior, tweaked a bunch of asteroid related stuff
216 lines
No EOL
6.5 KiB
C#
216 lines
No EOL
6.5 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using MessagePack;
|
|
using Newtonsoft.Json;
|
|
using Unity.Mathematics;
|
|
using static Unity.Mathematics.math;
|
|
using float2 = Unity.Mathematics.float2;
|
|
|
|
[Union(0, typeof(TowingControllerData))]
|
|
public abstract class ControllerData : BehaviorData
|
|
{
|
|
[InspectableField, JsonProperty("thrustSensitivity"), Key(1)]
|
|
public float ThrustSensitivity = 1;
|
|
|
|
[InspectableField, JsonProperty("thrustSpecificity"), Key(2)]
|
|
public float ThrustSpecificity = 8;
|
|
|
|
[InspectableField, JsonProperty("turningSensitivity"), Key(3)]
|
|
public float TurningSensitivity = 1;
|
|
|
|
[InspectableField, JsonProperty("tangentSensitivity"), Key(4)]
|
|
public float TangentSensitivity = 4;
|
|
|
|
[InspectableField, JsonProperty("targetDistance"), Key(5)]
|
|
public float TargetDistance = 10;
|
|
}
|
|
|
|
public abstract class ControllerBase : IBehavior, IController, IInitializableBehavior
|
|
{
|
|
public Guid HomeEntity;
|
|
public bool Available => Task == Guid.Empty;
|
|
public abstract TaskType TaskType { get; }
|
|
public Guid Zone => _entity.Zone;
|
|
public BehaviorData Data => _controllerData;
|
|
|
|
protected Locomotion Locomotion;
|
|
protected VelocityMatch VelocityMatch;
|
|
protected Func<float2> TargetPosition;
|
|
protected Func<float2> TargetVelocity;
|
|
protected bool MatchVelocity;
|
|
protected List<SimplifiedZoneData> Path;
|
|
protected Guid Task;
|
|
protected bool Moving;
|
|
|
|
private GameContext _context;
|
|
private Entity _entity;
|
|
private ControllerData _controllerData;
|
|
private MovementPhase _movementPhase;
|
|
private Action _onFinishMoving;
|
|
|
|
public ControllerBase(GameContext context, ControllerData data, Entity entity)
|
|
{
|
|
_context = context;
|
|
_controllerData = data;
|
|
_entity = entity;
|
|
}
|
|
|
|
public void Initialize()
|
|
{
|
|
Locomotion = new Locomotion(_context, _entity, _controllerData);
|
|
VelocityMatch = new VelocityMatch(_context, _entity, _controllerData);
|
|
|
|
_context.CorporationControllers[_entity.Corporation].Add(this);
|
|
}
|
|
|
|
public void AssignTask(Guid task)
|
|
{
|
|
Task = task;
|
|
Moving = false;
|
|
}
|
|
|
|
public bool Update(float delta)
|
|
{
|
|
if (Available)
|
|
{
|
|
// No task is assigned and we're at home, do nothing!
|
|
if (_entity.Parent == HomeEntity)
|
|
return false;
|
|
|
|
// No task is assigned, but we're not home, go home!
|
|
if (!Moving)
|
|
{
|
|
GoHome();
|
|
}
|
|
}
|
|
|
|
if (Moving)
|
|
{
|
|
if(_entity.Parent!=Guid.Empty)
|
|
_context.RemoveParent(_entity);
|
|
|
|
var distance = length(TargetPosition() - _entity.Position);
|
|
if (MatchVelocity)
|
|
{
|
|
VelocityMatch.TargetVelocity = TargetVelocity();
|
|
if (_movementPhase == MovementPhase.Locomotion)
|
|
{
|
|
var matchDistanceTime = VelocityMatch.MatchDistanceTime;
|
|
Locomotion.Objective = TargetPosition() + TargetVelocity() * matchDistanceTime.y;
|
|
Locomotion.Update(delta);
|
|
|
|
if (distance < matchDistanceTime.x)
|
|
{
|
|
_movementPhase = MovementPhase.Slowdown;
|
|
_context.Log($"Controller {_entity.Name} has entered slowdown phase.");
|
|
VelocityMatch.Clear();
|
|
VelocityMatch.OnMatch += () =>
|
|
{
|
|
Moving = false;
|
|
_onFinishMoving?.Invoke();
|
|
};
|
|
}
|
|
}
|
|
else
|
|
{
|
|
VelocityMatch.Update(delta);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Locomotion.Objective = TargetPosition();
|
|
Locomotion.Update(delta);
|
|
if (distance < _controllerData.TargetDistance)
|
|
{
|
|
Moving = false;
|
|
_onFinishMoving();
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public void FinishTask()
|
|
{
|
|
if (Task == Guid.Empty)
|
|
return;
|
|
|
|
var task = _context.Cache.Get(Task);
|
|
_context.Cache.Delete(task);
|
|
_context.Cache.Get<Corporation>(_entity.Corporation).Tasks.Remove(task.ID);
|
|
Task = Guid.Empty;
|
|
}
|
|
|
|
public void GoHome(Action onFinish = null)
|
|
{
|
|
var homeEntity = _context.Cache.Get<Entity>(HomeEntity);
|
|
if (Zone == homeEntity.Zone) MoveTo(homeEntity, true, () =>
|
|
{
|
|
_context.SetParent(_entity, homeEntity);
|
|
onFinish?.Invoke();
|
|
});
|
|
else MoveTo(homeEntity.Zone, () => MoveTo(homeEntity, true, () =>
|
|
{
|
|
_context.SetParent(_entity, homeEntity);
|
|
onFinish?.Invoke();
|
|
}));
|
|
}
|
|
|
|
public void MoveTo(Entity entity, bool matchVelocity = true, Action onFinish = null)
|
|
{
|
|
TargetPosition = () => entity.Position;
|
|
TargetVelocity = () => entity.Velocity;
|
|
MatchVelocity = matchVelocity;
|
|
_movementPhase = MovementPhase.Locomotion;
|
|
Moving = true;
|
|
_onFinishMoving = onFinish;
|
|
}
|
|
|
|
public void MoveTo(float2 position, bool matchVelocity = true, Action onFinish = null)
|
|
{
|
|
TargetPosition = () => position;
|
|
TargetVelocity = () => float2.zero;
|
|
MatchVelocity = matchVelocity;
|
|
_movementPhase = MovementPhase.Locomotion;
|
|
Moving = true;
|
|
_onFinishMoving = onFinish;
|
|
}
|
|
|
|
public void MoveTo(Func<float2> position, Func<float2> velocity, Action onFinish = null)
|
|
{
|
|
TargetPosition = position;
|
|
TargetVelocity = velocity;
|
|
MatchVelocity = true;
|
|
_movementPhase = MovementPhase.Locomotion;
|
|
Moving = true;
|
|
_onFinishMoving = onFinish;
|
|
}
|
|
|
|
public void MoveTo(Guid zone, Action onFinish = null)
|
|
{
|
|
var path = _context.FindPath(_context.GalaxyZones[Zone], _context.GalaxyZones[zone]);
|
|
|
|
void OnNextZone()
|
|
{
|
|
path.RemoveAt(0);
|
|
if (path.Count > 0)
|
|
{
|
|
MoveTo(_context.WormholePosition(_entity.Zone, Path[0].ZoneID), false, OnNextZone);
|
|
}
|
|
else
|
|
{
|
|
onFinish?.Invoke();
|
|
}
|
|
}
|
|
|
|
OnNextZone();
|
|
}
|
|
}
|
|
|
|
public enum MovementPhase
|
|
{
|
|
Locomotion,
|
|
Slowdown
|
|
} |