Last active
January 24, 2023 03:23
-
-
Save thexa4/1b106528767cba12629f42838f6fecf1 to your computer and use it in GitHub Desktop.
Space Engineers scripts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
bool _autoPowerSave = true; | |
IMyTextSurface _cockpitSurface; | |
RectangleF _viewport; | |
List<IMyCargoContainer> _containers = new List<IMyCargoContainer>(); | |
List<IMyEntity> _storages = new List<IMyEntity>(); | |
IMyGasGenerator _splitter; | |
List<IMyBatteryBlock> _batteries = new List<IMyBatteryBlock>(); | |
IMyPowerProducer _generator; | |
List<IMyGasTank> _tanks = new List<IMyGasTank>(); | |
IMyCockpit _cockpit; | |
IMyRemoteControl _remoteControl; | |
IMyRadioAntenna _antenna; | |
List<IMyLightingBlock> _headLights = new List<IMyLightingBlock>(); | |
IMyMotorStator _leftHinge; | |
IMyMotorStator _rightHinge; | |
IMyShipMergeBlock _topLeftMerge; | |
IMyShipMergeBlock _bottomLeftMerge; | |
IMyShipMergeBlock _topRightMerge; | |
IMyShipMergeBlock _bottomRightMerge; | |
IMyMotorSuspension _frontLeftWheel; | |
IMyMotorSuspension _frontRightWheel; | |
MyItemType _iceType = new MyItemType("MyObjectBuilder_Ore", "Ice"); | |
const double _iceConversionRatio = 20.0; | |
double _fuelTankSize = 1; | |
bool _wasDocked = false; | |
bool _isDeployed = false; | |
bool _isInconsistent = true; | |
bool _isStowing = false; | |
bool _isDeploying = false; | |
TimeSpan _lastDeployAction = TimeSpan.Zero; | |
TimeSpan _uptime = TimeSpan.Zero; | |
TimeSpan _timeIdle = TimeSpan.Zero; | |
private void ReInit() | |
{ | |
_timeIdle = TimeSpan.Zero; | |
_lastDeployAction = TimeSpan.Zero; | |
_isStowing = false; | |
_isDeploying = false; | |
GridTerminalSystem.GetBlocksOfType(_containers, b => b.IsSameConstructAs(Me)); | |
GridTerminalSystem.GetBlocksOfType(_batteries, b => b.IsSameConstructAs(Me)); | |
GridTerminalSystem.GetBlocksOfType(_tanks, b => b.IsSameConstructAs(Me)); | |
GridTerminalSystem.GetBlocksOfType(_headLights); | |
_fuelTankSize = 0; | |
foreach (var tank in _tanks) { | |
_fuelTankSize += tank.Capacity; | |
} | |
if (_fuelTankSize < 0.01) { | |
Echo("Fatal: No hydrogen tanks"); | |
_fuelTankSize = 1; | |
} | |
var splitters = new List<IMyGasGenerator>(); | |
GridTerminalSystem.GetBlocksOfType(splitters, b => b.IsSameConstructAs(Me)); | |
if (splitters.Any()) | |
_splitter = splitters.First(); | |
var generators = new List<IMyPowerProducer>(); | |
GridTerminalSystem.GetBlocksOfType(generators, b => b.IsSameConstructAs(Me) && b.BlockDefinition.ToString().Contains("HydrogenEngine")); | |
if (generators.Any()) | |
_generator = generators.First(); | |
var remoteControls = new List<IMyRemoteControl>(); | |
GridTerminalSystem.GetBlocksOfType(remoteControls, b => b.IsSameConstructAs(Me)); | |
if (remoteControls.Any()) | |
_remoteControl = remoteControls.First(); | |
var antennas = new List<IMyRadioAntenna>(); | |
GridTerminalSystem.GetBlocksOfType(antennas, b => b.IsSameConstructAs(Me)); | |
if (antennas.Any()) | |
_antenna = antennas.First(); | |
var cockpits = new List<IMyCockpit>(); | |
GridTerminalSystem.GetBlocksOfType(cockpits, b => b.IsSameConstructAs(Me)); | |
if (cockpits.Any()) | |
_cockpit = cockpits.First(); | |
_storages.Clear(); | |
_storages.AddRange(_containers); | |
_storages.Add(_cockpit); | |
_cockpitSurface = _cockpit.GetSurface(0); | |
_cockpitSurface.ContentType = ContentType.SCRIPT; | |
_cockpitSurface.Script = ""; | |
_viewport = new RectangleF( | |
(_cockpitSurface.TextureSize - _cockpitSurface.SurfaceSize) / 2f, | |
_cockpitSurface.SurfaceSize | |
); | |
foreach (var battery in _batteries) { | |
battery.ChargeMode = ChargeMode.Auto; | |
} | |
_leftHinge = GridTerminalSystem.GetBlockWithName("Hinge Left") as IMyMotorStator; | |
_rightHinge = GridTerminalSystem.GetBlockWithName("Hinge Right") as IMyMotorStator; | |
_topLeftMerge = GridTerminalSystem.GetBlockWithName("Top Left Merge Block Fork") as IMyShipMergeBlock; | |
_bottomLeftMerge = GridTerminalSystem.GetBlockWithName("Bottom Left Merge Block Fork") as IMyShipMergeBlock; | |
_topRightMerge = GridTerminalSystem.GetBlockWithName("Top Right Merge Block Fork") as IMyShipMergeBlock; | |
_bottomRightMerge = GridTerminalSystem.GetBlockWithName("Bottom Right Merge Block Fork") as IMyShipMergeBlock; | |
bool leftDeployed = false; | |
bool leftInconsistent = true; | |
bool rightDeployed = false; | |
bool rightInconsistent = true; | |
if (_topLeftMerge != null && _bottomLeftMerge != null && _topRightMerge != null && _bottomRightMerge != null && _leftHinge != null && _rightHinge != null) { | |
if (_topLeftMerge.IsConnected && !_bottomLeftMerge.IsConnected) { | |
leftDeployed = false; | |
leftInconsistent = false; | |
} | |
if (!_topLeftMerge.IsConnected && _bottomLeftMerge.IsConnected) { | |
leftDeployed = true; | |
leftInconsistent = false; | |
} | |
if (_topRightMerge.IsConnected && !_bottomRightMerge.IsConnected) { | |
rightDeployed = false; | |
rightInconsistent = false; | |
} | |
if (!_topRightMerge.IsConnected && _bottomRightMerge.IsConnected) { | |
rightDeployed = true; | |
rightInconsistent = false; | |
} | |
_isInconsistent = leftInconsistent || rightInconsistent || (leftDeployed != rightDeployed); | |
_isDeployed = leftDeployed && rightDeployed; | |
if (_isDeployed) { | |
_leftHinge.LowerLimitDeg = -20; | |
_leftHinge.UpperLimitDeg = -1; | |
_rightHinge.LowerLimitDeg = -20; | |
_rightHinge.UpperLimitDeg = -1; | |
_leftHinge.Torque = 100000; | |
_rightHinge.Torque = 100000; | |
_leftHinge.TargetVelocityRPM = -5; | |
_rightHinge.TargetVelocityRPM = -5; | |
} else { | |
if (!_isInconsistent) { | |
//_leftHinge.LowerLimitDeg = 0; | |
//_leftHinge.UpperLimitDeg = 0; | |
//_rightHinge.LowerLimitDeg = 0; | |
//_rightHinge.UpperLimitDeg = 0; | |
//_leftHinge.TargetVelocityRPM = 5; | |
//_rightHinge.TargetVelocityRPM = 5; | |
} | |
} | |
} | |
_frontLeftWheel = GridTerminalSystem.GetBlockWithName("Front Left Wheel") as IMyMotorSuspension; | |
_frontRightWheel = GridTerminalSystem.GetBlockWithName("Front Right Wheel") as IMyMotorSuspension; | |
if (_frontLeftWheel != null && _frontRightWheel != null) { | |
_frontLeftWheel.SteeringOverride = 0; | |
_frontRightWheel.SteeringOverride = 0; | |
_frontLeftWheel.PropulsionOverride = 0; | |
_frontRightWheel.PropulsionOverride = 0; | |
} else { | |
_isInconsistent = true; | |
} | |
_wasDocked = IsDocked(); | |
} | |
public Program() | |
{ | |
Runtime.UpdateFrequency = UpdateFrequency.Update10; | |
ReInit(); | |
} | |
public bool IsDocked() { | |
return _cockpit.HandBrake; | |
} | |
public void Save() | |
{ | |
// Called when the program needs to save its state. Use | |
// this method to save your state to the Storage field | |
// or some other means. | |
// | |
// This method is optional and can be removed if not | |
// needed. | |
} | |
private void DoHousekeeping() | |
{ | |
double hydrogen = 0; | |
double ice = 0; | |
double power = 0; | |
double powerMax = 0; | |
foreach (var tank in _tanks) { | |
if (!tank.IsFunctional) | |
continue; | |
hydrogen += tank.Capacity * tank.FilledRatio; | |
} | |
foreach (var storage in _storages) { | |
var inventory = storage.GetInventory(); | |
if (inventory == null) | |
continue; | |
var iceCount = inventory.GetItemAmount(_iceType); | |
ice += (double)iceCount * _iceConversionRatio; | |
} | |
foreach (var battery in _batteries) { | |
if (!battery.IsFunctional) | |
continue; | |
powerMax += battery.MaxStoredPower; | |
power += battery.CurrentStoredPower; | |
} | |
double fuelPercentage = Math.Ceiling((ice + hydrogen) / _fuelTankSize * 100); | |
Echo("Fuel: " + fuelPercentage.ToString() + "%"); | |
double hydrogenPercentage = Math.Ceiling(hydrogen / _fuelTankSize * 100); | |
Echo("Hydrogen: " + hydrogenPercentage.ToString() + "%"); | |
double powerPercentage = Math.Ceiling(power / powerMax * 100); | |
Echo("Power: " + powerPercentage.ToString() + "%"); | |
if (_isInconsistent) { | |
Echo("Forks inconsistent"); | |
} else { | |
if (_isDeployed) { | |
Echo("Forks deployed"); | |
_frontLeftWheel.SteeringOverride = _cockpit.MoveIndicator.X; | |
_frontRightWheel.SteeringOverride = _cockpit.MoveIndicator.X; | |
_frontLeftWheel.PropulsionOverride = -_cockpit.MoveIndicator.Z; | |
_frontRightWheel.PropulsionOverride = _cockpit.MoveIndicator.Z; | |
} else { | |
Echo ("Forks stowed"); | |
} | |
if ((_uptime - _lastDeployAction).TotalSeconds > 1) { | |
if (_isDeploying) { | |
if (_topLeftMerge.Enabled) { | |
_topLeftMerge.Enabled = false; | |
_topRightMerge.Enabled = false; | |
_lastDeployAction = _uptime; | |
} else { | |
if (_bottomLeftMerge.IsConnected && _bottomRightMerge.IsConnected) { | |
if ((_uptime - _lastDeployAction).TotalSeconds > 2) | |
ReInit(); | |
} else { | |
_lastDeployAction = _uptime; | |
} | |
} | |
} | |
if (_isStowing) { | |
Echo("Left: " + _leftHinge.Angle); | |
Echo("Right: " + _rightHinge.Angle); | |
if (_leftHinge.Angle < 0.001 && _rightHinge.Angle < 0.001) { | |
if (_bottomLeftMerge.Enabled) { | |
_bottomLeftMerge.Enabled = false; | |
_bottomRightMerge.Enabled = false; | |
_lastDeployAction = _uptime; | |
} else { | |
_lastDeployAction = _uptime; | |
if (_topLeftMerge.IsConnected && _topRightMerge.IsConnected) { | |
ReInit(); | |
} | |
} | |
} else { | |
_lastDeployAction = _uptime; | |
} | |
} | |
} | |
} | |
bool newDockStatus = IsDocked(); | |
if (newDockStatus != _wasDocked) { | |
_wasDocked = newDockStatus; | |
if (newDockStatus) { | |
foreach (var light in _headLights) { | |
light.Enabled = false; | |
} | |
} else { | |
_timeIdle = TimeSpan.Zero; | |
foreach (var light in _headLights) { | |
light.Enabled = true; | |
} | |
} | |
} | |
if (_antenna != null) { | |
bool nearEmpty = (fuelPercentage < 300); | |
_antenna.Enabled = !nearEmpty; | |
} | |
if (_generator != null) { | |
if (_batteries.Count() > 1) { | |
if (_generator.Enabled) { | |
if (powerPercentage == 100) | |
_generator.Enabled = false; | |
if (powerPercentage > 5) { | |
foreach (var battery in _batteries) { | |
if (battery.ChargeMode == ChargeMode.Recharge) | |
battery.ChargeMode = ChargeMode.Auto; | |
} | |
} | |
} else { | |
if (powerPercentage < 80) | |
_generator.Enabled = true; | |
} | |
} else { | |
_generator.Enabled = true; | |
} | |
} | |
if (_splitter != null) { | |
if (_tanks.Count() > 1) { | |
if (_splitter.Enabled) { | |
if (hydrogenPercentage == 100) | |
_splitter.Enabled = false; | |
} else { | |
if (hydrogenPercentage < 100) | |
_splitter.Enabled = true; | |
} | |
} else { | |
_splitter.Enabled = true; | |
} | |
} | |
if (powerPercentage < 5) { | |
if (_cockpit != null && !_cockpit.IsUnderControl) { | |
foreach (var battery in _batteries) | |
battery.ChargeMode = ChargeMode.Recharge; | |
} | |
} | |
if (_cockpit.IsUnderControl) | |
_timeIdle = TimeSpan.Zero; | |
if (_autoPowerSave && _timeIdle.TotalSeconds > 600) { | |
foreach (var battery in _batteries) { | |
battery.ChargeMode = ChargeMode.Auto; | |
} | |
_timeIdle = TimeSpan.Zero; | |
} | |
DrawCockpitScreen(hydrogen / _fuelTankSize, ice / _fuelTankSize, -1, -1); | |
} | |
private MySprite CreateBar(double offset, double angleDegrees, double start, double end, double width, Color color) | |
{ | |
if (start < -0.2f) | |
start = -0.2f; | |
double borderTop = 0; | |
double borderBottom = 0.055; | |
start = (start - borderTop) / (1 + borderBottom) + borderTop; | |
end = (end - borderTop) / (1 + borderBottom) + borderTop; | |
double radianAngle = angleDegrees / 180.0 * Math.PI; | |
float midY = (float)((start + end) / 2.0 * _viewport.Height) + _viewport.Y; | |
float midX = (float)offset - (float)(Math.Tan(radianAngle) * _viewport.Width * (start + end) / 4.0) + _viewport.X; | |
float maxHeight = (float)(_viewport.Height / Math.Cos(radianAngle)); | |
float rotatedHeight = (float)(maxHeight * (end - start)); | |
float rotatedWidth = (float)(_viewport.Width * width); | |
return new MySprite() { | |
Type = SpriteType.TEXTURE, | |
Data = "White screen", | |
Position = new Vector2(midX, midY), | |
Size = new Vector2(rotatedWidth, rotatedHeight), | |
Color = color, | |
Alignment = TextAlignment.CENTER, | |
RotationOrScale = (float)radianAngle, | |
}; | |
} | |
private void DrawCockpitScreen(double hydrogen, double fuel, int mainAmmo, int autoAmmo) { | |
if (_cockpit == null) | |
return; | |
if (!_cockpit.IsUnderControl) | |
return; | |
if (_cockpitSurface == null) | |
return; | |
using (var frame = _cockpitSurface.DrawFrame()) { | |
var bgSprite = new MySprite() { | |
Type = SpriteType.TEXTURE, | |
Data = "Grid", | |
Position = _viewport.Center, | |
Size = _viewport.Size, | |
Color = _cockpitSurface.ScriptForegroundColor.Alpha(0.66f), | |
Alignment = TextAlignment.CENTER | |
}; | |
frame.Add(bgSprite); | |
if (_uptime.TotalSeconds < 5) { | |
frame.Add(MySprite.CreateText("Wasp OS", "White", _cockpitSurface.ScriptForegroundColor, 1.0f, TextAlignment.CENTER)); | |
return; | |
} | |
frame.Add(CreateBar(72, 30, 1.0 - fuel, 1.0, 1.0 / 20.0, _cockpitSurface.ScriptForegroundColor)); | |
Color hydrogenColor = new Color(_cockpitSurface.ScriptForegroundColor.R, _cockpitSurface.ScriptForegroundColor.G, 255 - _cockpitSurface.ScriptForegroundColor.B); | |
frame.Add(CreateBar(72, 30, 1.0 - hydrogen, 1.0, 1.0 / 20.0, hydrogenColor)); | |
frame.Add(CreateBar(188, -30, 1.0 - (fuel / 25.0), 1.0, 1.0 / 20.0, _cockpitSurface.ScriptForegroundColor)); | |
int velocity = (int)Math.Round(_cockpit.GetShipVelocities().LinearVelocity.Length()); | |
frame.Add(new MySprite() { | |
Type = SpriteType.TEXT, | |
Data = velocity.ToString(), | |
Position = new Vector2(_viewport.X + _viewport.Width / 2.0f, _viewport.Y + 32f), | |
FontId = "White", | |
Color = _cockpitSurface.ScriptForegroundColor, | |
RotationOrScale = 1.0f, | |
Alignment = TextAlignment.CENTER | |
}); | |
} | |
} | |
public void Main(string argument, UpdateType updateSource) | |
{ | |
_uptime += Runtime.TimeSinceLastRun; | |
_timeIdle += Runtime.TimeSinceLastRun; | |
if (Runtime.TimeSinceLastRun.TotalSeconds > 5.0) { | |
_uptime = TimeSpan.Zero; | |
ReInit(); | |
} | |
if ((updateSource & UpdateType.Update10) != 0) { | |
DoHousekeeping(); | |
} | |
if (argument == "toggle_fork") { | |
if (!_isInconsistent && _bottomLeftMerge != null && _topLeftMerge != null && _bottomRightMerge != null && _topRightMerge != null) { | |
if (_isDeployed) { | |
_isDeploying = false; | |
_isStowing = true; | |
_lastDeployAction = _uptime; | |
_leftHinge.UpperLimitDeg = 0; | |
_rightHinge.UpperLimitDeg = 0; | |
_leftHinge.TargetVelocityRPM = 5; | |
_rightHinge.TargetVelocityRPM = 5; | |
_topLeftMerge.Enabled = true; | |
_topRightMerge.Enabled = true; | |
} else { | |
_isDeploying = true; | |
_isStowing = false; | |
_lastDeployAction = _uptime; | |
_bottomLeftMerge.Enabled = true; | |
_bottomRightMerge.Enabled = true; | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ItemTarget { | |
public ItemTarget(string category, string subtype, string blueprintCategory, string blueprintSubtype, long destCount) | |
{ | |
Type = new MyItemType(category, subtype); | |
Blueprint = MyDefinitionId.Parse(blueprintCategory + "/" + blueprintSubtype); | |
DestCount = destCount; | |
} | |
public ItemTarget(MyItemType type, long destCount) | |
{ | |
Type = type; | |
DestCount = destCount; | |
} | |
public MyItemType Type; | |
public long DestCount; | |
public long Count; | |
public List<IMyProductionBlock> ProductionBlocks = new List<IMyProductionBlock>(); | |
public MyDefinitionId Blueprint; | |
} | |
List<ItemTarget> _targets = new List<ItemTarget>() { | |
new ItemTarget("MyObjectBuilder_Component", "SteelPlate", "MyObjectBuilder_BlueprintDefinition", "POSteelPlate", 3000), | |
new ItemTarget("MyObjectBuilder_Component", "TitaniumPlate", "MyObjectBuilder_BlueprintDefinition", "TitaniumPlate", 200), | |
new ItemTarget("MyObjectBuilder_Component", "CopperWire", "MyObjectBuilder_BlueprintDefinition", "CopperWire", 1000), | |
new ItemTarget("MyObjectBuilder_Component", "GoldWire", "MyObjectBuilder_BlueprintDefinition", "GoldWire", 500), | |
new ItemTarget("MyObjectBuilder_Component", "LargeTube", "MyObjectBuilder_BlueprintDefinition", "POLargeTube", 400), | |
new ItemTarget("MyObjectBuilder_Component", "SmallTube", "MyObjectBuilder_BlueprintDefinition", "POSmallTube", 400), | |
new ItemTarget("MyObjectBuilder_Component", "Electromagnet", "MyObjectBuilder_BlueprintDefinition", "Electromagnet", 300), | |
new ItemTarget("MyObjectBuilder_Component", "Motor", "MyObjectBuilder_BlueprintDefinition", "POMotorComponent", 300), | |
new ItemTarget("MyObjectBuilder_Component", "Computer", "MyObjectBuilder_BlueprintDefinition", "POComputerComponent", 300), | |
new ItemTarget("MyObjectBuilder_Component", "AdvancedComputer", "MyObjectBuilder_BlueprintDefinition", "AdvancedComputer", 300), | |
new ItemTarget("MyObjectBuilder_Component", "Construction", "MyObjectBuilder_BlueprintDefinition", "POConstructionComponent", 1000), | |
new ItemTarget("MyObjectBuilder_Component", "MetalGrid", "MyObjectBuilder_BlueprintDefinition", "POMetalGrid", 100), | |
new ItemTarget("MyObjectBuilder_Component", "Girder", "MyObjectBuilder_BlueprintDefinition", "GirderComponent", 100), | |
new ItemTarget("MyObjectBuilder_Component", "Display", "MyObjectBuilder_BlueprintDefinition", "PODisplay", 50), | |
new ItemTarget("MyObjectBuilder_Component", "Rubber", "MyObjectBuilder_BlueprintDefinition", "Rubber", 500), | |
new ItemTarget("MyObjectBuilder_Component", "Lightbulb", "MyObjectBuilder_BlueprintDefinition", "Lightbulb", 10), | |
new ItemTarget("MyObjectBuilder_Component", "Ceramic", "MyObjectBuilder_BlueprintDefinition", "Ceramic", 100), | |
new ItemTarget("MyObjectBuilder_Component", "HeatingElement", "MyObjectBuilder_BlueprintDefinition", "HeatingElement", 100), | |
}; | |
List<MyItemType> _ignoreList = new List<MyItemType>() { | |
}; | |
List<IMyInventory> _inventories = new List<IMyInventory>(); | |
List<MyProductionItem> _tmpQueue = new List<MyProductionItem>(); | |
IMyTextSurface _statusSurface; | |
TimeSpan _uptime = TimeSpan.Zero; | |
private void ReInit() | |
{ | |
_statusSurface = Me.GetSurface(0); | |
List<IMyTerminalBlock> inventoryEntities = new List<IMyTerminalBlock>(); | |
GridTerminalSystem.GetBlocksOfType(inventoryEntities, b => b.IsSameConstructAs(Me)); | |
List<IMyProductionBlock> productionBlocks = new List<IMyProductionBlock>(); | |
GridTerminalSystem.GetBlocksOfType(productionBlocks, b => b.IsSameConstructAs(Me)); | |
_inventories.Clear(); | |
foreach (var block in inventoryEntities) { | |
if (productionBlocks.Contains(block)) { | |
if (block.InventoryCount != 2) { | |
Echo(block.ToString() + " has " + block.InventoryCount.ToString() + " inventories!"); | |
} else { | |
_inventories.Add(block.GetInventory(1)); | |
} | |
} else { | |
for (int i = 0; i < block.InventoryCount; i++) | |
_inventories.Add(block.GetInventory(i)); | |
} | |
} | |
foreach (var target in _targets) { | |
target.ProductionBlocks.Clear(); | |
} | |
foreach (var block in productionBlocks) { | |
foreach (var target in _targets) { | |
if (block.CanUseBlueprint(target.Blueprint)) | |
target.ProductionBlocks.Add(block); | |
} | |
//if (block.CustomName == "Assembler") { | |
// _tmpQueue.Clear(); | |
// block.GetQueue(_tmpQueue); | |
// foreach (var item in _tmpQueue) { | |
// Echo(item.BlueprintId.ToString()); | |
// } | |
//} | |
} | |
} | |
public Program() | |
{ | |
Runtime.UpdateFrequency = UpdateFrequency.Update100; | |
ReInit(); | |
} | |
private void DoHousekeeping() | |
{ | |
foreach (var target in _targets) { | |
target.Count = 0; | |
} | |
foreach (var inventory in _inventories) { | |
foreach (var target in _targets) { | |
var amount = inventory.GetItemAmount(target.Type); | |
target.Count += (long)amount; | |
} | |
} | |
foreach (var target in _targets) { | |
if (target.Count < target.DestCount) { | |
long remaining = target.DestCount - target.Count; | |
long inProgress = 0; | |
foreach (var block in target.ProductionBlocks) { | |
_tmpQueue.Clear(); | |
block.GetQueue(_tmpQueue); | |
foreach (var item in _tmpQueue) { | |
if (item.BlueprintId == target.Blueprint) | |
inProgress += (long)item.Amount; | |
} | |
} | |
long needed = Math.Min(10 * target.ProductionBlocks.Count(), remaining); | |
if (needed > inProgress) { | |
long left = needed - inProgress; | |
foreach (var block in target.ProductionBlocks) { | |
long available = 10; | |
_tmpQueue.Clear(); | |
block.GetQueue(_tmpQueue); | |
foreach (var item in _tmpQueue) { | |
if (item.BlueprintId == target.Blueprint) | |
available -= (long)item.Amount; | |
} | |
if (available > 0) { | |
block.AddQueueItem(target.Blueprint, (double)available); | |
left -= available; | |
} | |
} | |
} | |
if (target.ProductionBlocks.Count() == 0) { | |
Echo(target.Type.SubtypeId + " has no producers!"); | |
} else { | |
Echo(target.Type.SubtypeId + ": " + remaining.ToString()); | |
} | |
} | |
} | |
} | |
public void Main(string argument, UpdateType updateSource) | |
{ | |
_uptime += Runtime.TimeSinceLastRun; | |
if (Runtime.TimeSinceLastRun.TotalSeconds > 5.0) { | |
_uptime = TimeSpan.Zero; | |
ReInit(); | |
} | |
if ((updateSource & UpdateType.Update100) != 0) { | |
DoHousekeeping(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
TimeSpan _uptime = TimeSpan.Zero; | |
IMyBroadcastListener _channel; | |
List<IMyShipConnector> _connectors = new List<IMyShipConnector>(); | |
private void ReInit() | |
{ | |
_channel = IGC.RegisterBroadcastListener("nl.maxmaton.miningv1.docking.request"); | |
_channel.SetMessageCallback("igc-interrupt"); | |
GridTerminalSystem.GetBlocksOfType(_connectors, b => b.CustomData == "nl.maxmaton.miningv1.connector"); | |
} | |
public Program() | |
{ | |
Runtime.UpdateFrequency = UpdateFrequency.None; | |
ReInit(); | |
} | |
private void DoHousekeeping() | |
{ | |
} | |
private void HandleComms() { | |
while (_channel.HasPendingMessage) { | |
var message = _channel.AcceptMessage(); | |
var connector = _connectors[0]; | |
var pos = connector.GetPosition(); | |
var facing = connector.WorldMatrix.Forward; | |
double[] numbers = new double[] { | |
pos.X, | |
pos.Y, | |
pos.Z, | |
facing.X, | |
facing.Y, | |
facing.Z | |
}; | |
var response = string.Join("|", numbers.Select((a) => a.ToString())); | |
IGC.SendUnicastMessage(message.Source, "nl.maxmaton.miningv1.docking.response", response); | |
} | |
} | |
public void Main(string argument, UpdateType updateSource) | |
{ | |
_uptime += Runtime.TimeSinceLastRun; | |
if (Runtime.TimeSinceLastRun.TotalSeconds > 5.0) { | |
_uptime = TimeSpan.Zero; | |
ReInit(); | |
} | |
if ((updateSource & UpdateType.Update100) != 0) { | |
DoHousekeeping(); | |
} | |
if (argument == "igc-interrupt") | |
HandleComms(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class PID { | |
private double P; | |
private double I; | |
private double D; | |
private double _maxErrorSum; | |
private double _errorSum; | |
private double _lastValue; | |
private TimeSpan _lastTime; | |
private bool _hasData; | |
private double _setpoint; | |
public double SetPoint { | |
get { return _setpoint; } | |
set { | |
if (_setpoint != value) { | |
_setpoint = value; | |
Reset(); | |
} | |
} | |
} | |
public PID(double p, double i, double d, double maxErrorSum = 1.0) { | |
P = p; | |
I = i; | |
D = d; | |
_maxErrorSum = maxErrorSum; | |
} | |
public void Reset() { | |
_errorSum = 0; | |
_lastTime = TimeSpan.Zero; | |
_lastValue = 0; | |
_hasData = false; | |
} | |
public double Step(TimeSpan currentTime, double curval) { | |
double error = _setpoint - curval; | |
double result = P * error + I * _errorSum; | |
if (_hasData) { | |
double lastError = _setpoint - _lastValue; | |
double totalSeconds = (currentTime - _lastTime).TotalSeconds; | |
if (totalSeconds > 2) { | |
result -= I * _errorSum; | |
_errorSum = 0; | |
} else { | |
double deltaError = error - lastError; | |
result += D * deltaError; | |
_errorSum += error * totalSeconds; | |
if (_errorSum > _maxErrorSum) | |
_errorSum = _maxErrorSum; | |
if (_errorSum < -_maxErrorSum) | |
_errorSum = -_maxErrorSum; | |
} | |
} | |
_lastTime = currentTime; | |
_lastValue = curval; | |
_hasData = true; | |
return result; | |
} | |
} | |
class AttitudeController { | |
public IMyShipController Controller { get; private set; } | |
public bool CanOverrideUser { get; set; } | |
public Vector3D DesiredForward { | |
get { return _desiredForward; } | |
set { | |
if (value == Vector3D.Zero) | |
_desiredForward = Vector3D.Zero; | |
else { | |
Vector3D newForward = Vector3D.Normalize(value); | |
if (newForward != _desiredForward) { | |
_desiredForward = newForward; | |
_yawController.Reset(); | |
_pitchController.Reset(); | |
_rollController.Reset(); | |
} | |
} | |
ComputeAligned(); | |
} | |
} | |
public Vector3D DesiredUp { | |
get { return _desiredUp; } | |
set { | |
if (value == Vector3D.Zero) | |
_desiredUp = Vector3D.Zero; | |
else { | |
Vector3D newUp = Vector3D.Normalize(value); | |
if (newUp != _desiredUp) { | |
_desiredUp = newUp; | |
_rollController.Reset(); | |
} | |
} | |
ComputeAligned(); | |
} | |
} | |
public bool IsAligned { get; private set; } | |
private List<IMyGyro> _gyros = null; | |
private Vector3D _desiredForward; | |
private Vector3D _desiredUp; | |
private double _alignmentBoundary = 0.99; | |
private bool _forwardAligned; | |
private PID _yawController; | |
private PID _pitchController; | |
private PID _rollController; | |
public AttitudeController(IMyShipController controller, List<IMyGyro> gyros) { | |
Controller = controller; | |
_gyros = gyros; | |
if (gyros.Count() == 0) | |
throw new Exception("Not enough gyros"); | |
_yawController = new PID(1, 0, 0); | |
_pitchController = new PID(1, 0, 0); | |
_rollController = new PID(1, 0, 0); | |
ComputeAligned(); | |
} | |
public void ComputeAligned() { | |
IsAligned = true; | |
_forwardAligned = true; | |
if (DesiredForward != Vector3D.Zero) { | |
Vector3D ShipForward = Controller.WorldMatrix.Forward; | |
double forwardAlignment = Vector3D.Dot(ShipForward, DesiredForward); | |
if (forwardAlignment < _alignmentBoundary) { | |
IsAligned = false; | |
_forwardAligned = false; | |
return; | |
} | |
if (DesiredUp != Vector3D.Zero) { | |
Vector3D ShipUp = Controller.WorldMatrix.Up; | |
double upAlignment = Vector3D.Dot(ShipUp, DesiredUp); | |
if (forwardAlignment < _alignmentBoundary) { | |
IsAligned = false; | |
return; | |
} | |
} | |
} | |
} | |
public Vector3D ComputeRotation(TimeSpan currentTime) { | |
double yaw = 0; | |
double pitch = 0; | |
double roll = 0; | |
Vector3D ShipForward = Controller.WorldMatrix.Forward; | |
Vector3D ShipUp = Controller.WorldMatrix.Up; | |
Vector3D ShipLeft = Vector3D.Cross(ShipForward, ShipUp); | |
if (_forwardAligned) { | |
double desiredRoll = -Vector3D.Dot(ShipLeft, DesiredUp); | |
roll = _rollController.Step(currentTime, desiredRoll); | |
} else { | |
_rollController.Reset(); | |
} | |
double desiredPitch = Vector3D.Dot(ShipUp, DesiredForward); | |
pitch = _pitchController.Step(currentTime, desiredPitch); | |
double desiredYaw = -Vector3D.Dot(ShipLeft, DesiredForward); | |
yaw = _yawController.Step(currentTime, desiredYaw); | |
return new Vector3D(pitch, yaw, roll); | |
} | |
public void Tick(TimeSpan currentTime) { | |
ComputeAligned(); | |
Vector3D rotation = ComputeRotation(currentTime); | |
if (Controller.IsUnderControl) { | |
foreach (var gyro in _gyros) { | |
gyro.GyroOverride = false; | |
} | |
} else { | |
var Vector = Vector3.Transform(rotation, Controller.WorldMatrix.GetOrientation()); //Converts To World | |
foreach (var gyro in _gyros) { | |
gyro.GyroOverride = true; | |
var TRANS_VECT = Vector3.Transform(Vector, Matrix.Transpose(gyro.WorldMatrix.GetOrientation())); //Converts To Gyro Local | |
gyro.Pitch = (float)TRANS_VECT.X; | |
gyro.Yaw = (float)TRANS_VECT.Y; | |
gyro.Roll = (float)TRANS_VECT.Z; | |
} | |
} | |
} | |
} | |
class VelocityController { | |
IMyShipController _controller; | |
List<IMyThrust> _thrusters; | |
PID _xController; | |
PID _yController; | |
PID _zController; | |
Vector3D _desiredSpeed; | |
public Vector3D DesiredSpeed { | |
get { return _desiredSpeed; } | |
set { | |
_desiredSpeed = value; | |
_xController.SetPoint = value.X; | |
_yController.SetPoint = value.Y; | |
_zController.SetPoint = value.Z; | |
} | |
} | |
public VelocityController(IMyShipController controller, List<IMyThrust> thrusters) { | |
_controller = controller; | |
_thrusters = thrusters; | |
_xController = new PID(2, 0.1, 0.1, 100); | |
_yController = new PID(2, 0.1, 0.1, 100); | |
_zController = new PID(2, 0.1, 0.1, 100); | |
} | |
public void Reset() { | |
_xController.Reset(); | |
_yController.Reset(); | |
_zController.Reset(); | |
} | |
public Vector3D ComputeThrust(TimeSpan currentTime) { | |
double weight = _controller.CalculateShipMass().PhysicalMass; | |
var velocities = _controller.GetShipVelocities().LinearVelocity; | |
double x = _xController.Step(currentTime, velocities.X); | |
double y = _yController.Step(currentTime, velocities.Y); | |
double z = _zController.Step(currentTime, velocities.Z); | |
return new Vector3D(x, y, z) * weight; | |
} | |
public void Tick(TimeSpan currentTime) { | |
var desiredThrust = ComputeThrust(currentTime); | |
var RC_Matrix = _controller.WorldMatrix.GetOrientation(); | |
var desiredThrustWorld = Vector3.Transform(desiredThrust, RC_Matrix); | |
if (_desiredSpeed == Vector3D.Zero || _controller.IsUnderControl) { | |
_controller.DampenersOverride = true; | |
foreach (var thruster in _thrusters) { | |
thruster.ThrustOverride = 0; | |
} | |
Reset(); | |
} else { | |
_controller.DampenersOverride = false; | |
foreach (var thruster in _thrusters) { | |
thruster.ThrustOverride = -(float)Vector3D.Dot(desiredThrust, thruster.WorldMatrix.Forward); | |
} | |
} | |
} | |
} | |
class MiningState { | |
public class Lane { | |
public int X { get; private set; } | |
public int Y { get; private set; } | |
public Vector3D StartPos { get; private set; } | |
public Vector3D EndPos { get; private set; } | |
public Lane(int x, int y, Vector3D startPos, Vector3D endPos) { | |
X = x; | |
Y = y; | |
StartPos = startPos; | |
EndPos = endPos; | |
} | |
} | |
public string State { get; set; } | |
long _entityId; | |
public Vector3D Mins { get; private set; } | |
public Vector3D Maxs { get; private set; } | |
public Vector3D DockConnectorPosition { get; set; } | |
public Vector3D DockConnectorForward { get; set; } | |
double _shipWidth; | |
double _shipHeight; | |
string[] _laneDone; | |
int curx = 0; | |
int cury = 0; | |
int curScanY = 0; | |
int lanesDoneCount = 0; | |
public MiningState(string state, long entityId, Vector3D mins, Vector3D maxs, double shipWidth, double shipHeight, string laneState, Vector3D connectorPos, Vector3D connectorNormal) { | |
State = state; | |
_entityId = entityId; | |
Mins = mins; | |
Maxs = maxs; | |
_shipWidth = shipWidth; | |
_shipHeight = shipHeight; | |
string[] slices = laneState.Split('|'); | |
int width = slices[0].Length; | |
_laneDone = new string[slices.Count()]; | |
for (int i = 0; i < slices.Count(); i++) { | |
_laneDone[i] = slices[i]; | |
} | |
DockConnectorPosition = connectorPos; | |
DockConnectorForward = connectorNormal; | |
} | |
public MiningState(IMyShipController controller, IMyGridTerminalSystem GridTerminalSystem, MyDetectedEntityInfo asteroid) { | |
State = "init"; | |
_entityId = asteroid.EntityId; | |
Mins = asteroid.BoundingBox.Min; | |
Maxs = asteroid.BoundingBox.Max; | |
List<IMyShipDrill> drills = new List<IMyShipDrill>(); | |
GridTerminalSystem.GetBlocksOfType(drills, b => b.IsSameConstructAs(controller)); | |
double DistToDrill = Math.Sqrt(drills.Count)*0.9; //Size of Ship | |
if (controller.CubeGrid.ToString().Contains("Large")) //if large grid | |
DistToDrill = DistToDrill * 1.5; | |
_shipWidth = DistToDrill; //Wrong but usable | |
_shipHeight = DistToDrill; //Wrong but usable; | |
double asteroidWidth = asteroid.BoundingBox.Size.X; | |
double asteroidHeight = asteroid.BoundingBox.Size.Z; | |
if (_shipWidth <= 0 || _shipHeight <= 0) { | |
throw new Exception("Unable to mine without drills"); | |
} | |
int laneWidth = (int)Math.Ceiling(asteroidWidth / _shipWidth); | |
int laneHeight = (int)Math.Ceiling(asteroidHeight / _shipHeight); | |
_laneDone = new string[laneHeight]; | |
for (int i = 0; i < laneHeight; i++) { | |
_laneDone[i] = new String(' ', laneWidth); | |
} | |
} | |
public static MiningState FromSaveData(string saveData) { | |
var lines = saveData.Split('\n'); | |
string state = lines[0]; | |
long entityId = long.Parse(lines[1]); | |
var minsParts = lines[2].Split('|'); | |
Vector3D mins = new Vector3D(double.Parse(minsParts[0]), double.Parse(minsParts[1]), double.Parse(minsParts[2])); | |
var maxsParts = lines[3].Split('|'); | |
Vector3D maxs = new Vector3D(double.Parse(maxsParts[0]), double.Parse(maxsParts[1]), double.Parse(maxsParts[2])); | |
double shipWidth = double.Parse(lines[4]); | |
double shipHeight = double.Parse(lines[5]); | |
string laneState = lines[6]; | |
var connectorPosParts = lines[7].Split('|'); | |
Vector3D connectorPos = new Vector3D(double.Parse(connectorPosParts[0]), double.Parse(connectorPosParts[1]), double.Parse(connectorPosParts[2])); | |
var connectorNormParts = lines[8].Split('|'); | |
Vector3D connectorNormal = new Vector3D(double.Parse(connectorNormParts[0]), double.Parse(connectorNormParts[1]), double.Parse(connectorNormParts[2])); | |
if (state != "init" && state != "drain") | |
state = "init"; | |
return new MiningState(state, entityId, mins, maxs, shipWidth, shipHeight, laneState, connectorPos, connectorNormal); | |
} | |
public int LaneCount { | |
get { return _laneDone.Length * _laneDone[0].Length; } | |
} | |
public int LanesDone { | |
get { | |
if (curScanY < _laneDone.Length) { | |
var line = _laneDone[curScanY]; | |
curScanY++; | |
lanesDoneCount += line.Count(c => !Char.IsWhiteSpace(c)); | |
} | |
return lanesDoneCount; | |
} | |
} | |
public Lane NextLane { | |
get { | |
int iterationCount = 0; | |
for (int y = cury; y < _laneDone.Length; y++) { | |
var line = _laneDone[y]; | |
for (int x = curx; x < line.Length; x++) { | |
if (line[x] == 'x') { | |
iterationCount++; | |
if (iterationCount > 1000) | |
{ | |
cury = y; | |
curx = x; | |
return null; | |
} | |
continue; | |
} | |
Vector3D startPos = Maxs - y * new Vector3D(0, 0, _shipHeight) - x * new Vector3D(_shipWidth, 0, 0) - new Vector3D(0, _shipWidth * 10, 0); | |
Vector3D endPos = new Vector3D(startPos.X, Mins.Y - _shipWidth * 10, startPos.Z); | |
cury = y; | |
curx = x; | |
return new Lane(x, y, startPos, endPos); | |
} | |
curx = 0; | |
} | |
return null; | |
} | |
} | |
public void Finish(Lane lane) { | |
Finish(lane.X, lane.Y); | |
} | |
public void Finish(int x, int y) { | |
if (y < curScanY && _laneDone[y][x] != 'x') | |
lanesDoneCount++; | |
var line = _laneDone[y]; | |
var prefix = line.Substring(0, x); | |
var postfix = line.Substring(x + 1); | |
_laneDone[y] = prefix + "x" + postfix; | |
if (line.Length != _laneDone[y].Length) | |
throw new Exception("Bad programmer"); | |
} | |
public string SaveData { | |
get { | |
string[] lines = new string[]{ | |
State, | |
_entityId.ToString(), | |
Mins.X.ToString() + "|" + Mins.Y.ToString() + "|" + Mins.Z.ToString(), | |
Maxs.X.ToString() + "|" + Maxs.Y.ToString() + "|" + Maxs.Z.ToString(), | |
_shipWidth.ToString(), | |
_shipHeight.ToString(), | |
string.Join("|", _laneDone), | |
DockConnectorPosition.X.ToString() + "|" + DockConnectorPosition.Y.ToString() + "|" + DockConnectorPosition.Z.ToString(), | |
DockConnectorForward.X.ToString() + "|" + DockConnectorForward.Y.ToString() + "|" + DockConnectorForward.Z.ToString() | |
}; | |
return string.Join("\n", lines); | |
} | |
} | |
} | |
class SpaceStripMiner { | |
AttitudeController _attitude; | |
VelocityController _velocity; | |
IMyShipController _controller; | |
MiningState _state; | |
IMyCameraBlock _camera; | |
MiningState.Lane _lane; | |
List<IMyInventory> _inventories; | |
List<IMyShipDrill> _drills; | |
IMyShipConnector _connector; | |
IMyGridTerminalSystem GridTerminalSystem { get; set; } | |
List<IMyCargoContainer> _drainInventories = new List<IMyCargoContainer>(); | |
public Func<bool> CanUndock { get; set; } | |
const double TRANSIT_HEIGHT = 20.0; | |
const double CRUISE_SPEED = 10.0; | |
const double MINING_SPEED = 2.0; | |
const double DOCKING_DISTANCE = 25.0; | |
public SpaceStripMiner(IMyShipController controller, IMyGridTerminalSystem GridTerminalSystem, List<IMyThrust> thrusters, List<IMyGyro> gyros, List<IMyInventory> inventories, List<IMyShipDrill> drills, IMyCameraBlock camera, IMyShipConnector connector, MyDetectedEntityInfo asteroid) { | |
_controller = controller; | |
_camera = camera; | |
_attitude = new AttitudeController(controller, gyros); | |
_velocity = new VelocityController(controller, thrusters); | |
_state = new MiningState(controller, GridTerminalSystem, asteroid); | |
if (connector.Status == MyShipConnectorStatus.Connected) | |
_state.State = "drain"; | |
_inventories = inventories; | |
_drills = drills; | |
_connector = connector; | |
this.GridTerminalSystem = GridTerminalSystem; | |
} | |
public SpaceStripMiner(IMyShipController controller, IMyGridTerminalSystem GridTerminalSystem, List<IMyThrust> thrusters, List<IMyGyro> gyros, List<IMyInventory> inventories, List<IMyShipDrill> drills, IMyCameraBlock camera, IMyShipConnector connector, string saveData) { | |
_controller = controller; | |
_camera = camera; | |
_attitude = new AttitudeController(controller, gyros); | |
_velocity = new VelocityController(controller, thrusters); | |
_state = MiningState.FromSaveData(saveData); | |
if (connector.Status == MyShipConnectorStatus.Connected) | |
_state.State = "drain"; | |
_inventories = inventories; | |
_drills = drills; | |
_connector = connector; | |
this.GridTerminalSystem = GridTerminalSystem; | |
} | |
public void SeedConnectorData(Vector3D connectorPos, Vector3D connectorFacing) { | |
_state.DockConnectorPosition = connectorPos; | |
_state.DockConnectorForward = connectorFacing; | |
} | |
public string SaveData { | |
get { return _state.SaveData; } | |
} | |
public void Tick(TimeSpan currentTime, Action<string> Echo) { | |
Echo("State: " + _state.State); | |
Echo("Progress: " + _state.LanesDone.ToString() + "/" + _state.LaneCount.ToString()); | |
switch (_state.State) { | |
case "init": | |
InitState(Echo); | |
break; | |
case "realign": | |
RealignState(Echo); | |
break; | |
case "lower": | |
LowerState(Echo); | |
break; | |
case "mine": | |
MineState(Echo); | |
break; | |
case "return": | |
ReturnState(Echo); | |
break; | |
case "dock": | |
DockState(Echo); | |
break; | |
case "drain": | |
DrainState(Echo); | |
break; | |
case "undock": | |
UndockState(Echo); | |
break; | |
} | |
_attitude.Tick(currentTime); | |
_velocity.Tick(currentTime); | |
} | |
public bool IsInventoryFull { | |
get { | |
double totalVolume = 0.001; | |
double usedVolume = 0.001; | |
foreach (var inv in _inventories) { | |
totalVolume += (double)inv.MaxVolume; | |
usedVolume += (double)inv.CurrentVolume; | |
} | |
return usedVolume / totalVolume > 0.95; | |
} | |
} | |
void InitState(Action<string> Echo) { | |
foreach (var drill in _drills) { | |
drill.Enabled = false; | |
} | |
double metersLeft = _state.Maxs.Z + TRANSIT_HEIGHT - _controller.GetPosition().Z; | |
if (metersLeft < 0) { | |
_state.State = "realign"; | |
_velocity.DesiredSpeed = Vector3D.Zero; | |
_attitude.DesiredForward = Vector3D.Zero; | |
return; | |
} | |
Echo("Distance: " + Math.Ceiling(metersLeft).ToString()); | |
_attitude.DesiredForward = Vector3D.Zero; | |
if (!_attitude.IsAligned) { | |
_velocity.DesiredSpeed = Vector3D.Zero; | |
} else { | |
_velocity.DesiredSpeed = new Vector3D(0, 0, CRUISE_SPEED); | |
} | |
} | |
void RealignState(Action<string> Echo) { | |
if (IsInventoryFull) { | |
_state.State = "return"; | |
return; | |
} | |
if (_lane == null) { | |
Echo ("Computing next lane"); | |
_lane = _state.NextLane; | |
if (_lane == null) | |
return; // Staggered computation | |
} | |
var dest = new Vector3D(_lane.StartPos.X, _lane.StartPos.Y, _state.Maxs.Z + TRANSIT_HEIGHT); | |
var arrow = dest - _controller.GetPosition(); | |
var distance = arrow.Length(); | |
Echo("Distance: " + Math.Ceiling(distance).ToString()); | |
if (distance < 1) { | |
_state.State = "lower"; | |
_velocity.DesiredSpeed = Vector3D.Zero; | |
_attitude.DesiredForward = Vector3D.Zero; | |
return; | |
} | |
var dir = arrow / Math.Max(distance, 1); | |
if (distance > 100) | |
_attitude.DesiredForward = arrow; | |
_velocity.DesiredSpeed = dir * Math.Min(distance / 2, CRUISE_SPEED); | |
} | |
void LowerState(Action<string> Echo) { | |
var dest = _lane.StartPos; | |
var arrow = dest - _controller.GetPosition(); | |
var distance = arrow.Length(); | |
_camera.EnableRaycast = true; | |
Echo("Distance: " + Math.Ceiling(distance).ToString()); | |
if (distance < 1) { | |
_state.State = "mine"; | |
_velocity.DesiredSpeed = Vector3D.Zero; | |
var distToEnd = (_lane.EndPos - _controller.GetPosition()).Length(); | |
if (_camera.AvailableScanRange < distToEnd) { | |
Echo("Charging camera: " + Math.Floor(_camera.AvailableScanRange / distToEnd * 100).ToString() + "%"); | |
return; | |
} | |
var raycastResult = _camera.Raycast(_lane.EndPos); | |
if (raycastResult.Type == MyDetectedEntityType.None) { | |
_state.Finish(_lane); | |
var startDist = (_lane.StartPos - _controller.GetPosition()).Length(); | |
if (startDist < 5) { | |
var lastY = _lane.Y; | |
_lane = _state.NextLane; | |
if (_lane.Y == lastY) | |
_state.State = "lower"; | |
else | |
_state.State = "init"; | |
return; | |
} | |
_lane = null; | |
_state.State = "init"; | |
_camera.EnableRaycast = false; | |
} | |
return; | |
} | |
_attitude.DesiredForward = new Vector3D(0, -1, 0); | |
_attitude.DesiredUp = new Vector3D(0, 0, 1); | |
if (_attitude.IsAligned) { | |
_velocity.DesiredSpeed = Vector3D.Normalize(arrow); | |
} else { | |
_velocity.DesiredSpeed = Vector3D.Zero; | |
} | |
} | |
void MineState(Action<string> Echo) { | |
if (IsInventoryFull) { | |
_state.State = "init"; | |
foreach (var drill in _drills) { | |
drill.Enabled = false; | |
} | |
return; | |
} | |
foreach (var drill in _drills) { | |
drill.Enabled = true; | |
} | |
var dest = _lane.EndPos; | |
var arrow = dest - _controller.GetPosition(); | |
var distance = arrow.Length(); | |
Echo ("Distance: " + Math.Ceiling(distance).ToString()); | |
if (distance < 1) { | |
_state.Finish(_lane); | |
_state.State = "init"; | |
foreach (var drill in _drills) { | |
drill.Enabled = false; | |
} | |
return; | |
} | |
var speed = Vector3D.Normalize(new Vector3D(arrow.X, -MINING_SPEED, arrow.Z)); | |
_velocity.DesiredSpeed = speed; | |
} | |
void ReturnState(Action<string> Echo) { | |
if (_connector.Status == MyShipConnectorStatus.Connected) { | |
_state.DockConnectorPosition = _connector.OtherConnector.GetPosition(); | |
_state.DockConnectorForward = _connector.OtherConnector.WorldMatrix.Forward; | |
_drainInventories.Clear(); | |
_state.State = "drain"; | |
return; | |
} | |
if (_state.DockConnectorForward == Vector3D.Zero) { | |
Echo("Please manually dock me, I don't know where to go."); | |
_attitude.DesiredForward = Vector3D.Zero; | |
_velocity.DesiredSpeed = Vector3D.Zero; | |
return; | |
} | |
var dest = _state.DockConnectorPosition + DOCKING_DISTANCE * _state.DockConnectorForward; | |
var arrow = dest - _controller.GetPosition(); | |
var distance = arrow.Length(); | |
Echo("Distance: " + Math.Ceiling(distance).ToString()); | |
if (distance < 1) { | |
_state.State = "dock"; | |
_velocity.DesiredSpeed = Vector3D.Zero; | |
_attitude.DesiredForward = Vector3D.Zero; | |
return; | |
} | |
_velocity.DesiredSpeed = Vector3D.Normalize(arrow) * Math.Max(1.0, Math.Min(distance / 30, CRUISE_SPEED)); | |
_attitude.DesiredForward = Vector3D.Normalize(arrow); | |
} | |
void DockState(Action<string> Echo) { | |
_attitude.DesiredForward = _state.DockConnectorForward; | |
var arrow = _state.DockConnectorPosition - _connector.GetPosition(); | |
var distance = arrow.Length(); | |
if (_attitude.IsAligned) { | |
_velocity.DesiredSpeed = Vector3D.Normalize(arrow) * 0.5; | |
} else { | |
_velocity.DesiredSpeed = Vector3D.Zero; | |
} | |
if (_connector.Status == MyShipConnectorStatus.Connected) { | |
_state.State = "drain"; | |
_velocity.DesiredSpeed = Vector3D.Zero; | |
_attitude.DesiredForward = Vector3D.Zero; | |
return; | |
} | |
if (_connector.Status == MyShipConnectorStatus.Connectable) { | |
_connector.Connect(); | |
} | |
} | |
void DrainState(Action<string> Echo) { | |
if (_connector.Status == MyShipConnectorStatus.Connected) { | |
_state.DockConnectorPosition = _connector.OtherConnector.GetPosition(); | |
_state.DockConnectorForward = _connector.OtherConnector.WorldMatrix.Forward; | |
} else { | |
_state.State = "init"; | |
return; | |
} | |
if (_drainInventories.Count == 0) { | |
GridTerminalSystem.GetBlocksOfType(_drainInventories, b => !b.IsSameConstructAs(_controller)); | |
if (_drainInventories.Count == 0) { | |
throw new Exception("No drain inventories available"); | |
} | |
} | |
foreach(var inv in _inventories) { | |
if (inv.ItemCount == 0) | |
continue; | |
var curVolume = inv.CurrentVolume; | |
foreach (var dest in _drainInventories) { | |
if (inv.TransferItemTo(dest.GetInventory(), 0) && curVolume > inv.CurrentVolume) | |
return; | |
} | |
Echo("Destination inventory full, pausing"); | |
return; | |
} | |
if (CanUndock == null || CanUndock()) | |
_state.State = "undock"; | |
} | |
void UndockState(Action<string> Echo) { | |
if (_connector.Status == MyShipConnectorStatus.Connected) { | |
_connector.Disconnect(); | |
} | |
_velocity.DesiredSpeed = _state.DockConnectorForward * 0.5; | |
var arrow = _state.DockConnectorPosition - _controller.GetPosition(); | |
var distance = arrow.Length(); | |
Echo ("Distance: " + Math.Ceiling(distance).ToString()); | |
if (distance > DOCKING_DISTANCE) { | |
_state.State = "init"; | |
} | |
} | |
} | |
SpaceStripMiner _stripMiner; | |
Vector3D _connectorPos; | |
Vector3D _connectorFacing; | |
List<IMyShipConnector> _connectors = new List<IMyShipConnector>(); | |
private IMyShipController GetController() { | |
List<IMyShipController> controllers = new List<IMyShipController>(); | |
GridTerminalSystem.GetBlocksOfType(controllers, b => b.IsSameConstructAs(Me)); | |
return controllers[0]; | |
} | |
private void ReInit() | |
{ | |
var controller = GetController(); | |
_stripMiner = null; | |
List<IMySensorBlock> sensors = new List<IMySensorBlock>(); | |
GridTerminalSystem.GetBlocksOfType(sensors, b => b.IsSameConstructAs(Me)); | |
GridTerminalSystem.GetBlocksOfType(_connectors, b => b.IsSameConstructAs(Me)); | |
if (_stripMiner == null) { | |
Echo("Initialized, waiting for command to acquire asteroid"); | |
} | |
} | |
public Program() | |
{ | |
Runtime.UpdateFrequency = UpdateFrequency.None; | |
ReInit(); | |
if (Storage.Length > 0) { | |
try { | |
var controller = GetController(); | |
List<IMyCameraBlock> cameras = new List<IMyCameraBlock>(); | |
GridTerminalSystem.GetBlocksOfType(cameras, b => b.IsSameConstructAs(controller) && b.Orientation.Forward == controller.Orientation.Forward); | |
var camera = cameras[0]; | |
List<IMyGyro> gyros = new List<IMyGyro>(); | |
GridTerminalSystem.GetBlocksOfType(gyros, b => b.IsSameConstructAs(Me)); | |
List<IMyThrust> thrusters = new List<IMyThrust>(); | |
GridTerminalSystem.GetBlocksOfType(thrusters, b => b.IsSameConstructAs(Me)); | |
List<IMyShipDrill> drills = new List<IMyShipDrill>(); | |
GridTerminalSystem.GetBlocksOfType(drills, b => b.IsSameConstructAs(Me)); | |
List<IMyCargoContainer> containers = new List<IMyCargoContainer>(); | |
GridTerminalSystem.GetBlocksOfType(containers, b => b.IsSameConstructAs(Me)); | |
List<IMyInventory> inventories = containers.Select((c) => c.GetInventory()).ToList(); | |
inventories.Add(_connectors[0].GetInventory()); | |
_stripMiner = new SpaceStripMiner(controller, GridTerminalSystem, thrusters, gyros, inventories, drills, camera, _connectors[0], Storage); | |
if (_connectorFacing != Vector3D.Zero) | |
_stripMiner.SeedConnectorData(_connectorPos, _connectorFacing); | |
Runtime.UpdateFrequency = UpdateFrequency.Update10; | |
Echo("loaded save"); | |
} catch (Exception) { | |
Echo("Failure during loading, clearing storage"); | |
Echo(Storage); | |
Storage = ""; | |
} | |
} | |
DoHousekeeping(); | |
} | |
private void DoHousekeeping() | |
{ | |
if (_connectorFacing == Vector3D.Zero) { | |
if (_connectors[0].Status == MyShipConnectorStatus.Connected) { | |
_connectorPos = _connectors[0].OtherConnector.GetPosition(); | |
_connectorFacing = _connectors[0].OtherConnector.WorldMatrix.Forward; | |
Echo("Acquired docking port"); | |
} | |
} else { | |
Echo("Acquired docking port"); | |
} | |
if (_stripMiner == null) | |
return; | |
if (_stripMiner.CanUndock == null) { | |
List<IMyBatteryBlock> batteries = new List<IMyBatteryBlock>(); | |
GridTerminalSystem.GetBlocksOfType(batteries, b => b.IsSameConstructAs(Me)); | |
_stripMiner.CanUndock = () => { | |
bool canUndock = true; | |
foreach (var batt in batteries) { | |
batt.ChargeMode = ChargeMode.Recharge; | |
canUndock = canUndock && !batt.HasCapacityRemaining; | |
} | |
if (canUndock) { | |
foreach (var batt in batteries) { | |
batt.ChargeMode = ChargeMode.Auto; | |
} | |
} | |
return canUndock; | |
}; | |
} | |
_stripMiner.Tick(_uptime, Echo); | |
} | |
private void AcquireAsteroid() { | |
var controller = GetController(); | |
List<IMyCameraBlock> cameras = new List<IMyCameraBlock>(); | |
GridTerminalSystem.GetBlocksOfType(cameras, b => b.IsSameConstructAs(controller) && b.Orientation.Forward == controller.Orientation.Forward); | |
var camera = cameras[0]; | |
camera.EnableRaycast = true; | |
Runtime.UpdateFrequency = UpdateFrequency.Update100; | |
if (camera.AvailableScanRange < 1000) { | |
Echo("Camera charging: " + camera.AvailableScanRange.ToString()); | |
return; | |
} | |
var trace = camera.Raycast(camera.AvailableScanRange); | |
if (trace.Type != MyDetectedEntityType.Asteroid) { | |
Echo("Detected non-asteroid, retrying"); | |
return; | |
} | |
List<IMyGyro> gyros = new List<IMyGyro>(); | |
GridTerminalSystem.GetBlocksOfType(gyros, b => b.IsSameConstructAs(Me)); | |
List<IMyThrust> thrusters = new List<IMyThrust>(); | |
GridTerminalSystem.GetBlocksOfType(thrusters, b => b.IsSameConstructAs(Me)); | |
List<IMyShipDrill> drills = new List<IMyShipDrill>(); | |
GridTerminalSystem.GetBlocksOfType(drills, b => b.IsSameConstructAs(Me)); | |
List<IMyCargoContainer> containers = new List<IMyCargoContainer>(); | |
GridTerminalSystem.GetBlocksOfType(containers, b => b.IsSameConstructAs(Me)); | |
List<IMyInventory> inventories = containers.Select((c) => c.GetInventory()).ToList(); | |
inventories.Add(_connectors[0].GetInventory()); | |
_stripMiner = new SpaceStripMiner(GetController(), GridTerminalSystem, thrusters, gyros, inventories, drills, camera, _connectors[0], trace); | |
if (_connectorFacing != Vector3D.Zero) | |
_stripMiner.SeedConnectorData(_connectorPos, _connectorFacing); | |
Echo("Asteroid found"); | |
Runtime.UpdateFrequency = UpdateFrequency.Update10; | |
Save(); | |
} | |
private TimeSpan _uptime; | |
public void Main(string argument, UpdateType updateSource) | |
{ | |
if (argument == "acquire") { | |
AcquireAsteroid(); | |
return; | |
} | |
_uptime += Runtime.TimeSinceLastRun; | |
if (Runtime.TimeSinceLastRun.TotalSeconds > 5.0) { | |
_uptime = TimeSpan.Zero; | |
ReInit(); | |
} | |
if ((updateSource & UpdateType.Update10) != 0) { | |
DoHousekeeping(); | |
} | |
if ((updateSource & UpdateType.Update100) != 0) { | |
AcquireAsteroid(); | |
} | |
} | |
public void Save() { | |
if (_stripMiner != null) | |
Storage = _stripMiner.SaveData; | |
else | |
Storage = ""; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
List<IMyGasTank> _tanks = new List<IMyGasTank>(); | |
List<IMyCockpit> _cockpits = new List<IMyCockpit>(); | |
List<IMyTextSurface> _surfaces = new List<IMyTextSurface>(); | |
List<IMySoundBlock> _soundblocks = new List<IMySoundBlock>(); | |
float _alertLevel = 20; | |
double _fuelTankSize = 0; | |
string _state = "starting"; | |
double _secondsUntilNextAlert = 4; | |
private void ReInit() | |
{ | |
GridTerminalSystem.GetBlocksOfType(_tanks, b => b.IsSameConstructAs(Me) && b.BlockDefinition.SubtypeName.Contains("RocketFuel")); | |
GridTerminalSystem.GetBlocksOfType(_cockpits, b => b.IsSameConstructAs(Me)); | |
GridTerminalSystem.GetBlocksOfType(_soundblocks, b => b.IsSameConstructAs(Me)); | |
_fuelTankSize = 0; | |
foreach (var tank in _tanks) { | |
_fuelTankSize += tank.Capacity; | |
Echo (tank.BlockDefinition.SubtypeName); | |
} | |
if (_fuelTankSize < 0.01) { | |
Echo("Fatal: No tanks"); | |
_fuelTankSize = 1; | |
} | |
_surfaces.Clear(); | |
foreach (var cockpit in _cockpits) { | |
var screen = cockpit.GetSurface(0); | |
_surfaces.Add(screen); | |
screen.ContentType = ContentType.TEXT_AND_IMAGE; | |
screen.FontSize = 8.0f; | |
screen.Alignment = TextAlignment.RIGHT; | |
screen.WriteText("?%", false); | |
} | |
} | |
public Program() | |
{ | |
Runtime.UpdateFrequency = UpdateFrequency.Update100; | |
ReInit(); | |
} | |
private void DoHousekeeping() | |
{ | |
double fuel = 0; | |
foreach (var tank in _tanks) { | |
if (tank.CustomData == "ignore") | |
continue; | |
if (!tank.Stockpile) | |
fuel += tank.Capacity * tank.FilledRatio; | |
} | |
int percentage = (int)Math.Ceiling(fuel / _fuelTankSize * 100); | |
foreach (var screen in _surfaces) { | |
screen.WriteText(percentage.ToString() + "%", false); | |
} | |
if (percentage < _alertLevel) { | |
_secondsUntilNextAlert -= Runtime.TimeSinceLastRun.TotalSeconds; | |
if (_secondsUntilNextAlert <= 0) { | |
if (_state == "starting") { | |
foreach (var block in _soundblocks) { | |
block.Play(); | |
} | |
_state = "stopping"; | |
_secondsUntilNextAlert = 1; | |
} else { | |
foreach (var block in _soundblocks) { | |
block.Stop(); | |
} | |
_state = "starting"; | |
_secondsUntilNextAlert = 4; | |
} | |
} | |
} | |
} | |
public void Main(string argument, UpdateType updateSource) | |
{ | |
if ((updateSource & UpdateType.Update100) != 0) { | |
DoHousekeeping(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
bool _autoPowerSave = true; | |
IMyTextSurface _cockpitSurface; | |
RectangleF _viewport; | |
List<IMyCargoContainer> _containers = new List<IMyCargoContainer>(); | |
List<IMyEntity> _storages = new List<IMyEntity>(); | |
IMyGasGenerator _splitter; | |
List<IMyBatteryBlock> _batteries = new List<IMyBatteryBlock>(); | |
IMyPowerProducer _generator; | |
List<IMyGasTank> _tanks = new List<IMyGasTank>(); | |
IMyShipConnector _connector; | |
List<IMyLandingGear> _landingGear = new List<IMyLandingGear>(); | |
IMyCockpit _cockpit; | |
IMyRemoteControl _remoteControl; | |
IMyRadioAntenna _antenna; | |
IMyBeacon _beacon; | |
List<IMyLightingBlock> _navLights = new List<IMyLightingBlock>(); | |
List<IMyThrust> _thrusters = new List<IMyThrust>(); | |
//List<IMySmallGattlingGun> _gattlingGuns = new List<IMySmallGattlingGun>(); | |
MyItemType _iceType = new MyItemType("MyObjectBuilder_Ore", "Ice"); | |
const double _iceConversionRatio = 20.0; | |
double _fuelTankSize = 1; | |
bool _wasDocked = false; | |
TimeSpan _uptime = TimeSpan.Zero; | |
TimeSpan _timeIdle = TimeSpan.Zero; | |
private void ReInit() | |
{ | |
_timeIdle = TimeSpan.Zero; | |
GridTerminalSystem.GetBlocksOfType(_containers, b => b.IsSameConstructAs(Me)); | |
GridTerminalSystem.GetBlocksOfType(_batteries, b => b.IsSameConstructAs(Me)); | |
GridTerminalSystem.GetBlocksOfType(_tanks, b => b.IsSameConstructAs(Me)); | |
GridTerminalSystem.GetBlocksOfType(_navLights, b => b.IsSameConstructAs(Me)); | |
GridTerminalSystem.GetBlocksOfType(_thrusters, b => b.IsSameConstructAs(Me)); | |
GridTerminalSystem.GetBlocksOfType(_landingGear, b => b.IsSameConstructAs(Me)); | |
_fuelTankSize = 0; | |
foreach (var tank in _tanks) { | |
_fuelTankSize += tank.Capacity; | |
} | |
if (_fuelTankSize < 0.01) { | |
Echo("Fatal: No hydrogen tanks"); | |
_fuelTankSize = 1; | |
} | |
var splitters = new List<IMyGasGenerator>(); | |
GridTerminalSystem.GetBlocksOfType(splitters, b => b.IsSameConstructAs(Me)); | |
if (splitters.Any()) | |
_splitter = splitters.First(); | |
var generators = new List<IMyPowerProducer>(); | |
GridTerminalSystem.GetBlocksOfType(generators, b => b.IsSameConstructAs(Me) && b.BlockDefinition.ToString().Contains("HydrogenEngine")); | |
if (generators.Any()) | |
_generator = generators.First(); | |
var connectors = new List<IMyShipConnector>(); | |
GridTerminalSystem.GetBlocksOfType(connectors, b => b.IsSameConstructAs(Me)); | |
if (connectors.Any()) | |
_connector = connectors.First(); | |
var remoteControls = new List<IMyRemoteControl>(); | |
GridTerminalSystem.GetBlocksOfType(remoteControls, b => b.IsSameConstructAs(Me)); | |
if (remoteControls.Any()) | |
_remoteControl = remoteControls.First(); | |
var antennas = new List<IMyRadioAntenna>(); | |
GridTerminalSystem.GetBlocksOfType(antennas, b => b.IsSameConstructAs(Me)); | |
if (antennas.Any()) | |
_antenna = antennas.First(); | |
var beacons = new List<IMyBeacon>(); | |
GridTerminalSystem.GetBlocksOfType(beacons, b => b.IsSameConstructAs(Me)); | |
if (beacons.Any()) | |
_beacon = beacons.First(); | |
var cockpits = new List<IMyCockpit>(); | |
GridTerminalSystem.GetBlocksOfType(cockpits, b => b.IsSameConstructAs(Me)); | |
if (cockpits.Any()) | |
_cockpit = cockpits.First(); | |
_storages.Clear(); | |
_storages.AddRange(_containers); | |
_storages.Add(_cockpit); | |
_storages.Add(_connector); | |
_cockpitSurface = _cockpit.GetSurface(0); | |
_cockpitSurface.ContentType = ContentType.SCRIPT; | |
_cockpitSurface.Script = ""; | |
_viewport = new RectangleF( | |
(_cockpitSurface.TextureSize - _cockpitSurface.SurfaceSize) / 2f, | |
_cockpitSurface.SurfaceSize | |
); | |
foreach (var battery in _batteries) { | |
battery.ChargeMode = ChargeMode.Auto; | |
} | |
_wasDocked = IsDocked(); | |
} | |
public Program() | |
{ | |
Runtime.UpdateFrequency = UpdateFrequency.Update100; | |
ReInit(); | |
} | |
public bool IsDocked() { | |
if (_connector != null) | |
if (_connector.Status == MyShipConnectorStatus.Connected) | |
return true; | |
foreach (var leg in _landingGear) { | |
if (leg.IsLocked) | |
return true; | |
} | |
return false; | |
} | |
public void Save() | |
{ | |
// Called when the program needs to save its state. Use | |
// this method to save your state to the Storage field | |
// or some other means. | |
// | |
// This method is optional and can be removed if not | |
// needed. | |
} | |
private void DoHousekeeping() | |
{ | |
double hydrogen = 0; | |
double ice = 0; | |
double power = 0; | |
double powerMax = 0; | |
foreach (var tank in _tanks) { | |
if (!tank.IsFunctional) | |
continue; | |
hydrogen += tank.Capacity * tank.FilledRatio; | |
} | |
foreach (var storage in _storages) { | |
var inventory = storage.GetInventory(); | |
if (inventory == null) | |
continue; | |
var iceCount = inventory.GetItemAmount(_iceType); | |
ice += (double)iceCount * _iceConversionRatio; | |
} | |
foreach (var battery in _batteries) { | |
if (!battery.IsFunctional) | |
continue; | |
powerMax += battery.MaxStoredPower; | |
power += battery.CurrentStoredPower; | |
} | |
double fuelPercentage = Math.Ceiling((ice + hydrogen) / _fuelTankSize * 100); | |
Echo("Fuel: " + fuelPercentage.ToString() + "%"); | |
double hydrogenPercentage = Math.Ceiling(hydrogen / _fuelTankSize * 100); | |
Echo("Hydrogen: " + hydrogenPercentage.ToString() + "%"); | |
double powerPercentage = Math.Ceiling(power / powerMax * 100); | |
Echo("Power: " + powerPercentage.ToString() + "%"); | |
bool newDockStatus = IsDocked(); | |
if (newDockStatus != _wasDocked) { | |
_wasDocked = newDockStatus; | |
if (newDockStatus) { | |
foreach (var thruster in _thrusters) { | |
thruster.Enabled = false; | |
} | |
foreach (var light in _navLights) { | |
light.Enabled = false; | |
} | |
} else { | |
_timeIdle = TimeSpan.Zero; | |
foreach (var thruster in _thrusters) { | |
thruster.Enabled = true; | |
} | |
foreach (var light in _navLights) { | |
light.Enabled = true; | |
} | |
} | |
} | |
if (_antenna != null) { | |
if (_connector != null && _connector.Status == MyShipConnectorStatus.Connected) { | |
_antenna.Enabled = false; | |
if (_beacon != null) | |
_beacon.Enabled = false; | |
} else { | |
bool nearEmpty = (fuelPercentage < 300); | |
_antenna.Enabled = !nearEmpty; | |
if (_beacon != null) { | |
_beacon.Enabled = nearEmpty; | |
} | |
} | |
} | |
if (_generator != null) { | |
if (_batteries.Count() > 1) { | |
if (_generator.Enabled) { | |
if (powerPercentage == 100) | |
_generator.Enabled = false; | |
if (powerPercentage > 5) { | |
foreach (var battery in _batteries) { | |
if (battery.ChargeMode == ChargeMode.Recharge) | |
battery.ChargeMode = ChargeMode.Auto; | |
} | |
} | |
} else { | |
if (powerPercentage < 80) | |
_generator.Enabled = true; | |
} | |
} else { | |
_generator.Enabled = true; | |
} | |
} | |
if (_splitter != null) { | |
if (_tanks.Count() > 1) { | |
if (_splitter.Enabled) { | |
if (hydrogenPercentage == 100) | |
_splitter.Enabled = false; | |
} else { | |
if (hydrogenPercentage < 100) | |
_splitter.Enabled = true; | |
} | |
} else { | |
_splitter.Enabled = true; | |
} | |
} | |
if (powerPercentage < 5) { | |
if (_cockpit != null && !_cockpit.IsUnderControl) { | |
foreach (var battery in _batteries) | |
battery.ChargeMode = ChargeMode.Recharge; | |
} | |
} | |
if (_cockpit.IsUnderControl) | |
_timeIdle = TimeSpan.Zero; | |
if (_autoPowerSave && _timeIdle.TotalSeconds > 600) { | |
foreach (var battery in _batteries) { | |
battery.ChargeMode = ChargeMode.Auto; | |
} | |
_timeIdle = TimeSpan.Zero; | |
} | |
DrawCockpitScreen(hydrogen / _fuelTankSize, ice / _fuelTankSize, -1, -1); | |
} | |
private MySprite CreateBar(double offset, double angleDegrees, double start, double end, double width, Color color) | |
{ | |
if (start < -0.2f) | |
start = -0.2f; | |
double borderTop = 0; | |
double borderBottom = 0.055; | |
start = (start - borderTop) / (1 + borderBottom) + borderTop; | |
end = (end - borderTop) / (1 + borderBottom) + borderTop; | |
double radianAngle = angleDegrees / 180.0 * Math.PI; | |
float midY = (float)((start + end) / 2.0 * _viewport.Height) + _viewport.Y; | |
float midX = (float)offset - (float)(Math.Tan(radianAngle) * _viewport.Width * (start + end) / 4.0) + _viewport.X; | |
float maxHeight = (float)(_viewport.Height / Math.Cos(radianAngle)); | |
float rotatedHeight = (float)(maxHeight * (end - start)); | |
float rotatedWidth = (float)(_viewport.Width * width); | |
return new MySprite() { | |
Type = SpriteType.TEXTURE, | |
Data = "White screen", | |
Position = new Vector2(midX, midY), | |
Size = new Vector2(rotatedWidth, rotatedHeight), | |
Color = color, | |
Alignment = TextAlignment.CENTER, | |
RotationOrScale = (float)radianAngle, | |
}; | |
} | |
private void DrawCockpitScreen(double hydrogen, double fuel, int mainAmmo, int autoAmmo) { | |
if (_cockpit == null) | |
return; | |
if (!_cockpit.IsUnderControl) | |
return; | |
if (_cockpitSurface == null) | |
return; | |
using (var frame = _cockpitSurface.DrawFrame()) { | |
var bgSprite = new MySprite() { | |
Type = SpriteType.TEXTURE, | |
Data = "Grid", | |
Position = _viewport.Center, | |
Size = _viewport.Size, | |
Color = _cockpitSurface.ScriptForegroundColor.Alpha(0.66f), | |
Alignment = TextAlignment.CENTER | |
}; | |
frame.Add(bgSprite); | |
if (_uptime.TotalSeconds < 5) { | |
frame.Add(MySprite.CreateText("Wasp OS", "White", _cockpitSurface.ScriptForegroundColor, 1.0f, TextAlignment.CENTER)); | |
return; | |
} | |
frame.Add(CreateBar(72, 30, 1.0 - fuel, 1.0, 1.0 / 20.0, _cockpitSurface.ScriptForegroundColor)); | |
Color hydrogenColor = new Color(_cockpitSurface.ScriptForegroundColor.R, _cockpitSurface.ScriptForegroundColor.G, 255 - _cockpitSurface.ScriptForegroundColor.B); | |
frame.Add(CreateBar(72, 30, 1.0 - hydrogen, 1.0, 1.0 / 20.0, hydrogenColor)); | |
frame.Add(CreateBar(188, -30, 1.0 - (fuel / 25.0), 1.0, 1.0 / 20.0, _cockpitSurface.ScriptForegroundColor)); | |
int velocity = (int)Math.Round(_cockpit.GetShipVelocities().LinearVelocity.Length()); | |
frame.Add(new MySprite() { | |
Type = SpriteType.TEXT, | |
Data = velocity.ToString(), | |
Position = new Vector2(_viewport.X + _viewport.Width / 2.0f, _viewport.Y + 32f), | |
FontId = "White", | |
Color = _cockpitSurface.ScriptForegroundColor, | |
RotationOrScale = 1.0f, | |
Alignment = TextAlignment.CENTER | |
}); | |
} | |
} | |
public void Main(string argument, UpdateType updateSource) | |
{ | |
_uptime += Runtime.TimeSinceLastRun; | |
_timeIdle += Runtime.TimeSinceLastRun; | |
if (Runtime.TimeSinceLastRun.TotalSeconds > 5.0) { | |
_uptime = TimeSpan.Zero; | |
ReInit(); | |
} | |
if ((updateSource & UpdateType.Update100) != 0) { | |
DoHousekeeping(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment