Files
zfxaction26_2/src/ReactorMaintenance.Simulation/LevelEditor.cs
2026-05-10 18:37:30 +02:00

163 lines
7.3 KiB
C#

namespace ReactorMaintenance.Simulation;
public enum EEditorTool
{
Cursor,
Floor,
Wall,
FuelUnderground,
CoolantUnderground,
ElectricityUnderground,
FuelFlow,
CoolantFlow,
ElectricityFlow,
FuelConsumer,
CoolantConsumer,
ElectricityConsumer,
Junction,
Door,
AllSeeingEyeTerminal,
FuelRemedySupply,
CoolantRemedySupply,
ElectricityRemedySupply,
HeatRemedySupply,
ReactorControl,
FuelLeak,
CoolantLeak,
ElectricityLeak,
FuelHazard,
CoolantHazard,
ElectricityHazard,
Heat,
Robot
}
public static class LevelEditor
{
public static LevelState Apply(LevelState level, GridPosition position, EEditorTool tool)
{
if (!level.InBounds(position))
return level;
return tool switch {
EEditorTool.Cursor => level,
EEditorTool.Floor => level.SetTerrain(position, ECellTerrain.Floor),
EEditorTool.Wall => level.SetTerrain(position, ECellTerrain.Wall),
EEditorTool.FuelUnderground => SetUnderground(level, position, ECarrierType.Fuel),
EEditorTool.CoolantUnderground => SetUnderground(level, position, ECarrierType.Coolant),
EEditorTool.ElectricityUnderground => SetUnderground(level, position, ECarrierType.Electricity),
EEditorTool.FuelFlow => SetCarrierProp(level, position, EPropType.Flow, ECarrierType.Fuel),
EEditorTool.CoolantFlow => SetCarrierProp(level, position, EPropType.Flow, ECarrierType.Coolant),
EEditorTool.ElectricityFlow => SetCarrierProp(level, position, EPropType.Flow, ECarrierType.Electricity),
EEditorTool.FuelConsumer => SetCarrierProp(level, position, EPropType.Consumer, ECarrierType.Fuel),
EEditorTool.CoolantConsumer => SetCarrierProp(level, position, EPropType.Consumer, ECarrierType.Coolant),
EEditorTool.ElectricityConsumer => SetCarrierProp(level, position, EPropType.Consumer, ECarrierType.Electricity),
EEditorTool.Junction => SetFloorProp(level, position, new() { Type = EPropType.Junction }),
EEditorTool.Door => SetDoor(level, position),
EEditorTool.AllSeeingEyeTerminal => SetFloorProp(level, position, new() { Type = EPropType.AllSeeingEyeTerminal }),
EEditorTool.FuelRemedySupply => SetFloorProp(level, position, new() { Type = EPropType.RemedySupply, RemedyType = ERemedyType.FuelNeutralizer }),
EEditorTool.CoolantRemedySupply => SetFloorProp(level, position, new() { Type = EPropType.RemedySupply, RemedyType = ERemedyType.CoolantNeutralizer }),
EEditorTool.ElectricityRemedySupply => SetFloorProp(level, position, new() { Type = EPropType.RemedySupply, RemedyType = ERemedyType.ElectricityNeutralizer }),
EEditorTool.HeatRemedySupply => SetFloorProp(level, position, new() { Type = EPropType.RemedySupply, RemedyType = ERemedyType.HeatShield }),
EEditorTool.ReactorControl => SetReactorControl(level, position),
EEditorTool.FuelLeak => SetLeak(level, position, ECarrierType.Fuel),
EEditorTool.CoolantLeak => SetLeak(level, position, ECarrierType.Coolant),
EEditorTool.ElectricityLeak => SetLeak(level, position, ECarrierType.Electricity),
EEditorTool.FuelHazard => level.SetSurface(position, level.GetSurface(position) with { Fuel = level.GetSurface(position).Fuel + 1 }),
EEditorTool.CoolantHazard => level.SetSurface(position, level.GetSurface(position) with { Coolant = level.GetSurface(position).Coolant + 1 }),
EEditorTool.ElectricityHazard => level.SetSurface(position, level.GetSurface(position) with { Electricity = level.GetSurface(position).Electricity + 1 }),
EEditorTool.Heat => level.SetSurface(position, level.GetSurface(position) with { Heat = level.GetSurface(position).Heat + 1 }),
EEditorTool.Robot => level.IsFloor(position) ? level with { Robot = level.Robot with { Position = position } } : level,
_ => level
};
}
public static LevelState BindFirstReactorToConsumers(LevelState level, GridPosition fuelConsumer, GridPosition coolantConsumer, GridPosition electricityConsumer)
{
if (level.Reactors.Count == 0)
return level;
var reactors = level.Reactors.ToArray();
reactors[0] = reactors[0] with {
FuelConsumerPosition = fuelConsumer,
CoolantConsumerPosition = coolantConsumer,
ElectricityConsumerPosition = electricityConsumer
};
return level with { Reactors = reactors };
}
private static LevelState SetUnderground(LevelState level, GridPosition position, ECarrierType carrier)
{
return level.SetUnderground(position, carrier, new() { State = EUndergroundState.Intact });
}
private static LevelState SetCarrierProp(LevelState level, GridPosition position, EPropType type, ECarrierType carrier)
{
return SetFloorProp(level, position, new() { Type = type, Carrier = carrier, SwitchState = EPropSwitchState.Enabled });
}
private static LevelState SetFloorProp(LevelState level, GridPosition position, PropState prop)
{
return level.IsFloor(position) ? level.SetProp(position, prop) : level;
}
private static LevelState SetDoor(LevelState level, GridPosition position)
{
if (!level.IsFloor(position))
return level;
var neighbor = position.Neighbors().FirstOrDefault(level.IsFloor);
if (neighbor is null)
return SetFloorProp(level, position, new() { Type = EPropType.Door });
return SetFloorProp(level, position, new() { Type = EPropType.Door }) with {
Doors = [.. level.Doors, new() { A = position, B = neighbor }]
};
}
private static LevelState SetReactorControl(LevelState level, GridPosition position)
{
if (!level.IsFloor(position))
return level;
var id = level.Reactors.Count == 0 ? 1 : level.Reactors.Max(reactor => reactor.ReactorId) + 1;
var levelWithProp = level.SetProp(position, new() { Type = EPropType.ReactorControl, ReactorId = id });
return levelWithProp with {
Reactors = [
.. level.Reactors,
new() {
ReactorId = id,
ControlPosition = position,
FuelConsumerPosition = position,
CoolantConsumerPosition = position,
ElectricityConsumerPosition = position
}
]
};
}
private static LevelState SetLeak(LevelState level, GridPosition position, ECarrierType carrier)
{
if (!level.InBounds(position))
return level;
var accessPosition = carrier == ECarrierType.Electricity && level.GetTerrain(position) == ECellTerrain.Wall
? position.Neighbors().FirstOrDefault(level.IsFloor)
: position;
if (accessPosition is null || !level.IsFloor(accessPosition))
return level;
var next = level.SetUnderground(position, carrier, new() { State = EUndergroundState.Leaking });
return next with {
Leaks = [
.. next.Leaks,
new() {
Carrier = carrier,
UndergroundPosition = position,
AccessPosition = accessPosition
}
]
};
}
}