From e01b3f59f7c95f87e18623dd1a5c52b8f2061980 Mon Sep 17 00:00:00 2001 From: Ed Kolis Date: Sun, 17 Nov 2024 19:13:02 -0500 Subject: [PATCH] 333 put vehicles in their own module (#335) * Move Vehicles up a namespace, out of Objects * Create FrEee.Vehicles project * Fix a bunch of code broken by moving concrete vehicle type classes to a separate module. There's still some to fix but I think Design and Hull will be need to migrated to the same or another module as well for that. * Add VehicleFactory * Reorganize some things * Add HullFactory * Add DesignFactory * Fix a few simple crashes * Move WeaponPlatform to correct namespace * Mark vehicles project as private assets * Fix compile errors in unit tests caused by referencing newly hidden code * Fix more unit tests * Fix compile errors in winforms, clean up some stuff --- .../Extensions/ChecksExtensions.cs | 2 +- .../Extensions/CommonExtensions.cs | 13 +- FrEee.Core.Domain/FrEee.Core.Domain.csproj | 3 + .../Commands/Designs/ICreateDesignCommand.cs | 2 +- .../Commands/Designs/IDesignCommandFactory.cs | 2 +- .../Designs/ISetObsoleteFlagCommand.cs | 2 +- .../Modding/Abilities/Extensions.cs | 12 +- .../Modding/Loaders/ComponentLoader.cs | 2 +- .../Modding/Loaders/HullLoader.cs | 52 ++---- .../Modding/Loaders/MountLoader.cs | 2 +- FrEee.Core.Domain/Modding/Mod.cs | 1 + .../Modding/Templates/ComponentTemplate.cs | 2 +- .../Civilization/CargoStorage/Cargo.cs | 2 +- .../Civilization/CargoStorage/CargoDelta.cs | 3 +- .../CargoStorage/ICargoContainer.cs | 2 +- .../Construction/ConstructionQueue.cs | 5 +- .../Objects/Civilization/Diplomacy/Package.cs | 3 +- .../Objects/Civilization/Empire.cs | 11 +- .../Civilization/IHasMaintenanceCost.cs | 19 +++ .../Orders/ActivateAbilityOrder.cs | 11 +- .../Civilization/Orders/ColonizeOrder.cs | 4 +- .../Civilization/Orders/ConstructionOrder.cs | 7 +- .../Civilization/Orders/PathfindingOrder.cs | 6 +- .../Orders/RecycleBehaviors/ScrapBehavior.cs | 4 +- .../Orders/RecycleVehicleInSpaceOrder.cs | 4 +- .../Civilization/Orders/SentryOrder.cs | 4 +- FrEee.Core.Domain/Objects/GameState/Game.cs | 2 +- .../Objects/SimulatedObjectWrappers.cs | 2 +- FrEee.Core.Domain/Objects/Space/Fleet.cs | 24 +-- .../Objects/Space/IMobileSpaceObject.cs | 5 +- .../Objects/Space/ISpaceObject.cs | 17 +- FrEee.Core.Domain/Objects/Space/Planet.cs | 9 +- FrEee.Core.Domain/Objects/Space/Sector.cs | 2 +- .../Objects/Technology/Component.cs | 2 +- .../Objects/Technology/ComponentReference.cs | 2 +- FrEee.Core.Domain/Objects/Technology/IHull.cs | 103 ------------ FrEee.Core.Domain/Objects/Technology/Mount.cs | 2 +- .../Technology/MountedComponentTemplate.cs | 4 +- ...ntedComponentTemplateContainerPopulator.cs | 2 +- FrEee.Core.Domain/Objects/Vehicles/IDesign.cs | 152 ----------------- FrEee.Core.Domain/Objects/Vehicles/IUnit.cs | 11 -- .../Objects/Vehicles/IVehicle.cs | 37 ----- .../Objects/Vehicles/VehicleTypes.cs | 51 ------ FrEee.Core.Domain/Utility/DIRoot.cs | 16 ++ FrEee.Core.Domain/Utility/Pictures.cs | 36 ++-- FrEee.Core.Domain/Vehicles/IDesign.cs | 157 ++++++++++++++++++ FrEee.Core.Domain/Vehicles/IDesignFactory.cs | 38 +++++ FrEee.Core.Domain/Vehicles/IHull.cs | 104 ++++++++++++ FrEee.Core.Domain/Vehicles/IHullFactory.cs | 21 +++ FrEee.Core.Domain/Vehicles/IVehicle.cs | 49 ++++++ FrEee.Core.Domain/Vehicles/IVehicleFactory.cs | 21 +++ .../Vehicles/Types/IMajorSpaceVehicle.cs | 17 ++ .../Vehicles/Types/ISpaceVehicle.cs | 29 ++++ FrEee.Core.Domain/Vehicles/Types/IUnit.cs | 26 +++ .../Vehicles/Types/VehicleTypes.cs | 52 ++++++ .../Commands/Designs/CreateDesignCommand.cs | 51 +++--- .../Commands/Designs/DesignCommandFactory.cs | 11 +- .../Designs/SetObsoleteFlagCommand.cs | 98 +++++------ .../Commands/Fleets/CreateFleetCommand.cs | 4 +- .../Commands/Fleets/DisbandFleetCommand.cs | 4 +- .../Commands/Fleets/FleetCommandFactory.cs | 13 +- .../Commands/Fleets/JoinFleetCommand.cs | 6 +- .../Commands/Messages/DeleteMessageCommand.cs | 4 +- .../Messages/MessageCommandFactory.cs | 16 +- .../Commands/Messages/SendMessageCommand.cs | 4 +- .../Ministers/MinisterCommandFactory.cs | 17 +- .../Ministers/ToggleMinistersCommand.cs | 31 ++-- .../Commands/Notes/ClearPlayerNoteCommand.cs | 6 +- .../Commands/Notes/ClearPrivateNameCommand.cs | 6 +- .../Commands/Notes/NoteCommandFactory.cs | 8 +- .../Commands/Notes/SetPlayerInfoCommand.cs | 6 +- .../Commands/Notes/SetPlayerNoteCommand.cs | 6 +- .../Commands/Notes/SetPrivateNameCommand.cs | 6 +- .../Commands/Orders/AddOrderCommand.cs | 6 +- .../Commands/Orders/OrderCommand.cs | 8 +- .../Commands/Orders/OrderCommandFactory.cs | 7 +- .../Commands/Orders/RearrangeOrdersCommand.cs | 4 +- .../Commands/Orders/RemoveOrderCommand.cs | 6 +- .../Projects/ProjectCommandFactory.cs | 13 +- .../Commands/Projects/ResearchCommand.cs | 80 ++++----- .../Waypoints/CreateWaypointCommand.cs | 4 +- .../Waypoints/DeleteWaypointCommand.cs | 4 +- .../Waypoints/HotkeyWaypointCommand.cs | 7 +- .../Waypoints/WaypointCommandFactory.cs | 13 +- FrEee.Processes/Combat/Grid/Battle.cs | 13 +- FrEee.Processes/Combat/Grid/GroundBattle.cs | 11 +- FrEee.Processes/TurnProcessor.cs | 20 ++- FrEee.Root/Configuration.cs | 6 + FrEee.Root/FrEee.Root.csproj | 3 + FrEee.Tests/Modding/FormulaTest.cs | 9 +- FrEee.Tests/Objects/Abilities/AbilityTest.cs | 14 +- FrEee.Tests/Objects/Space/MemoryTest.cs | 21 +-- FrEee.Tests/Objects/Vehicles/CloakingTest.cs | 19 ++- FrEee.Tests/Objects/Vehicles/DamageTest.cs | 13 +- FrEee.Tests/Objects/Vehicles/ResupplyTest.cs | 16 +- .../Processes/Combat/DamageTypesTest.cs | 22 +-- FrEee.Tests/TestUtilities.cs | 39 ++--- FrEee.Tests/Utility/SerializerTest.cs | 8 +- FrEee.UI.WinForms/Controls/BattleView.cs | 9 +- FrEee.UI.WinForms/Controls/Cargolist.cs | 3 +- FrEee.UI.WinForms/Controls/DesignReport.cs | 2 +- FrEee.UI.WinForms/Controls/FleetReport.cs | 11 +- .../Controls/SpaceVehicleReport.cs | 17 +- .../Controls/StarSystemReport.cs | 4 +- FrEee.UI.WinForms/Controls/StarSystemView.cs | 4 +- .../Forms/ActivateAbilityForm.cs | 2 +- FrEee.UI.WinForms/Forms/BattleReplayForm.cs | 4 +- FrEee.UI.WinForms/Forms/BattleResultsForm.cs | 2 +- .../Forms/CombatSimulatorForm.cs | 18 +- .../Forms/ConstructionQueueForm.cs | 2 +- FrEee.UI.WinForms/Forms/DesignListForm.cs | 3 +- FrEee.UI.WinForms/Forms/DiplomacyForm.cs | 11 +- FrEee.UI.WinForms/Forms/FleetTransferForm.cs | 23 +-- FrEee.UI.WinForms/Forms/GameSetupForm.cs | 4 +- FrEee.UI.WinForms/Forms/HostConsoleForm.cs | 4 +- FrEee.UI.WinForms/Forms/HullPickerForm.cs | 4 +- FrEee.UI.WinForms/Forms/LogForm.cs | 3 +- FrEee.UI.WinForms/Forms/MainGameForm.cs | 20 +-- FrEee.UI.WinForms/Forms/MainMenuForm.cs | 6 +- FrEee.UI.WinForms/Forms/MountPickerForm.cs | 1 + FrEee.UI.WinForms/Forms/PlanetListForm.cs | 8 +- FrEee.UI.WinForms/Forms/RecycleForm.cs | 12 +- FrEee.UI.WinForms/Forms/ShipListForm.cs | 6 +- FrEee.UI.WinForms/Forms/TechTreeForm.cs | 1 + FrEee.UI.WinForms/Forms/VehicleDesignForm.cs | 8 +- .../Objects/GalaxyViewModes/ForcesMode.cs | 8 +- FrEee.UI.WinForms/Program.cs | 4 +- .../Vehicles => FrEee.Vehicles}/Design.cs | 124 ++------------ FrEee.Vehicles/DesignFactory.cs | 86 ++++++++++ FrEee.Vehicles/FrEee.Vehicles.csproj | 22 +++ .../Technology => FrEee.Vehicles}/Hull.cs | 5 +- FrEee.Vehicles/HullFactory.cs | 27 +++ .../Vehicles => FrEee.Vehicles/Types}/Base.cs | 2 +- .../Types}/Drone.cs | 8 +- .../Types}/Fighter.cs | 10 +- .../Types}/MajorSpaceVehicle.cs | 10 +- .../Vehicles => FrEee.Vehicles/Types}/Mine.cs | 13 +- .../Types}/Satellite.cs | 10 +- .../Vehicles => FrEee.Vehicles/Types}/Ship.cs | 2 +- .../Types}/SpaceVehicle.cs | 17 +- .../Types}/Troop.cs | 10 +- .../Types}/WeaponPlatform.cs | 8 +- .../Vehicles => FrEee.Vehicles}/Vehicle.cs | 23 +-- FrEee.Vehicles/VehicleFactory.cs | 27 +++ FrEee.sln | 14 ++ 145 files changed, 1348 insertions(+), 1110 deletions(-) create mode 100644 FrEee.Core.Domain/Objects/Civilization/IHasMaintenanceCost.cs delete mode 100644 FrEee.Core.Domain/Objects/Technology/IHull.cs delete mode 100644 FrEee.Core.Domain/Objects/Vehicles/IDesign.cs delete mode 100644 FrEee.Core.Domain/Objects/Vehicles/IUnit.cs delete mode 100644 FrEee.Core.Domain/Objects/Vehicles/IVehicle.cs delete mode 100644 FrEee.Core.Domain/Objects/Vehicles/VehicleTypes.cs create mode 100644 FrEee.Core.Domain/Vehicles/IDesign.cs create mode 100644 FrEee.Core.Domain/Vehicles/IDesignFactory.cs create mode 100644 FrEee.Core.Domain/Vehicles/IHull.cs create mode 100644 FrEee.Core.Domain/Vehicles/IHullFactory.cs create mode 100644 FrEee.Core.Domain/Vehicles/IVehicle.cs create mode 100644 FrEee.Core.Domain/Vehicles/IVehicleFactory.cs create mode 100644 FrEee.Core.Domain/Vehicles/Types/IMajorSpaceVehicle.cs create mode 100644 FrEee.Core.Domain/Vehicles/Types/ISpaceVehicle.cs create mode 100644 FrEee.Core.Domain/Vehicles/Types/IUnit.cs create mode 100644 FrEee.Core.Domain/Vehicles/Types/VehicleTypes.cs rename {FrEee.Core.Domain/Objects/Vehicles => FrEee.Vehicles}/Design.cs (85%) create mode 100644 FrEee.Vehicles/DesignFactory.cs create mode 100644 FrEee.Vehicles/FrEee.Vehicles.csproj rename {FrEee.Core.Domain/Objects/Technology => FrEee.Vehicles}/Hull.cs (99%) create mode 100644 FrEee.Vehicles/HullFactory.cs rename {FrEee.Core.Domain/Objects/Vehicles => FrEee.Vehicles/Types}/Base.cs (95%) rename {FrEee.Core.Domain/Objects/Vehicles => FrEee.Vehicles/Types}/Drone.cs (87%) rename {FrEee.Core.Domain/Objects/Vehicles => FrEee.Vehicles/Types}/Fighter.cs (86%) rename {FrEee.Core.Domain/Objects/Vehicles => FrEee.Vehicles/Types}/MajorSpaceVehicle.cs (91%) rename {FrEee.Core.Domain/Objects/Vehicles => FrEee.Vehicles/Types}/Mine.cs (79%) rename {FrEee.Core.Domain/Objects/Vehicles => FrEee.Vehicles/Types}/Satellite.cs (87%) rename {FrEee.Core.Domain/Objects/Vehicles => FrEee.Vehicles/Types}/Ship.cs (94%) rename {FrEee.Core.Domain/Objects/Vehicles => FrEee.Vehicles/Types}/SpaceVehicle.cs (96%) rename {FrEee.Core.Domain/Objects/Vehicles => FrEee.Vehicles/Types}/Troop.cs (91%) rename {FrEee.Core.Domain/Objects/Vehicles => FrEee.Vehicles/Types}/WeaponPlatform.cs (92%) rename {FrEee.Core.Domain/Objects/Vehicles => FrEee.Vehicles}/Vehicle.cs (96%) create mode 100644 FrEee.Vehicles/VehicleFactory.cs diff --git a/FrEee.Core.Domain/Extensions/ChecksExtensions.cs b/FrEee.Core.Domain/Extensions/ChecksExtensions.cs index b534ed9e..145c8d49 100644 --- a/FrEee.Core.Domain/Extensions/ChecksExtensions.cs +++ b/FrEee.Core.Domain/Extensions/ChecksExtensions.cs @@ -227,7 +227,7 @@ public static bool IsMemoryOfKnownObject(this ISpaceObject sobj) /// The space object to check. /// The empire to check against. /// The visibility level. - internal static Visibility CheckSpaceObjectVisibility(this ISpaceObject sobj, Empire emp) + public static Visibility CheckSpaceObjectVisibility(this ISpaceObject sobj, Empire emp) { bool hasMemory = false; if (sobj.IsMemory) diff --git a/FrEee.Core.Domain/Extensions/CommonExtensions.cs b/FrEee.Core.Domain/Extensions/CommonExtensions.cs index aa5f0537..156b126a 100644 --- a/FrEee.Core.Domain/Extensions/CommonExtensions.cs +++ b/FrEee.Core.Domain/Extensions/CommonExtensions.cs @@ -13,7 +13,6 @@ using FrEee.Objects.LogMessages; using FrEee.Objects.Space; using FrEee.Objects.Technology; -using FrEee.Objects.Vehicles; using FrEee.Modding; using FrEee.Utility; using FrEee.Serialization; @@ -24,6 +23,8 @@ using FrEee.Modding.Abilities; using FrEee.Gameplay.Commands; using FrEee.Gameplay.Commands.Orders; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; namespace FrEee.Extensions; @@ -170,7 +171,13 @@ public static void DealWithMines(this ISpaceObject sobj) return; // shuffle up the mines so they hit in a random order - var mines = sector.SpaceObjects.OfType().Concat(sector.SpaceObjects.OfType().SelectMany(f => f.LeafVehicles.OfType())).Where(m => m.IsHostileTo(sobj.Owner)).Shuffle().ToList(); + var mines = sector.SpaceObjects + .OfType() + .Concat(sector.SpaceObjects.OfType().SelectMany(f => + f.LeafVehicles.OfType())) + .Where(m => m.DetonatesWhenEnemiesEnterSector && m.IsHostileTo(sobj.Owner)) + .Shuffle() + .ToList(); // for log messages var totalDamage = 0; @@ -231,7 +238,7 @@ public static void DealWithMines(this ISpaceObject sobj) if (minesDetonated.Any() || minesSwept.Any() || minesAttacking.Any()) owner.Log.Add(sobj.CreateLogMessage(sobj + " encountered a mine field at " + sector + " and took " + totalDamage + " points of damage, sweeping " + minesSwept.Sum(kvp => kvp.Value) + " mines.", LogMessageType.Generic)); foreach (var emp in minesSwept.Keys.Union(minesDetonated.Keys).Union(minesAttacking.Keys)) - emp.Log.Add(sobj.CreateLogMessage(sobj + " encountered our mine field at " + sector + ". " + minesDetonated[emp] + " of our mines detonated, " + minesAttacking[emp] + " others fired weapons, and " + minesSwept[emp] + " were swept. " + sector.SpaceObjects.OfType().Where(m => m.Owner == emp).Count() + " mines remain in the sector.", LogMessageType.Generic)); + emp.Log.Add(sobj.CreateLogMessage(sobj + " encountered our mine field at " + sector + ". " + minesDetonated[emp] + " of our mines detonated, " + minesAttacking[emp] + " others fired weapons, and " + minesSwept[emp] + " were swept. " + sector.SpaceObjects.OfType().Where(m => m.DetonatesWhenEnemiesEnterSector && m.Owner == emp).Count() + " mines remain in the sector.", LogMessageType.Generic)); } } diff --git a/FrEee.Core.Domain/FrEee.Core.Domain.csproj b/FrEee.Core.Domain/FrEee.Core.Domain.csproj index 767b752d..4263c1b9 100644 --- a/FrEee.Core.Domain/FrEee.Core.Domain.csproj +++ b/FrEee.Core.Domain/FrEee.Core.Domain.csproj @@ -28,6 +28,9 @@ + + + diff --git a/FrEee.Core.Domain/Gameplay/Commands/Designs/ICreateDesignCommand.cs b/FrEee.Core.Domain/Gameplay/Commands/Designs/ICreateDesignCommand.cs index 692cb692..67eac3ba 100644 --- a/FrEee.Core.Domain/Gameplay/Commands/Designs/ICreateDesignCommand.cs +++ b/FrEee.Core.Domain/Gameplay/Commands/Designs/ICreateDesignCommand.cs @@ -1,5 +1,5 @@ using FrEee.Objects.Civilization; -using FrEee.Objects.Vehicles; +using FrEee.Vehicles; namespace FrEee.Gameplay.Commands.Designs; diff --git a/FrEee.Core.Domain/Gameplay/Commands/Designs/IDesignCommandFactory.cs b/FrEee.Core.Domain/Gameplay/Commands/Designs/IDesignCommandFactory.cs index 48b8fffe..a2f3d04b 100644 --- a/FrEee.Core.Domain/Gameplay/Commands/Designs/IDesignCommandFactory.cs +++ b/FrEee.Core.Domain/Gameplay/Commands/Designs/IDesignCommandFactory.cs @@ -6,7 +6,7 @@ using FrEee.Objects.Civilization; using FrEee.Objects.Civilization.Orders; using FrEee.Objects.GameState; -using FrEee.Objects.Vehicles; +using FrEee.Vehicles; namespace FrEee.Gameplay.Commands.Designs; diff --git a/FrEee.Core.Domain/Gameplay/Commands/Designs/ISetObsoleteFlagCommand.cs b/FrEee.Core.Domain/Gameplay/Commands/Designs/ISetObsoleteFlagCommand.cs index dc6de57d..ac5591ff 100644 --- a/FrEee.Core.Domain/Gameplay/Commands/Designs/ISetObsoleteFlagCommand.cs +++ b/FrEee.Core.Domain/Gameplay/Commands/Designs/ISetObsoleteFlagCommand.cs @@ -1,5 +1,5 @@ using FrEee.Objects.Civilization; -using FrEee.Objects.Vehicles; +using FrEee.Vehicles; namespace FrEee.Gameplay.Commands.Designs; diff --git a/FrEee.Core.Domain/Modding/Abilities/Extensions.cs b/FrEee.Core.Domain/Modding/Abilities/Extensions.cs index d8b3d6a3..bef83d88 100644 --- a/FrEee.Core.Domain/Modding/Abilities/Extensions.cs +++ b/FrEee.Core.Domain/Modding/Abilities/Extensions.cs @@ -2,7 +2,6 @@ using FrEee.Objects.Civilization.Diplomacy.Clauses; using FrEee.Objects.Space; using FrEee.Objects.Technology; -using FrEee.Objects.Vehicles; using FrEee.Modding; using System; using System.Collections.Generic; @@ -10,6 +9,7 @@ using FrEee.Objects.GameState; using FrEee.Modding.Abilities; using FrEee.Extensions; +using FrEee.Vehicles; namespace FrEee.Modding.Abilities; @@ -49,7 +49,7 @@ public static ILookup AbilityTree(this IAbilityObject obj, Fun /// /// /// - public static IDictionary ActivatableAbilities(this Vehicle v) + public static IDictionary ActivatableAbilities(this IVehicle v) { var dict = new Dictionary(); foreach (var a in v.Hull.Abilities) @@ -96,10 +96,10 @@ public static IDictionary ActivatableAbilities(this Pla /// public static IDictionary ActivatableAbilities(this IAbilityObject o) { - if (o is Vehicle) - return ((Vehicle)o).ActivatableAbilities(); - if (o is Planet) - return ((Planet)o).ActivatableAbilities(); + if (o is IVehicle v) + return v.ActivatableAbilities(); + if (o is Planet p) + return p.ActivatableAbilities(); var dict = new Dictionary(); foreach (var a in o.Abilities()) diff --git a/FrEee.Core.Domain/Modding/Loaders/ComponentLoader.cs b/FrEee.Core.Domain/Modding/Loaders/ComponentLoader.cs index dc4e3751..d0950b78 100644 --- a/FrEee.Core.Domain/Modding/Loaders/ComponentLoader.cs +++ b/FrEee.Core.Domain/Modding/Loaders/ComponentLoader.cs @@ -5,8 +5,8 @@ using System; using System.Collections.Generic; using System.Linq; -using FrEee.Objects.Vehicles; using FrEee.Processes.Combat; +using FrEee.Vehicles.Types; namespace FrEee.Modding.Loaders; diff --git a/FrEee.Core.Domain/Modding/Loaders/HullLoader.cs b/FrEee.Core.Domain/Modding/Loaders/HullLoader.cs index bf27dbcd..53397974 100644 --- a/FrEee.Core.Domain/Modding/Loaders/HullLoader.cs +++ b/FrEee.Core.Domain/Modding/Loaders/HullLoader.cs @@ -1,6 +1,9 @@ -using FrEee.Objects.Technology; -using FrEee.Objects.Vehicles; +using FrEee.Extensions; +using FrEee.Objects.Technology; using FrEee.Utility; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; +using System; using System.Collections.Generic; using System.Linq; @@ -22,46 +25,17 @@ public override IEnumerable Load(Mod mod) { foreach (var rec in DataFile.Records) { - IHull hull; + IHull hull; var hullname = rec.Get("Name", null); var hulltype = rec.Get("Vehicle Type", null); - switch (hulltype) + try { - case "Ship": - hull = new Hull(); - break; - - case "Base": - hull = new Hull(); - break; - - case "Fighter": - hull = new Hull(); - break; - - case "Satellite": - hull = new Hull(); - break; - - case "Troop": - hull = new Hull(); - break; - - case "Drone": - hull = new Hull(); - break; - - case "Mine": - hull = new Hull(); - break; - - case "Weapon Platform": - hull = new Hull(); - break; - - default: - Mod.Errors.Add(new DataParsingException("Invalid vehicle type \"" + hulltype + "\" specified for " + hullname + " hull.", Mod.CurrentFileName, rec)); - continue; + hull = DIRoot.Hulls.Build(Parser.ParseEnum(hulltype)); + } + catch (InvalidOperationException ex) + { + Mod.Errors.Add(new DataParsingException("Invalid vehicle type \"" + hulltype + "\" specified for " + hullname + " hull.", Mod.CurrentFileName, rec)); + continue; } hull.TemplateParameters = rec.Parameters; hull.ModID = rec.Get("ID", hull); diff --git a/FrEee.Core.Domain/Modding/Loaders/MountLoader.cs b/FrEee.Core.Domain/Modding/Loaders/MountLoader.cs index 94177022..c405da9f 100644 --- a/FrEee.Core.Domain/Modding/Loaders/MountLoader.cs +++ b/FrEee.Core.Domain/Modding/Loaders/MountLoader.cs @@ -2,8 +2,8 @@ using FrEee.Extensions; using System.Collections.Generic; using System.Linq; -using FrEee.Objects.Vehicles; using FrEee.Processes.Combat; +using FrEee.Vehicles.Types; namespace FrEee.Modding.Loaders; diff --git a/FrEee.Core.Domain/Modding/Mod.cs b/FrEee.Core.Domain/Modding/Mod.cs index 5d5c34a2..3d061498 100644 --- a/FrEee.Core.Domain/Modding/Mod.cs +++ b/FrEee.Core.Domain/Modding/Mod.cs @@ -14,6 +14,7 @@ using FrEee.Processes.AI; using FrEee.Modding.Abilities; using FrEee.Modding.Scripts; +using FrEee.Vehicles; namespace FrEee.Modding; diff --git a/FrEee.Core.Domain/Modding/Templates/ComponentTemplate.cs b/FrEee.Core.Domain/Modding/Templates/ComponentTemplate.cs index fdf0de76..311a8072 100644 --- a/FrEee.Core.Domain/Modding/Templates/ComponentTemplate.cs +++ b/FrEee.Core.Domain/Modding/Templates/ComponentTemplate.cs @@ -9,9 +9,9 @@ using System.IO; using System.Linq; using FrEee.Objects.GameState; -using FrEee.Objects.Vehicles; using FrEee.Processes.Combat; using FrEee.Modding.Abilities; +using FrEee.Vehicles.Types; namespace FrEee.Modding.Templates; diff --git a/FrEee.Core.Domain/Objects/Civilization/CargoStorage/Cargo.cs b/FrEee.Core.Domain/Objects/Civilization/CargoStorage/Cargo.cs index a7f0a892..f4c73373 100644 --- a/FrEee.Core.Domain/Objects/Civilization/CargoStorage/Cargo.cs +++ b/FrEee.Core.Domain/Objects/Civilization/CargoStorage/Cargo.cs @@ -5,8 +5,8 @@ using System; using System.Collections.Generic; using System.Linq; -using FrEee.Objects.Vehicles; using FrEee.Processes.Combat; +using FrEee.Vehicles.Types; namespace FrEee.Objects.Civilization.CargoStorage; diff --git a/FrEee.Core.Domain/Objects/Civilization/CargoStorage/CargoDelta.cs b/FrEee.Core.Domain/Objects/Civilization/CargoStorage/CargoDelta.cs index cf63730e..eb76670b 100644 --- a/FrEee.Core.Domain/Objects/Civilization/CargoStorage/CargoDelta.cs +++ b/FrEee.Core.Domain/Objects/Civilization/CargoStorage/CargoDelta.cs @@ -3,8 +3,9 @@ using FrEee.Extensions; using System; using System.Collections.Generic; -using FrEee.Objects.Vehicles; using FrEee.Objects.GameState; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; namespace FrEee.Objects.Civilization.CargoStorage; diff --git a/FrEee.Core.Domain/Objects/Civilization/CargoStorage/ICargoContainer.cs b/FrEee.Core.Domain/Objects/Civilization/CargoStorage/ICargoContainer.cs index da1c07da..01cffd33 100644 --- a/FrEee.Core.Domain/Objects/Civilization/CargoStorage/ICargoContainer.cs +++ b/FrEee.Core.Domain/Objects/Civilization/CargoStorage/ICargoContainer.cs @@ -1,6 +1,6 @@ using FrEee.Objects.GameState; using FrEee.Objects.Space; -using FrEee.Objects.Vehicles; +using FrEee.Vehicles.Types; using System.Collections.Generic; namespace FrEee.Objects.Civilization.CargoStorage; diff --git a/FrEee.Core.Domain/Objects/Civilization/Construction/ConstructionQueue.cs b/FrEee.Core.Domain/Objects/Civilization/Construction/ConstructionQueue.cs index 76cee702..1597ab89 100644 --- a/FrEee.Core.Domain/Objects/Civilization/Construction/ConstructionQueue.cs +++ b/FrEee.Core.Domain/Objects/Civilization/Construction/ConstructionQueue.cs @@ -1,6 +1,5 @@ using FrEee.Objects.Space; using FrEee.Objects.Technology; -using FrEee.Objects.Vehicles; using FrEee.Modding; using FrEee.Utility; using FrEee.Serialization; @@ -14,6 +13,8 @@ using FrEee.Objects.GameState; using FrEee.Modding.Templates; using FrEee.Modding.Abilities; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; namespace FrEee.Objects.Civilization.Construction; @@ -403,7 +404,7 @@ public bool ExecuteOrders() Orders.Add(copy); } builtThisTurn.Add(order.Item); - if (order.Item is Ship || order.Item is Base) + if (order.Item is IMajorSpaceVehicle) { // trigger ship built happiness changes Owner.TriggerHappinessChange(hm => hm.AnyShipConstructed); diff --git a/FrEee.Core.Domain/Objects/Civilization/Diplomacy/Package.cs b/FrEee.Core.Domain/Objects/Civilization/Diplomacy/Package.cs index 82202343..97ff9888 100644 --- a/FrEee.Core.Domain/Objects/Civilization/Diplomacy/Package.cs +++ b/FrEee.Core.Domain/Objects/Civilization/Diplomacy/Package.cs @@ -7,9 +7,10 @@ using System.Collections.Generic; using System.Linq; using Tech = FrEee.Objects.Technology.Technology; -using FrEee.Objects.Vehicles; using FrEee.Objects.GameState; using FrEee.Modding; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; namespace FrEee.Objects.Civilization.Diplomacy; diff --git a/FrEee.Core.Domain/Objects/Civilization/Empire.cs b/FrEee.Core.Domain/Objects/Civilization/Empire.cs index d33f09e5..42d00ff9 100644 --- a/FrEee.Core.Domain/Objects/Civilization/Empire.cs +++ b/FrEee.Core.Domain/Objects/Civilization/Empire.cs @@ -1,7 +1,6 @@ using FrEee.Objects.Civilization.Diplomacy.Clauses; using FrEee.Objects.LogMessages; using FrEee.Objects.Space; -using FrEee.Objects.Vehicles; using FrEee.Modding; using FrEee.Utility; using FrEee.Serialization; @@ -24,6 +23,8 @@ using FrEee.Gameplay.Commands; using FrEee.Gameplay.Commands.Orders; using FrEee.Gameplay.Commands.Projects; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; namespace FrEee.Objects.Civilization; @@ -62,7 +63,7 @@ public Empire() /// /// The current empire being controlled by the player. /// - public static Empire Current + public static Empire? Current { get { @@ -383,8 +384,8 @@ public ResourceQuantity Maintenance { // shouldn't change except at turn processing... // TODO - facility/unit maintenance? - if (maintenance == null || Empire.Current == null) - maintenance = OwnedSpaceObjects.OfType().Sum(v => v.MaintenanceCost); + if (maintenance is null || Current is null) + maintenance = OwnedSpaceObjects.OfType().Sum(v => ((IVehicle)v).MaintenanceCost); return maintenance; } } @@ -902,7 +903,7 @@ public void Dispose() Game.Current.UnassignID(this); if (Game.Current.Empires.Contains(this)) Game.Current.Empires[Game.Current.Empires.IndexOf(this)] = null; - foreach (var x in OwnedSpaceObjects.OfType().ToArray()) + foreach (var x in OwnedSpaceObjects.OfType().ToArray()) x.Dispose(); foreach (var x in ColonizedPlanets.ToArray()) x.Colony.Dispose(); diff --git a/FrEee.Core.Domain/Objects/Civilization/IHasMaintenanceCost.cs b/FrEee.Core.Domain/Objects/Civilization/IHasMaintenanceCost.cs new file mode 100644 index 00000000..3c3bffc7 --- /dev/null +++ b/FrEee.Core.Domain/Objects/Civilization/IHasMaintenanceCost.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Utility; + +namespace FrEee.Objects.Civilization; + +/// +/// Something that has a per-turn maintenance cost. +/// +public interface IHasMaintenanceCost +{ + /// + /// Cost to maintain this object per turn. + /// + ResourceQuantity MaintenanceCost { get; } +} diff --git a/FrEee.Core.Domain/Objects/Civilization/Orders/ActivateAbilityOrder.cs b/FrEee.Core.Domain/Objects/Civilization/Orders/ActivateAbilityOrder.cs index 7bf520c2..6f117b4f 100644 --- a/FrEee.Core.Domain/Objects/Civilization/Orders/ActivateAbilityOrder.cs +++ b/FrEee.Core.Domain/Objects/Civilization/Orders/ActivateAbilityOrder.cs @@ -1,15 +1,15 @@ using FrEee.Objects.LogMessages; using FrEee.Objects.Space; -using FrEee.Objects.Vehicles; using FrEee.Modding; using FrEee.Serialization; using FrEee.Extensions; using System.Collections.Generic; using System.Linq; -using FrEee.Objects.Technology; using FrEee.Objects.GameState; using FrEee.Processes.Combat; using FrEee.Modding.Abilities; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; namespace FrEee.Objects.Civilization.Orders; @@ -112,15 +112,14 @@ public void Execute(IOrderable ord) { executor.SupplyRemaining += Ability.Value1.Value.ToInt(); // TODO - normalize supplies on other stuff, not just space vehicles - if (executor is SpaceVehicle) - (executor as SpaceVehicle).NormalizeSupplies(); + if (executor is ISpaceVehicle sv) + sv.NormalizeSupplies(); Owner.RecordLog(executor, executor + " has activated its emergency resupply pod and now has " + executor.SupplyRemaining.ToUnitString(true) + " supplies.", LogMessageType.Generic); } else if (Ability.Rule.Matches("Emergency Energy")) { - if (executor is Vehicle) + if (executor is ISpaceVehicle v) { - var v = executor as Vehicle; v.EmergencySpeed += Ability.Value1.Value.ToInt(); Owner.RecordLog(executor, executor + " has activated its emergency propulsion and has had its speed boosted to " + v.StrategicSpeed + " temporarily.", LogMessageType.Generic); } diff --git a/FrEee.Core.Domain/Objects/Civilization/Orders/ColonizeOrder.cs b/FrEee.Core.Domain/Objects/Civilization/Orders/ColonizeOrder.cs index 04cd31cf..6adb2325 100644 --- a/FrEee.Core.Domain/Objects/Civilization/Orders/ColonizeOrder.cs +++ b/FrEee.Core.Domain/Objects/Civilization/Orders/ColonizeOrder.cs @@ -1,6 +1,5 @@ using FrEee.Objects.LogMessages; using FrEee.Objects.Space; -using FrEee.Objects.Vehicles; using FrEee.Modding; using FrEee.Serialization; using FrEee.Extensions; @@ -11,6 +10,7 @@ using FrEee.Objects.Civilization.Construction; using FrEee.Objects.GameState; using FrEee.Modding.Abilities; +using FrEee.Vehicles.Types; namespace FrEee.Objects.Civilization.Orders; @@ -79,7 +79,7 @@ public void Dispose() return; foreach (var v in Game.Current.Referrables.OfType()) { - if (v is SpaceVehicle sv) + if (v is ISpaceVehicle sv) sv.Orders.Remove(this); else if (v is Fleet f) f.Orders.Remove(this); diff --git a/FrEee.Core.Domain/Objects/Civilization/Orders/ConstructionOrder.cs b/FrEee.Core.Domain/Objects/Civilization/Orders/ConstructionOrder.cs index 207b875c..4f14755d 100644 --- a/FrEee.Core.Domain/Objects/Civilization/Orders/ConstructionOrder.cs +++ b/FrEee.Core.Domain/Objects/Civilization/Orders/ConstructionOrder.cs @@ -3,13 +3,13 @@ using System.Linq; using FrEee.Objects.LogMessages; using FrEee.Objects.Technology; -using FrEee.Objects.Vehicles; using FrEee.Modding; using FrEee.Utility; using FrEee.Serialization; using FrEee.Extensions; using FrEee.Objects.Civilization.Construction; using FrEee.Objects.GameState; +using FrEee.Vehicles.Types; namespace FrEee.Objects.Civilization.Orders; @@ -160,15 +160,14 @@ public void Execute(IOrderable q) if (!errors.Any()) { // create item if needed - if (Item == null) + if (Item is null) { Item = Template.Instantiate(); if (!(Item is Facility)) Item.Owner = queue.Owner; - if (Item is SpaceVehicle) + if (Item is ISpaceVehicle sv) { // space vehicles need their supplies filled up - var sv = (SpaceVehicle)(IConstructable)Item; sv.SupplyRemaining = sv.SupplyStorage; } } diff --git a/FrEee.Core.Domain/Objects/Civilization/Orders/PathfindingOrder.cs b/FrEee.Core.Domain/Objects/Civilization/Orders/PathfindingOrder.cs index 1301218a..e2cd0bca 100644 --- a/FrEee.Core.Domain/Objects/Civilization/Orders/PathfindingOrder.cs +++ b/FrEee.Core.Domain/Objects/Civilization/Orders/PathfindingOrder.cs @@ -254,17 +254,15 @@ public override string ToString() /// public void UpdateAlternateTarget() { - if (Target is Fleet) + if (Target is Fleet f) { - var f = (Fleet)Target; if (!f.IsDestroyed) AlternateTarget = f.LeafVehicles.Largest(); else Target = AlternateTarget; } - else if (Target is IMobileSpaceObject) + else if (Target is IMobileSpaceObject sobj) { - var sobj = (IMobileSpaceObject)Target; if (sobj.IsMemory && sobj.FindOriginalObject(Owner) != null) Target = (ISpaceObject)sobj.FindOriginalObject(Owner); if (!sobj.IsDestroyed) diff --git a/FrEee.Core.Domain/Objects/Civilization/Orders/RecycleBehaviors/ScrapBehavior.cs b/FrEee.Core.Domain/Objects/Civilization/Orders/RecycleBehaviors/ScrapBehavior.cs index d851583d..f4a3129a 100644 --- a/FrEee.Core.Domain/Objects/Civilization/Orders/RecycleBehaviors/ScrapBehavior.cs +++ b/FrEee.Core.Domain/Objects/Civilization/Orders/RecycleBehaviors/ScrapBehavior.cs @@ -1,10 +1,10 @@  using FrEee.Objects.LogMessages; using FrEee.Objects.Space; -using FrEee.Objects.Vehicles; using FrEee.Extensions; using System.Collections.Generic; using System.Linq; +using FrEee.Vehicles.Types; namespace FrEee.Objects.Civilization.Orders.RecycleBehaviors; @@ -45,7 +45,7 @@ public IEnumerable GetErrors(IMobileSpaceObject executor, IRecyclabl yield return target.CreateLogMessage($"{target} cannot be scrapped because it is already destroyed.", LogMessageType.Error); if (target.RecycleContainer != executor) yield return target.CreateLogMessage(target + " cannot be scrapped by " + executor + " because " + target + " does not belong to " + executor + ".", LogMessageType.Error); - if ((target is Ship || target is Base) && !executor.Sector.SpaceObjects.Any(sobj => sobj.Owner == executor.Owner && sobj.HasAbility("Space Yard"))) + if ((target is IMajorSpaceVehicle) && !executor.Sector.SpaceObjects.Any(sobj => sobj.Owner == executor.Owner && sobj.HasAbility("Space Yard"))) yield return target.CreateLogMessage(target + " cannot be scrapped at " + executor.Sector + " because there is no space yard present in that sector.", LogMessageType.Error); if (target is IUnit && !executor.Sector.SpaceObjects.Any(sobj => sobj.Owner == executor.Owner && (sobj is Planet || sobj.HasAbility("Space Yard")))) yield return target.CreateLogMessage(target + " cannot be scrapped at " + executor.Sector + " because there is no space yard or colony present in that sector.", LogMessageType.Error); diff --git a/FrEee.Core.Domain/Objects/Civilization/Orders/RecycleVehicleInSpaceOrder.cs b/FrEee.Core.Domain/Objects/Civilization/Orders/RecycleVehicleInSpaceOrder.cs index 0fb6d4ff..e534074b 100644 --- a/FrEee.Core.Domain/Objects/Civilization/Orders/RecycleVehicleInSpaceOrder.cs +++ b/FrEee.Core.Domain/Objects/Civilization/Orders/RecycleVehicleInSpaceOrder.cs @@ -1,8 +1,8 @@ using FrEee.Objects.GameState; using FrEee.Objects.LogMessages; using FrEee.Objects.Space; -using FrEee.Objects.Vehicles; using FrEee.Serialization; +using FrEee.Vehicles.Types; using System.Collections.Generic; using System.Linq; @@ -57,7 +57,7 @@ public void Dispose() { if (IsDisposed) return; - foreach (var v in Game.Current.Referrables.OfType()) + foreach (var v in Game.Current.Referrables.OfType()) v.Orders.Remove(this); Game.Current.UnassignID(this); } diff --git a/FrEee.Core.Domain/Objects/Civilization/Orders/SentryOrder.cs b/FrEee.Core.Domain/Objects/Civilization/Orders/SentryOrder.cs index 87f31010..48634dc5 100644 --- a/FrEee.Core.Domain/Objects/Civilization/Orders/SentryOrder.cs +++ b/FrEee.Core.Domain/Objects/Civilization/Orders/SentryOrder.cs @@ -1,6 +1,5 @@ using FrEee.Objects.LogMessages; using FrEee.Objects.Space; -using FrEee.Objects.Vehicles; using FrEee.Serialization; using FrEee.Extensions; using System; @@ -8,6 +7,7 @@ using System.Linq; using FrEee.Objects.GameState; using FrEee.Processes.Combat; +using FrEee.Vehicles.Types; namespace FrEee.Objects.Civilization.Orders; @@ -66,7 +66,7 @@ public void Dispose() { if (IsDisposed) return; - foreach (var v in Game.Current.Referrables.OfType()) + foreach (var v in Game.Current.Referrables.OfType()) v.Orders.Remove(this); Game.Current.UnassignID(this); } diff --git a/FrEee.Core.Domain/Objects/GameState/Game.cs b/FrEee.Core.Domain/Objects/GameState/Game.cs index 88e4afb5..68d73342 100644 --- a/FrEee.Core.Domain/Objects/GameState/Game.cs +++ b/FrEee.Core.Domain/Objects/GameState/Game.cs @@ -13,7 +13,6 @@ using System.Linq; using System.Reflection; using FrEee.Objects.Civilization.Construction; -using FrEee.Objects.Vehicles; using FrEee.Objects.Civilization.Orders; using FrEee.Objects.Space; using FrEee.Processes.Combat; @@ -23,6 +22,7 @@ using FrEee.Modding.Loaders; using FrEee.Gameplay.Commands; using FrEee.Gameplay.Commands.Notes; +using FrEee.Vehicles.Types; namespace FrEee.Objects.GameState; diff --git a/FrEee.Core.Domain/Objects/SimulatedObjectWrappers.cs b/FrEee.Core.Domain/Objects/SimulatedObjectWrappers.cs index 394668b7..c668825c 100644 --- a/FrEee.Core.Domain/Objects/SimulatedObjectWrappers.cs +++ b/FrEee.Core.Domain/Objects/SimulatedObjectWrappers.cs @@ -2,8 +2,8 @@ using FrEee.Extensions; using System; using System.Collections.Generic; -using FrEee.Objects.Vehicles; using FrEee.Processes.Combat; +using FrEee.Vehicles.Types; namespace FrEee.Objects; diff --git a/FrEee.Core.Domain/Objects/Space/Fleet.cs b/FrEee.Core.Domain/Objects/Space/Fleet.cs index ea9ba16e..df350798 100644 --- a/FrEee.Core.Domain/Objects/Space/Fleet.cs +++ b/FrEee.Core.Domain/Objects/Space/Fleet.cs @@ -1,6 +1,5 @@ using FrEee.Objects.Civilization; using FrEee.Objects.Technology; -using FrEee.Objects.Vehicles; using FrEee.Modding; using FrEee.Utility; using FrEee.Serialization; @@ -16,6 +15,7 @@ using FrEee.Objects.GameState; using FrEee.Processes.Combat; using FrEee.Modding.Abilities; +using FrEee.Vehicles.Types; namespace FrEee.Objects.Space; @@ -288,20 +288,22 @@ public bool IsMemory /// /// All space vehicles in this fleet and subfleets, but not counting the subfleets themselves. /// - public IEnumerable LeafVehicles + public IEnumerable LeafVehicles { get { return Vehicles.SelectMany(v => { - var list = new List(); - if (v is Fleet) + var list = new List(); + if (v is Fleet f) { - foreach (var v2 in ((Fleet)v).LeafVehicles) + foreach (var v2 in f.LeafVehicles) list.Add(v2); } - else if (v is SpaceVehicle) - list.Add((SpaceVehicle)v); + else if (v is ISpaceVehicle sv) + { + list.Add(sv); + } return list; }); } @@ -899,13 +901,13 @@ private IEnumerable GetImagePaths(string imagetype) yield break; string imageName = "Fleet"; - if (LeafVehicles.All(v => v is Fighter)) + if (LeafVehicles.All(v => v.VehicleType == VehicleTypes.Fighter)) imageName = "FighterGroup"; - else if (LeafVehicles.All(v => v is Satellite)) + else if (LeafVehicles.All(v => v.VehicleType == VehicleTypes.Satellite)) imageName = "SatelliteGroup"; - else if (LeafVehicles.All(v => v is Drone)) + else if (LeafVehicles.All(v => v.VehicleType == VehicleTypes.Drone)) imageName = "DroneGroup"; - else if (LeafVehicles.All(v => v is Mine)) + else if (LeafVehicles.All(v => v.VehicleType == VehicleTypes.Mine)) imageName = "MineGroup"; if (Mod.Current.RootPath != null) diff --git a/FrEee.Core.Domain/Objects/Space/IMobileSpaceObject.cs b/FrEee.Core.Domain/Objects/Space/IMobileSpaceObject.cs index b4270a16..def01779 100644 --- a/FrEee.Core.Domain/Objects/Space/IMobileSpaceObject.cs +++ b/FrEee.Core.Domain/Objects/Space/IMobileSpaceObject.cs @@ -9,7 +9,7 @@ namespace FrEee.Objects.Space; /// /// An object that can move about in space and/or receive orders. /// -public interface IMobileSpaceObject : ICombatSpaceObject, IOrderable, IContainable, IDamageableReferrable +public interface IMobileSpaceObject : ICombatSpaceObject, IOrderable, IContainable, IDamageableReferrable, IHasMaintenanceCost { new Fleet Container { get; set; } @@ -17,8 +17,6 @@ public interface IMobileSpaceObject : ICombatSpaceObject, IOrderable, IContainab /// The Dijkstra map used for pathfinding. /// IDictionary, ISet>> DijkstraMap { get; set; } - - ResourceQuantity MaintenanceCost { get; } int MovementRemaining { get; set; } new Sector Sector { get; set; } @@ -36,6 +34,7 @@ public interface IMobileSpaceObject : ICombatSpaceObject, IOrderable, IContainab void SpendTime(double timeElapsed); } +// HACK: find a way to get rid of this generic interface, it's stupid... public interface IMobileSpaceObject : IMobileSpaceObject where T : IMobileSpaceObject { //new IList Orders { get; } diff --git a/FrEee.Core.Domain/Objects/Space/ISpaceObject.cs b/FrEee.Core.Domain/Objects/Space/ISpaceObject.cs index e75ba0d5..ef532dd4 100644 --- a/FrEee.Core.Domain/Objects/Space/ISpaceObject.cs +++ b/FrEee.Core.Domain/Objects/Space/ISpaceObject.cs @@ -1,9 +1,10 @@ using FrEee.Modding.Abilities; +using FrEee.Objects.Civilization; using FrEee.Objects.GameState; using FrEee.Utility; namespace FrEee.Objects.Space; -public interface ISpaceObject : IOwnableAbilityObject, IPictorial, IReferrable, IFoggable, INamed, ILocated +public interface ISpaceObject : IOwnableAbilityObject, IPictorial, IReferrable, IFoggable, INameable, ILocated { /// /// Can this space object be placed in a fleet? @@ -36,11 +37,6 @@ public interface ISpaceObject : IOwnableAbilityObject, IPictorial, IReferrable, /// bool IsIdle { get; } - /// - /// The name of this space object. - /// - new string Name { get; set; } - /// /// Resources stored on this space object. /// For a ship, this could include supplies. @@ -51,4 +47,13 @@ public interface ISpaceObject : IOwnableAbilityObject, IPictorial, IReferrable, /// Supply storage capacity. /// int SupplyStorage { get; } + + /// + /// Resolves ambiguity between INamed and INameable. + /// + new string Name + { + get => ((INameable)this).Name; + set => ((INameable)this).Name = value; + } } \ No newline at end of file diff --git a/FrEee.Core.Domain/Objects/Space/Planet.cs b/FrEee.Core.Domain/Objects/Space/Planet.cs index f593a9bc..eb5abbd6 100644 --- a/FrEee.Core.Domain/Objects/Space/Planet.cs +++ b/FrEee.Core.Domain/Objects/Space/Planet.cs @@ -1,6 +1,5 @@ using FrEee.Objects.Civilization; using FrEee.Objects.Technology; -using FrEee.Objects.Vehicles; using FrEee.Modding; using FrEee.Modding.Templates; using FrEee.Utility; @@ -17,6 +16,7 @@ using FrEee.Objects.GameState; using FrEee.Processes.Combat; using FrEee.Modding.Abilities; +using FrEee.Vehicles.Types; namespace FrEee.Objects.Space; @@ -584,7 +584,7 @@ public IEnumerable Weapons { if (Cargo == null) return Enumerable.Empty(); - return Cargo.Units.OfType().SelectMany(wp => wp.Weapons).Where(x => !x.IsDestroyed); + return Cargo.Units.Where(q => q.CanFireIntoSpaceFromPlanetaryCargo).SelectMany(wp => wp.Weapons).Where(x => !x.IsDestroyed); } } @@ -647,7 +647,7 @@ public void BurnMovementSupplies() // do nothing } - public bool CanTarget(ITargetable target) => Cargo?.Units.OfType().Any(wp => wp.CanTarget(target)) ?? false; + public bool CanTarget(ITargetable target) => Cargo?.Units.Where(q => q.CanFireIntoSpaceFromPlanetaryCargo).Any(wp => wp.CanTarget(target)) ?? false; /// /// Deletes this planet and spawns an asteroid field with the same name, sector, size, and value as this planet. @@ -1041,7 +1041,8 @@ private int TakePopulationDamage(Hit hit, PRNG dice = null) public Progress AngerProgress => new Progress(Colony?.AverageAnger ?? 0, Mod.Current.Settings.MaxAnger); - public IEnumerable Components => Cargo.Units.OfType().SelectMany(q => q.Components); + // TODO: units that can't fire into space from planetary cargo but still count as components for planets? + public IEnumerable Components => Cargo.Units.Where(q => q.CanFireIntoSpaceFromPlanetaryCargo).SelectMany(q => q.Components); public bool FillsCombatTile => true; } diff --git a/FrEee.Core.Domain/Objects/Space/Sector.cs b/FrEee.Core.Domain/Objects/Space/Sector.cs index 564f263f..db50a1ae 100644 --- a/FrEee.Core.Domain/Objects/Space/Sector.cs +++ b/FrEee.Core.Domain/Objects/Space/Sector.cs @@ -8,9 +8,9 @@ using System.Linq; using System.Text.RegularExpressions; using FrEee.Objects.Civilization.CargoStorage; -using FrEee.Objects.Vehicles; using FrEee.Objects.GameState; using FrEee.Modding.Abilities; +using FrEee.Vehicles.Types; namespace FrEee.Objects.Space; diff --git a/FrEee.Core.Domain/Objects/Technology/Component.cs b/FrEee.Core.Domain/Objects/Technology/Component.cs index 6da132db..6b91918f 100644 --- a/FrEee.Core.Domain/Objects/Technology/Component.cs +++ b/FrEee.Core.Domain/Objects/Technology/Component.cs @@ -8,10 +8,10 @@ using System.Collections.Generic; using System.Drawing; using System.Linq; -using FrEee.Objects.Vehicles; using FrEee.Objects.GameState; using FrEee.Processes.Combat; using FrEee.Modding.Abilities; +using FrEee.Vehicles; namespace FrEee.Objects.Technology; diff --git a/FrEee.Core.Domain/Objects/Technology/ComponentReference.cs b/FrEee.Core.Domain/Objects/Technology/ComponentReference.cs index db5bcfa0..cb61393e 100644 --- a/FrEee.Core.Domain/Objects/Technology/ComponentReference.cs +++ b/FrEee.Core.Domain/Objects/Technology/ComponentReference.cs @@ -1,9 +1,9 @@ using System.Collections.Generic; using FrEee.Serialization; using FrEee.Extensions; -using FrEee.Objects.Vehicles; using FrEee.Objects.GameState; using FrEee.Utility; +using FrEee.Vehicles; namespace FrEee.Objects.Technology; diff --git a/FrEee.Core.Domain/Objects/Technology/IHull.cs b/FrEee.Core.Domain/Objects/Technology/IHull.cs deleted file mode 100644 index 0671ccda..00000000 --- a/FrEee.Core.Domain/Objects/Technology/IHull.cs +++ /dev/null @@ -1,103 +0,0 @@ -using FrEee.Utility; -using System.Collections.Generic; -using System.Drawing; -using FrEee.Objects.Vehicles; -using FrEee.Objects.GameState; -using FrEee.Modding; -using FrEee.Modding.Abilities; - -namespace FrEee.Objects.Technology; - -public interface IHull : IModObject, IResearchable, IAbilityContainer, IPictorial, IUpgradeable -{ - /// - /// Can this hull use components with the Ship Auxiliary Control ability? - /// - bool CanUseAuxiliaryControl { get; set; } - - string Code { get; set; } - ResourceQuantity Cost { get; set; } - string Description { get; set; } - - /// - /// Maximum number of engines allowed. - /// - int MaxEngines { get; set; } - - /// - /// Required number of crew quarters components. - /// - int MinCrewQuarters { get; set; } - - /// - /// Required number of life support components. - /// - int MinLifeSupport { get; set; } - - /// - /// Minimum percentage of space required to be used for cargo-storage components. - /// - int MinPercentCargoBays { get; set; } - - /// - /// Minimum percentage of space required to be used for colonizing components. - /// - int MinPercentColonyModules { get; set; } - - /// - /// Minimum percentage of space required to be used for fighter-launching components. - /// - int MinPercentFighterBays { get; set; } - - new string Name { get; set; } - - /// - /// Does this hull need a component with the Ship Bridge ability? - /// - bool NeedsBridge { get; set; } - - IList PictureNames { get; } - - string ShortName { get; set; } - - int Size { get; set; } - - /// - /// Thrust points required to move one sector per turn. - /// SE4 called this "engines per move" but this was a misnomer because engines were allowed to produce more than one thrust point. - /// - int ThrustPerMove { get; set; } - - /// - /// The vehicle type of this hull. - /// - VehicleTypes VehicleType { get; } - - string VehicleTypeName { get; } - - /// - /// Can this hull use a mount? - /// - /// - /// - bool CanUseMount(Mount m); - - Image GetIcon(string shipsetPath); - - Image GetPortrait(string shipsetPath); -} - -/// -/// A vehicle hull. -/// -public interface IHull : IHull, IUpgradeable> where T : IVehicle -{ - new bool IsObsolescent { get; } - - // to deal with ambiguity between implementing IHull and IHull - new bool IsObsolete { get; } - - new IHull LatestVersion { get; } - new IEnumerable> NewerVersions { get; } - new IEnumerable> OlderVersions { get; } -} \ No newline at end of file diff --git a/FrEee.Core.Domain/Objects/Technology/Mount.cs b/FrEee.Core.Domain/Objects/Technology/Mount.cs index a9e8d5c7..f0c6b1d4 100644 --- a/FrEee.Core.Domain/Objects/Technology/Mount.cs +++ b/FrEee.Core.Domain/Objects/Technology/Mount.cs @@ -6,9 +6,9 @@ using System.Drawing; using System.IO; using FrEee.Objects.GameState; -using FrEee.Objects.Vehicles; using FrEee.Processes.Combat; using FrEee.Modding.Abilities; +using FrEee.Vehicles.Types; namespace FrEee.Objects.Technology; diff --git a/FrEee.Core.Domain/Objects/Technology/MountedComponentTemplate.cs b/FrEee.Core.Domain/Objects/Technology/MountedComponentTemplate.cs index 46c7e962..ad3502f4 100644 --- a/FrEee.Core.Domain/Objects/Technology/MountedComponentTemplate.cs +++ b/FrEee.Core.Domain/Objects/Technology/MountedComponentTemplate.cs @@ -1,6 +1,5 @@ using FrEee.Objects.Civilization; using FrEee.Processes.Combat; -using FrEee.Objects.Vehicles; using FrEee.Modding; using FrEee.Modding.Templates; using FrEee.Utility; @@ -13,6 +12,7 @@ using FrEee.Objects.GameState; using FrEee.Modding.Abilities; using FrEee.Objects.Space; +using FrEee.Vehicles; namespace FrEee.Objects.Technology; @@ -274,7 +274,7 @@ public IDictionary Variables { get { - var design = Container ?? Design.Create(Mod.Current.Hulls.FirstOrDefault(h => ComponentTemplate.VehicleTypes.HasFlag(h.VehicleType))); + var design = Container ?? DIRoot.Designs.Build(Mod.Current.Hulls.FirstOrDefault(h => ComponentTemplate.VehicleTypes.HasFlag(h.VehicleType))); var empire = Container == null ? Empire.Current : Container.Owner; return new Dictionary { diff --git a/FrEee.Core.Domain/Objects/Technology/MountedComponentTemplateContainerPopulator.cs b/FrEee.Core.Domain/Objects/Technology/MountedComponentTemplateContainerPopulator.cs index a8389518..fd91e408 100644 --- a/FrEee.Core.Domain/Objects/Technology/MountedComponentTemplateContainerPopulator.cs +++ b/FrEee.Core.Domain/Objects/Technology/MountedComponentTemplateContainerPopulator.cs @@ -1,7 +1,7 @@ using System.Linq; using FrEee.Objects.GameState; -using FrEee.Objects.Vehicles; using FrEee.Utility; +using FrEee.Vehicles; namespace FrEee.Objects.Technology; /// diff --git a/FrEee.Core.Domain/Objects/Vehicles/IDesign.cs b/FrEee.Core.Domain/Objects/Vehicles/IDesign.cs deleted file mode 100644 index 08af8702..00000000 --- a/FrEee.Core.Domain/Objects/Vehicles/IDesign.cs +++ /dev/null @@ -1,152 +0,0 @@ -using FrEee.Objects.Civilization; -using FrEee.Objects.Technology; -using FrEee.Modding.Templates; -using FrEee.Utility; -using System.Collections.Generic; -using FrEee.Objects.Civilization.Construction; -using FrEee.Objects.GameState; -using FrEee.Modding.Abilities; -using FrEee.Gameplay.Commands.Designs; - -namespace FrEee.Objects.Vehicles; - -/// -/// A vehicle design. -/// -public interface IDesign : INamed, IPictorial, IOwnableAbilityObject, IConstructionTemplate, IPromotable, IFoggable, IUpgradeable, ICleanable -{ - int Accuracy { get; } - - int ArmorHitpoints { get; } - - /// - /// The base name of the design, without the iteration number. - /// - string BaseName { get; set; } - - int CargoCapacity { get; } - - int CargoStorage { get; } - - /// - /// The movement speed of the design in combat. - /// - double CombatSpeed { get; } - - /// - /// The vehicle's components. - /// - IList Components { get; } - - int Evasion { get; } - - /// - /// The vehicle's hull. - /// - IHull Hull { get; set; } - - int HullHitpoints { get; } - - /// - /// Is this a newly created design on the client side that needs to be sent to the server? - /// - bool IsNew { get; set; } - - /// - /// Is this design obsolete? - /// Note that foreign designs will never be obsoleted, since you don't know when their owner obsoleted them. - /// - new bool IsObsolete { get; set; } - - /// - /// Is this design valid in the current mod? Or is it using techs from other mods? - /// - bool IsValidInMod { get; } - - int Iteration { get; set; } - - ResourceQuantity MaintenanceCost { get; } - - /// - /// The name of the design. - /// - new string Name { get; } - - /// - /// The empire which created this design. - /// - new Empire Owner { get; set; } - - /// - /// The ship's role (design type in SE4). - /// - string Role { get; set; } - - int ShieldHitpoints { get; } - - int ShieldRegeneration { get; } - - /// - /// Unused space on the design. - /// - int SpaceFree { get; } - - /// - /// The movement speed of the design, in sectors per turn. - /// - int StrategicSpeed { get; } - - int SupplyStorage { get; } - - /// - /// Supply used for each sector of movement. - /// - int SupplyUsagePerSector { get; } - - /// - /// The turn this design was created (for our designs) or discovered (for alien designs). - /// - int TurnNumber { get; set; } - - int VehiclesBuilt { get; set; } - - /// - /// The vehicle type. - /// - VehicleTypes VehicleType { get; } - - /// - /// The name of the vehicle type. - /// - string VehicleTypeName { get; } - - /// - /// Warnings that need to be resolved before the design can be saved. - /// - IEnumerable Warnings { get; } - - void AddComponent(ComponentTemplate ct, Mount m = null); - - /// - /// Creates an order to build this design. - /// - /// - IConstructionOrder CreateConstructionOrder(ConstructionQueue queue); - - /// - /// Creates a command to create this design on the server. - /// - /// - ICreateDesignCommand CreateCreationCommand(); - - IVehicle Instantiate(); - - IDesign Upgrade(); -} - -public interface IDesign : IDesign, IPictorial, IReferrable, IUpgradeable> where T : IVehicle -{ - new T Instantiate(); - - new IDesign Upgrade(); -} diff --git a/FrEee.Core.Domain/Objects/Vehicles/IUnit.cs b/FrEee.Core.Domain/Objects/Vehicles/IUnit.cs deleted file mode 100644 index b0ddb449..00000000 --- a/FrEee.Core.Domain/Objects/Vehicles/IUnit.cs +++ /dev/null @@ -1,11 +0,0 @@ -using FrEee.Objects.Civilization.CargoStorage; -using FrEee.Objects.GameState; - -namespace FrEee.Objects.Vehicles; - -/// -/// A vehicle which can be contained in cargo. -/// -public interface IUnit : IVehicle, IContainable -{ -} \ No newline at end of file diff --git a/FrEee.Core.Domain/Objects/Vehicles/IVehicle.cs b/FrEee.Core.Domain/Objects/Vehicles/IVehicle.cs deleted file mode 100644 index 04967e2f..00000000 --- a/FrEee.Core.Domain/Objects/Vehicles/IVehicle.cs +++ /dev/null @@ -1,37 +0,0 @@ -using FrEee.Objects.Civilization; -using FrEee.Objects.Civilization.Construction; -using FrEee.Objects.Civilization.Orders; -using FrEee.Objects.Technology; -using FrEee.Serialization; -using FrEee.Utility; -using System.Collections.Generic; -using FrEee.Processes.Combat; -using FrEee.Modding.Abilities; -using FrEee.Objects.GameState; - -namespace FrEee.Objects.Vehicles; - -/// -/// A space or ground vehicle. -/// -public interface IVehicle : IConstructable, IOwnableAbilityObject, IReferrable, IDamageable, ICombatant, IRecyclable, IIncomeProducer, IUpgradeable, INameable -{ - [DoNotSerialize(false)] - new IList Components { get; } - - /// - /// Damage that has been applied to this vehicle's components. - /// - SafeDictionary> Damage { get; set; } - - /// - /// The design of this vehicle. - /// - [DoNotCopy] - IDesign Design { get; set; } - - /// - /// Cost to maintain this vehicle per turn. - /// - ResourceQuantity MaintenanceCost { get; } -} diff --git a/FrEee.Core.Domain/Objects/Vehicles/VehicleTypes.cs b/FrEee.Core.Domain/Objects/Vehicles/VehicleTypes.cs deleted file mode 100644 index a49b0cd0..00000000 --- a/FrEee.Core.Domain/Objects/Vehicles/VehicleTypes.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using FrEee.Utility; -namespace FrEee.Objects.Vehicles; - -/// -/// Vehicle types. Used for restricting component placement. -/// -[Flags] -public enum VehicleTypes -{ - None = 0x0, - - [Name("Ships")] - Ship = 0x1, - - [Name("Bases")] - Base = 0x2, - - [Name("Fighters")] - [Name("Ftr")] - Fighter = 0x4, - - [Name("Satellites")] - [Name("Sat")] - Satellite = 0x8, - - [Name("Mines")] - Mine = 0x10, - - [Name("Troops")] - [Name("Troop")] - [Name("Trp")] - Troop = 0x20, - - [Name("Drones")] - Drone = 0x40, - - [Name("WeapPlatform")] - [Name("WeapPlatforms")] - [Name("WeapPlat")] - [Name("WeapPlats")] - [Name("WeaponPlatforms")] - [CanonicalName("Weapon Platform")] - [Name("Weapon Platforms")] - WeaponPlatform = 0x80, - - [Name("Any")] - All = Ship | Base | Fighter | Satellite | Mine | Troop | Drone | WeaponPlatform, - - Invalid = 0x1000, -} \ No newline at end of file diff --git a/FrEee.Core.Domain/Utility/DIRoot.cs b/FrEee.Core.Domain/Utility/DIRoot.cs index dace8242..c24fb0ba 100644 --- a/FrEee.Core.Domain/Utility/DIRoot.cs +++ b/FrEee.Core.Domain/Utility/DIRoot.cs @@ -13,6 +13,7 @@ using FrEee.Gameplay.Commands.Waypoints; using FrEee.Processes; using FrEee.Processes.Combat; +using FrEee.Vehicles; namespace FrEee.Utility; @@ -70,4 +71,19 @@ public static class DIRoot /// Allows players to manage waypoints. /// public static IWaypointCommandFactory WaypointCommands => DI.Get(); + + /// + /// Creates vehicle hulls. + /// + public static IHullFactory Hulls => DI.Get(); + + /// + /// Creates vehicle designs. + /// + public static IDesignFactory Designs => DI.Get(); + + /// + /// Creates vehicles. + /// + public static IVehicleFactory Vehicles => DI.Get(); } diff --git a/FrEee.Core.Domain/Utility/Pictures.cs b/FrEee.Core.Domain/Utility/Pictures.cs index 389057db..8a2cfc65 100644 --- a/FrEee.Core.Domain/Utility/Pictures.cs +++ b/FrEee.Core.Domain/Utility/Pictures.cs @@ -1,7 +1,6 @@ using FrEee.Objects.Civilization; using FrEee.Objects.Space; using FrEee.Objects.Technology; -using FrEee.Objects.Vehicles; using FrEee.Modding; using FrEee.Modding.Templates; using FrEee.Extensions; @@ -14,6 +13,8 @@ using System.Reflection; using FrEee.Processes.Combat; using FrEee.Processes.Setup; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; namespace FrEee.Utility; @@ -261,6 +262,12 @@ public static Image GetGenericImage(double scale = 1.0) return GetGenericImage(typeof(T), scale); } + public static Image GetGenericImage(VehicleTypes vt, double scale = 1.0) + { + // TODO: generic images per vehicle type + return GetGenericImage(scale); + } + /// /// Gets a generic image for a type of object. /// @@ -416,13 +423,13 @@ public static Image GetIcon(Fleet fleet, string shipsetPath, int size = 32) var paths = new List(); string imageName = "Fleet"; - if (fleet.LeafVehicles.All(v => v is Fighter)) + if (fleet.LeafVehicles.All(v => v.VehicleType == VehicleTypes.Fighter)) imageName = "FighterGroup"; - else if (fleet.LeafVehicles.All(v => v is Satellite)) + else if (fleet.LeafVehicles.All(v => v.VehicleType == VehicleTypes.Satellite)) imageName = "SatelliteGroup"; - else if (fleet.LeafVehicles.All(v => v is Drone)) + else if (fleet.LeafVehicles.All(v => v.VehicleType == VehicleTypes.Drone)) imageName = "DroneGroup"; - else if (fleet.LeafVehicles.All(v => v is Mine)) + else if (fleet.LeafVehicles.All(v => v.VehicleType == VehicleTypes.Mine)) imageName = "MineGroup"; if (Mod.Current.RootPath != null) @@ -776,13 +783,13 @@ public static Image GetPortrait(Fleet fleet, string shipsetPath) var paths = new List(); string imageName = "Fleet"; - if (fleet.LeafVehicles.All(v => v is Fighter)) + if (fleet.LeafVehicles.All(v => v.VehicleType == VehicleTypes.Fighter)) imageName = "FighterGroup"; - else if (fleet.LeafVehicles.All(v => v is Satellite)) + else if (fleet.LeafVehicles.All(v => v.VehicleType == VehicleTypes.Satellite)) imageName = "SatelliteGroup"; - else if (fleet.LeafVehicles.All(v => v is Drone)) + else if (fleet.LeafVehicles.All(v => v.VehicleType == VehicleTypes.Drone)) imageName = "DroneGroup"; - else if (fleet.LeafVehicles.All(v => v is Mine)) + else if (fleet.LeafVehicles.All(v => v.VehicleType == VehicleTypes.Mine)) imageName = "MineGroup"; if (Mod.Current.RootPath != null) @@ -867,47 +874,38 @@ public static Image GetVehicleTypeImage(string shipsetPath, VehicleTypes vt = Ve { case VehicleTypes.Base: hullname = "BattleStation"; - hulltype = typeof(Base); break; case VehicleTypes.Drone: hullname = "Drone"; - hulltype = typeof(Drone); break; case VehicleTypes.Fighter: hullname = "FighterMedium"; - hulltype = typeof(Fighter); break; case VehicleTypes.Mine: hullname = "Mine"; - hulltype = typeof(Mine); break; case VehicleTypes.Satellite: hullname = "Satellite"; - hulltype = typeof(Satellite); break; case VehicleTypes.Ship: hullname = "Cruiser"; - hulltype = typeof(Ship); break; case VehicleTypes.Troop: hullname = "TroopMedium"; - hulltype = typeof(Troop); break; case VehicleTypes.WeaponPlatform: hullname = "WeapPlatformMedium"; - hulltype = typeof(WeaponPlatform); break; default: hullname = "Fighter"; - hulltype = typeof(Fighter); break; } @@ -919,7 +917,7 @@ public static Image GetVehicleTypeImage(string shipsetPath, VehicleTypes vt = Ve paths.Add(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "Pictures", "Races", shipsetPath, "Portrait_" + hullname)); paths.Add(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "Pictures", "Races", shipsetPath, shipsetPath + "_Portrait_" + hullname)); // for SE4 shipset compatibility - return GetCachedImage(paths) ?? GetGenericImage(hulltype); + return GetCachedImage(paths) ?? GetGenericImage(vt); } /// diff --git a/FrEee.Core.Domain/Vehicles/IDesign.cs b/FrEee.Core.Domain/Vehicles/IDesign.cs new file mode 100644 index 00000000..16d8f4d7 --- /dev/null +++ b/FrEee.Core.Domain/Vehicles/IDesign.cs @@ -0,0 +1,157 @@ +using FrEee.Objects.Civilization; +using FrEee.Objects.Technology; +using FrEee.Modding.Templates; +using FrEee.Utility; +using System.Collections.Generic; +using FrEee.Objects.Civilization.Construction; +using FrEee.Objects.GameState; +using FrEee.Modding.Abilities; +using FrEee.Gameplay.Commands.Designs; +using FrEee.Vehicles.Types; + +namespace FrEee.Vehicles; + +/// +/// A vehicle design. +/// +public interface IDesign : INamed, IPictorial, IOwnableAbilityObject, IConstructionTemplate, IPromotable, IFoggable, IUpgradeable, ICleanable +{ + int Accuracy { get; } + + int ArmorHitpoints { get; } + + /// + /// The base name of the design, without the iteration number. + /// + string BaseName { get; set; } + + bool CanInvadeAndPoliceColonies { get; } + + int CargoCapacity { get; } + + int CargoStorage { get; } + + /// + /// The movement speed of the design in combat. + /// + double CombatSpeed { get; } + + /// + /// The vehicle's components. + /// + IList Components { get; } + + int Evasion { get; } + + /// + /// The vehicle's hull. + /// + IHull Hull { get; set; } + + int HullHitpoints { get; } + + /// + /// Is this a newly created design on the client side that needs to be sent to the server? + /// + bool IsNew { get; set; } + + /// + /// Is this design obsolete? + /// Note that foreign designs will never be obsoleted, since you don't know when their owner obsoleted them. + /// + new bool IsObsolete { get; set; } + + bool IsSpaceVehicleDesign { get; } + + /// + /// Is this design valid in the current mod? Or is it using techs from other mods? + /// + bool IsValidInMod { get; } + + int Iteration { get; set; } + + ResourceQuantity MaintenanceCost { get; } + + /// + /// The name of the design. + /// + new string Name { get; } + + /// + /// The empire which created this design. + /// + new Empire Owner { get; set; } + + /// + /// The ship's role (design type in SE4). + /// + string Role { get; set; } + + int ShieldHitpoints { get; } + + int ShieldRegeneration { get; } + + /// + /// Unused space on the design. + /// + int SpaceFree { get; } + + /// + /// The movement speed of the design, in sectors per turn. + /// + int StrategicSpeed { get; } + + int SupplyStorage { get; } + + /// + /// Supply used for each sector of movement. + /// + int SupplyUsagePerSector { get; } + + /// + /// The turn this design was created (for our designs) or discovered (for alien designs). + /// + int TurnNumber { get; set; } + + int VehiclesBuilt { get; set; } + + /// + /// The vehicle type. + /// + VehicleTypes VehicleType { get; } + + /// + /// The name of the vehicle type. + /// + string VehicleTypeName { get; } + + /// + /// Warnings that need to be resolved before the design can be saved. + /// + IEnumerable Warnings { get; } + + void AddComponent(ComponentTemplate ct, Mount m = null); + + /// + /// Creates an order to build this design. + /// + /// + IConstructionOrder CreateConstructionOrder(ConstructionQueue queue); + + /// + /// Creates a command to create this design on the server. + /// + /// + ICreateDesignCommand CreateCreationCommand(); + + IVehicle Instantiate(); + + IDesign Upgrade(); +} + +public interface IDesign : IDesign, IPictorial, IReferrable, IUpgradeable> where T : IVehicle +{ + new T Instantiate(); + + new IDesign Upgrade(); +} diff --git a/FrEee.Core.Domain/Vehicles/IDesignFactory.cs b/FrEee.Core.Domain/Vehicles/IDesignFactory.cs new file mode 100644 index 00000000..8655cda1 --- /dev/null +++ b/FrEee.Core.Domain/Vehicles/IDesignFactory.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Vehicles.Types; + +namespace FrEee.Vehicles; + +/// +/// Build vehicle designs. +/// +public interface IDesignFactory +{ + /// + /// Builds a design with a specific vehicle type. + /// + /// The vehicle type to build. + /// The built design, with no hull or components. + IDesign Build(VehicleTypes vehicleType); + + /// + /// Builds a design with a specific hull. + /// + /// The hull to use on the design. + /// The built design, with a hull but no components. + IDesign Build(IHull hull); + + /// + /// Imports designs from the user's library into the current game. + /// + IEnumerable ImportFromLibrary(); + + /// + /// The standard militia unit design for use in defending colonies. + /// + IDesign Militia { get; } +} diff --git a/FrEee.Core.Domain/Vehicles/IHull.cs b/FrEee.Core.Domain/Vehicles/IHull.cs new file mode 100644 index 00000000..12f1cf79 --- /dev/null +++ b/FrEee.Core.Domain/Vehicles/IHull.cs @@ -0,0 +1,104 @@ +using FrEee.Utility; +using System.Collections.Generic; +using System.Drawing; +using FrEee.Objects.GameState; +using FrEee.Modding; +using FrEee.Modding.Abilities; +using FrEee.Objects.Technology; +using FrEee.Vehicles.Types; + +namespace FrEee.Vehicles; + +public interface IHull : IModObject, IResearchable, IAbilityContainer, IPictorial, IUpgradeable +{ + /// + /// Can this hull use components with the Ship Auxiliary Control ability? + /// + bool CanUseAuxiliaryControl { get; set; } + + string Code { get; set; } + ResourceQuantity Cost { get; set; } + string Description { get; set; } + + /// + /// Maximum number of engines allowed. + /// + int MaxEngines { get; set; } + + /// + /// Required number of crew quarters components. + /// + int MinCrewQuarters { get; set; } + + /// + /// Required number of life support components. + /// + int MinLifeSupport { get; set; } + + /// + /// Minimum percentage of space required to be used for cargo-storage components. + /// + int MinPercentCargoBays { get; set; } + + /// + /// Minimum percentage of space required to be used for colonizing components. + /// + int MinPercentColonyModules { get; set; } + + /// + /// Minimum percentage of space required to be used for fighter-launching components. + /// + int MinPercentFighterBays { get; set; } + + new string Name { get; set; } + + /// + /// Does this hull need a component with the Ship Bridge ability? + /// + bool NeedsBridge { get; set; } + + IList PictureNames { get; } + + string ShortName { get; set; } + + int Size { get; set; } + + /// + /// Thrust points required to move one sector per turn. + /// SE4 called this "engines per move" but this was a misnomer because engines were allowed to produce more than one thrust point. + /// + int ThrustPerMove { get; set; } + + /// + /// The vehicle type of this hull. + /// + VehicleTypes VehicleType { get; } + + string VehicleTypeName { get; } + + /// + /// Can this hull use a mount? + /// + /// + /// + bool CanUseMount(Mount m); + + Image GetIcon(string shipsetPath); + + Image GetPortrait(string shipsetPath); +} + +/// +/// A vehicle hull. +/// +public interface IHull : IHull, IUpgradeable> where T : IVehicle +{ + new bool IsObsolescent { get; } + + // to deal with ambiguity between implementing IHull and IHull + new bool IsObsolete { get; } + + new IHull LatestVersion { get; } + new IEnumerable> NewerVersions { get; } + new IEnumerable> OlderVersions { get; } +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Vehicles/IHullFactory.cs b/FrEee.Core.Domain/Vehicles/IHullFactory.cs new file mode 100644 index 00000000..fa264aed --- /dev/null +++ b/FrEee.Core.Domain/Vehicles/IHullFactory.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Vehicles.Types; + +namespace FrEee.Vehicles; + +/// +/// Build vehicle hulls. +/// +public interface IHullFactory +{ + /// + /// Builds a hull of a specific type. + /// + /// The type of hull to build. + /// The built hull. + IHull Build(VehicleTypes vehicleType); +} diff --git a/FrEee.Core.Domain/Vehicles/IVehicle.cs b/FrEee.Core.Domain/Vehicles/IVehicle.cs new file mode 100644 index 00000000..cbf619a0 --- /dev/null +++ b/FrEee.Core.Domain/Vehicles/IVehicle.cs @@ -0,0 +1,49 @@ +using FrEee.Objects.Civilization; +using FrEee.Objects.Civilization.Construction; +using FrEee.Objects.Civilization.Orders; +using FrEee.Objects.Technology; +using FrEee.Serialization; +using FrEee.Utility; +using System.Collections.Generic; +using FrEee.Processes.Combat; +using FrEee.Modding.Abilities; +using FrEee.Objects.GameState; +using FrEee.Vehicles.Types; + +namespace FrEee.Vehicles; + +/// +/// A space or ground vehicle. +/// +public interface IVehicle : IConstructable, IOwnableAbilityObject, IReferrable, IDamageable, ICombatant, IRecyclable, IIncomeProducer, IUpgradeable, INameable, IHasMaintenanceCost +{ + [DoNotSerialize(false)] + new IList Components { get; } + + /// + /// Damage that has been applied to this vehicle's components. + /// + SafeDictionary> Damage { get; set; } + + /// + /// The design of this vehicle. + /// + [DoNotCopy] + IDesign Design { get; set; } + + IHull Hull => Design.Hull; + + VehicleTypes VehicleType => Hull.VehicleType; + + /// + /// Does this vehicle detonate to inflict damage on enemies that enter its sector? + /// (i.e. in stock, is it a mine?) + /// + // TODO: make this an ability on hulls and/or components + bool DetonatesWhenEnemiesEnterSector { get; } + + /// + /// Does this vehicle belong to the current empire? + /// + bool IsOurs { get; } +} diff --git a/FrEee.Core.Domain/Vehicles/IVehicleFactory.cs b/FrEee.Core.Domain/Vehicles/IVehicleFactory.cs new file mode 100644 index 00000000..05612d05 --- /dev/null +++ b/FrEee.Core.Domain/Vehicles/IVehicleFactory.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Vehicles.Types; + +namespace FrEee.Vehicles; + +/// +/// Build vehicles. +/// +public interface IVehicleFactory +{ + /// + /// Builds a vehicle of a specific type. + /// + /// The type of vehicle to build. + /// The built vehicle. + IVehicle Build(VehicleTypes vehicleType); +} diff --git a/FrEee.Core.Domain/Vehicles/Types/IMajorSpaceVehicle.cs b/FrEee.Core.Domain/Vehicles/Types/IMajorSpaceVehicle.cs new file mode 100644 index 00000000..17b34bcb --- /dev/null +++ b/FrEee.Core.Domain/Vehicles/Types/IMajorSpaceVehicle.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using FrEee.Objects.Civilization; +using FrEee.Objects.Civilization.CargoStorage; +using FrEee.Objects.Civilization.Construction; +using FrEee.Objects.Space; +using FrEee.Processes.Combat; + +namespace FrEee.Vehicles.Types; + +/// +/// A space vehicle which can contain cargo and build things. +/// Should not be a unit unless you want Matryosha ships... +/// +public interface IMajorSpaceVehicle + : ISpaceVehicle, ICargoTransferrer, IConstructor +{ +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Vehicles/Types/ISpaceVehicle.cs b/FrEee.Core.Domain/Vehicles/Types/ISpaceVehicle.cs new file mode 100644 index 00000000..2207a8f0 --- /dev/null +++ b/FrEee.Core.Domain/Vehicles/Types/ISpaceVehicle.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using FrEee.Modding.Abilities; +using FrEee.Objects.Civilization; +using FrEee.Objects.Civilization.Orders; +using FrEee.Objects.GameState; +using FrEee.Objects.Space; +using FrEee.Utility; + +namespace FrEee.Vehicles.Types; + +/// +/// A vehicle that can be in space on its own. +/// +public interface ISpaceVehicle + : IVehicle, IMobileSpaceObject +{ + int CargoStorage { get; } + IDictionary, ISet>> DijkstraMap { get; set; } + int EngineSupplyBurnRate { get; } + ResourceQuantity GrossIncome { get; } + long PopulationStorageFree { get; } + Progress SupplyFill { get; } + new IList Orders { get; } + + /// + /// Emergency speed generated by activated emergency propulsion components. Only available for one turn. + /// + int EmergencySpeed { get; set; } +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Vehicles/Types/IUnit.cs b/FrEee.Core.Domain/Vehicles/Types/IUnit.cs new file mode 100644 index 00000000..98ef50fb --- /dev/null +++ b/FrEee.Core.Domain/Vehicles/Types/IUnit.cs @@ -0,0 +1,26 @@ +using FrEee.Objects.Civilization.CargoStorage; +using FrEee.Objects.GameState; + +namespace FrEee.Vehicles.Types; + +/// +/// A vehicle which can be contained in cargo. +/// +public interface IUnit : IVehicle, IContainable +{ + /// + /// Can this unit fire into space from planetary cargo? + /// i.e. in stock is it a weapon platform? + /// + /// + /// Troops could do this in SE3 + /// + // TODO: make this an ability on hulls and/or weapons + bool CanFireIntoSpaceFromPlanetaryCargo { get; } + + /// + /// Can this unit invade enemy colonies and police friendly colonies? + /// + // TODO: make thi an ability on hulls and/or components + bool CanInvadeAndPoliceColonies { get; } +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Vehicles/Types/VehicleTypes.cs b/FrEee.Core.Domain/Vehicles/Types/VehicleTypes.cs new file mode 100644 index 00000000..2abd57c6 --- /dev/null +++ b/FrEee.Core.Domain/Vehicles/Types/VehicleTypes.cs @@ -0,0 +1,52 @@ +using System; +using FrEee.Utility; +namespace FrEee.Vehicles.Types; + +/// +/// Vehicle types. Used for restricting component placement. +/// +// TODO: make this a data file similar to hulls and not an enum +[Flags] +public enum VehicleTypes +{ + None = 0x0, + + [Name("Ships")] + Ship = 0x1, + + [Name("Bases")] + Base = 0x2, + + [Name("Fighters")] + [Name("Ftr")] + Fighter = 0x4, + + [Name("Satellites")] + [Name("Sat")] + Satellite = 0x8, + + [Name("Mines")] + Mine = 0x10, + + [Name("Troops")] + [Name("Troop")] + [Name("Trp")] + Troop = 0x20, + + [Name("Drones")] + Drone = 0x40, + + [Name("WeapPlatform")] + [Name("WeapPlatforms")] + [Name("WeapPlat")] + [Name("WeapPlats")] + [Name("WeaponPlatforms")] + [CanonicalName("Weapon Platform")] + [Name("Weapon Platforms")] + WeaponPlatform = 0x80, + + [Name("Any")] + All = Ship | Base | Fighter | Satellite | Mine | Troop | Drone | WeaponPlatform, + + Invalid = 0x1000, +} \ No newline at end of file diff --git a/FrEee.Gameplay/Commands/Designs/CreateDesignCommand.cs b/FrEee.Gameplay/Commands/Designs/CreateDesignCommand.cs index 04814880..d046b10f 100644 --- a/FrEee.Gameplay/Commands/Designs/CreateDesignCommand.cs +++ b/FrEee.Gameplay/Commands/Designs/CreateDesignCommand.cs @@ -1,12 +1,11 @@ -using FrEee.Objects.Civilization; -using FrEee.Extensions; -using System; +using System; using System.Collections.Generic; using System.Linq; -using FrEee.Objects.Vehicles; +using FrEee.Extensions; +using FrEee.Objects.Civilization; using FrEee.Objects.GameState; using FrEee.Objects.LogMessages; -using FrEee.Gameplay.Commands.Designs; +using FrEee.Vehicles; namespace FrEee.Gameplay.Commands.Designs; @@ -16,29 +15,29 @@ namespace FrEee.Gameplay.Commands.Designs; [Serializable] public class CreateDesignCommand : Command, ICreateDesignCommand where T : IVehicle { - public CreateDesignCommand(IDesign design) - : base(Empire.Current) - { - Design = design; - } + public CreateDesignCommand(IDesign design) + : base(Empire.Current) + { + Design = design; + } - IDesign ICreateDesignCommand.Design { get { return Design; } } + IDesign ICreateDesignCommand.Design { get { return Design; } } - public IDesign Design { get; set; } + public IDesign Design { get; set; } - public override IEnumerable NewReferrables - { - get - { - yield return Design; - } - } + public override IEnumerable NewReferrables + { + get + { + yield return Design; + } + } - public override void Execute() - { - Design.VehiclesBuilt = 0; // in case it was tested in the simulator - if (Design.Warnings.Any()) - Issuer.Log.Add(Design.CreateLogMessage("The " + Design.Name + " " + Design.VehicleTypeName + " design cannot be saved because it has warnings.", LogMessageType.Warning)); - Issuer.KnownDesigns.Add(Design); - } + public override void Execute() + { + Design.VehiclesBuilt = 0; // in case it was tested in the simulator + if (Design.Warnings.Any()) + Issuer.Log.Add(Design.CreateLogMessage("The " + Design.Name + " " + Design.VehicleTypeName + " design cannot be saved because it has warnings.", LogMessageType.Warning)); + Issuer.KnownDesigns.Add(Design); + } } \ No newline at end of file diff --git a/FrEee.Gameplay/Commands/Designs/DesignCommandFactory.cs b/FrEee.Gameplay/Commands/Designs/DesignCommandFactory.cs index 402676c9..563780d5 100644 --- a/FrEee.Gameplay/Commands/Designs/DesignCommandFactory.cs +++ b/FrEee.Gameplay/Commands/Designs/DesignCommandFactory.cs @@ -1,13 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using FrEee.Gameplay.Commands.Notes; -using FrEee.Objects.Civilization; -using FrEee.Objects.Civilization.Orders; -using FrEee.Objects.GameState; -using FrEee.Objects.Vehicles; +using FrEee.Vehicles; namespace FrEee.Gameplay.Commands.Designs; public class DesignCommandFactory diff --git a/FrEee.Gameplay/Commands/Designs/SetObsoleteFlagCommand.cs b/FrEee.Gameplay/Commands/Designs/SetObsoleteFlagCommand.cs index 759b81e2..8fbbe746 100644 --- a/FrEee.Gameplay/Commands/Designs/SetObsoleteFlagCommand.cs +++ b/FrEee.Gameplay/Commands/Designs/SetObsoleteFlagCommand.cs @@ -1,8 +1,8 @@ -using FrEee.Serialization; +using System.Collections.Generic; using FrEee.Extensions; -using System.Collections.Generic; -using FrEee.Objects.Vehicles; using FrEee.Objects.GameState; +using FrEee.Serialization; +using FrEee.Vehicles; namespace FrEee.Gameplay.Commands.Designs; @@ -11,57 +11,57 @@ namespace FrEee.Gameplay.Commands.Designs; /// public class SetObsoleteFlagCommand : Command, ISetObsoleteFlagCommand { - public SetObsoleteFlagCommand(IDesign design, bool isObsolete) - : base(design) - { - if (design.IsNew) - NewDesign = design; - else - Design = design; - IsObsolete = isObsolete; - } + public SetObsoleteFlagCommand(IDesign design, bool isObsolete) + : base(design) + { + if (design.IsNew) + NewDesign = design; + else + Design = design; + IsObsolete = isObsolete; + } - [DoNotSerialize] - public IDesign Design { get { return design?.Value; } set { design = value.ReferViaGalaxy(); } } + [DoNotSerialize] + public IDesign Design { get { return design?.Value; } set { design = value.ReferViaGalaxy(); } } - public bool IsObsolete { get; set; } + public bool IsObsolete { get; set; } - public IDesign NewDesign { get; set; } + public IDesign NewDesign { get; set; } - public override IEnumerable NewReferrables - { - get - { - if (NewDesign != null) - yield return NewDesign; - } - } + public override IEnumerable NewReferrables + { + get + { + if (NewDesign != null) + yield return NewDesign; + } + } - private GameReference design { get; set; } + private GameReference design { get; set; } - public override void Execute() - { - if (NewDesign != null) - { - // allows obsoleting designs that are on the library or newly created (not on the server yet) - Issuer.KnownDesigns.Add(NewDesign); - Design = NewDesign; - } - Design.IsObsolete = IsObsolete; - } + public override void Execute() + { + if (NewDesign != null) + { + // allows obsoleting designs that are on the library or newly created (not on the server yet) + Issuer.KnownDesigns.Add(NewDesign); + Design = NewDesign; + } + Design.IsObsolete = IsObsolete; + } - public override void ReplaceClientIDs(IDictionary idmap, ISet done = null) - { - if (done == null) - done = new HashSet(); - if (!done.Contains(this)) - { - done.Add(this); - base.ReplaceClientIDs(idmap, done); - if (design != null) - design.ReplaceClientIDs(idmap, done); - if (NewDesign != null) - NewDesign.ReplaceClientIDs(idmap, done); - } - } + public override void ReplaceClientIDs(IDictionary idmap, ISet done = null) + { + if (done == null) + done = new HashSet(); + if (!done.Contains(this)) + { + done.Add(this); + base.ReplaceClientIDs(idmap, done); + if (design != null) + design.ReplaceClientIDs(idmap, done); + if (NewDesign != null) + NewDesign.ReplaceClientIDs(idmap, done); + } + } } \ No newline at end of file diff --git a/FrEee.Gameplay/Commands/Fleets/CreateFleetCommand.cs b/FrEee.Gameplay/Commands/Fleets/CreateFleetCommand.cs index a907274e..2eae7ec5 100644 --- a/FrEee.Gameplay/Commands/Fleets/CreateFleetCommand.cs +++ b/FrEee.Gameplay/Commands/Fleets/CreateFleetCommand.cs @@ -1,7 +1,7 @@ -using FrEee.Objects.Civilization; +using System.Collections.Generic; +using FrEee.Objects.Civilization; using FrEee.Objects.GameState; using FrEee.Objects.Space; -using System.Collections.Generic; namespace FrEee.Gameplay.Commands.Fleets; diff --git a/FrEee.Gameplay/Commands/Fleets/DisbandFleetCommand.cs b/FrEee.Gameplay/Commands/Fleets/DisbandFleetCommand.cs index b23f9e8e..bee14aeb 100644 --- a/FrEee.Gameplay/Commands/Fleets/DisbandFleetCommand.cs +++ b/FrEee.Gameplay/Commands/Fleets/DisbandFleetCommand.cs @@ -1,5 +1,5 @@ -using FrEee.Objects.Space; -using System.Linq; +using System.Linq; +using FrEee.Objects.Space; namespace FrEee.Gameplay.Commands.Fleets; diff --git a/FrEee.Gameplay/Commands/Fleets/FleetCommandFactory.cs b/FrEee.Gameplay/Commands/Fleets/FleetCommandFactory.cs index d453a145..9bde6c6b 100644 --- a/FrEee.Gameplay/Commands/Fleets/FleetCommandFactory.cs +++ b/FrEee.Gameplay/Commands/Fleets/FleetCommandFactory.cs @@ -1,15 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using FrEee.Gameplay.Commands.Designs; -using FrEee.Gameplay.Commands.Notes; -using FrEee.Objects.Civilization; -using FrEee.Objects.Civilization.Orders; -using FrEee.Objects.GameState; -using FrEee.Objects.Space; -using FrEee.Objects.Vehicles; +using FrEee.Objects.Space; namespace FrEee.Gameplay.Commands.Fleets; public class FleetCommandFactory diff --git a/FrEee.Gameplay/Commands/Fleets/JoinFleetCommand.cs b/FrEee.Gameplay/Commands/Fleets/JoinFleetCommand.cs index 4045bfa8..d538ae1f 100644 --- a/FrEee.Gameplay/Commands/Fleets/JoinFleetCommand.cs +++ b/FrEee.Gameplay/Commands/Fleets/JoinFleetCommand.cs @@ -1,9 +1,9 @@ -using FrEee.Objects.Space; -using FrEee.Serialization; +using System.Collections.Generic; using FrEee.Extensions; -using System.Collections.Generic; using FrEee.Objects.GameState; using FrEee.Objects.LogMessages; +using FrEee.Objects.Space; +using FrEee.Serialization; namespace FrEee.Gameplay.Commands.Fleets; diff --git a/FrEee.Gameplay/Commands/Messages/DeleteMessageCommand.cs b/FrEee.Gameplay/Commands/Messages/DeleteMessageCommand.cs index d68c2da6..8bf5abcf 100644 --- a/FrEee.Gameplay/Commands/Messages/DeleteMessageCommand.cs +++ b/FrEee.Gameplay/Commands/Messages/DeleteMessageCommand.cs @@ -1,5 +1,5 @@ -using FrEee.Objects.Civilization; -using FrEee.Extensions; +using FrEee.Extensions; +using FrEee.Objects.Civilization; using FrEee.Objects.Civilization.Diplomacy.Messages; using FrEee.Objects.GameState; diff --git a/FrEee.Gameplay/Commands/Messages/MessageCommandFactory.cs b/FrEee.Gameplay/Commands/Messages/MessageCommandFactory.cs index 87c8b6e2..0a1d153d 100644 --- a/FrEee.Gameplay/Commands/Messages/MessageCommandFactory.cs +++ b/FrEee.Gameplay/Commands/Messages/MessageCommandFactory.cs @@ -1,16 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using FrEee.Gameplay.Commands.Designs; -using FrEee.Gameplay.Commands.Notes; -using FrEee.Objects.Civilization; -using FrEee.Objects.Civilization.Diplomacy.Messages; -using FrEee.Objects.Civilization.Orders; -using FrEee.Objects.GameState; -using FrEee.Objects.Space; -using FrEee.Objects.Vehicles; +using FrEee.Objects.Civilization.Diplomacy.Messages; namespace FrEee.Gameplay.Commands.Messages; public class MessageCommandFactory @@ -24,5 +12,5 @@ public ISendMessageCommand SendMessage(IMessage message) public IDeleteMessageCommand DeleteMessage(IMessage message) { return new DeleteMessageCommand(message); - } + } } diff --git a/FrEee.Gameplay/Commands/Messages/SendMessageCommand.cs b/FrEee.Gameplay/Commands/Messages/SendMessageCommand.cs index f90eccd3..6e181357 100644 --- a/FrEee.Gameplay/Commands/Messages/SendMessageCommand.cs +++ b/FrEee.Gameplay/Commands/Messages/SendMessageCommand.cs @@ -1,6 +1,6 @@ -using FrEee.Objects.Civilization; +using System.Collections.Generic; using FrEee.Extensions; -using System.Collections.Generic; +using FrEee.Objects.Civilization; using FrEee.Objects.Civilization.Diplomacy.Messages; using FrEee.Objects.GameState; using FrEee.Objects.LogMessages; diff --git a/FrEee.Gameplay/Commands/Ministers/MinisterCommandFactory.cs b/FrEee.Gameplay/Commands/Ministers/MinisterCommandFactory.cs index ac0de59d..93a5738b 100644 --- a/FrEee.Gameplay/Commands/Ministers/MinisterCommandFactory.cs +++ b/FrEee.Gameplay/Commands/Ministers/MinisterCommandFactory.cs @@ -1,19 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using FrEee.Gameplay.Commands.Designs; -using FrEee.Gameplay.Commands.Ministers; -using FrEee.Gameplay.Commands.Notes; -using FrEee.Objects.Civilization; -using FrEee.Objects.Civilization.Diplomacy.Messages; -using FrEee.Objects.Civilization.Orders; -using FrEee.Objects.GameState; -using FrEee.Objects.Space; -using FrEee.Objects.Vehicles; - -namespace FrEee.Gameplay.Commands.Ministers; +namespace FrEee.Gameplay.Commands.Ministers; public class MinisterCommandFactory : IMinisterCommandFactory { diff --git a/FrEee.Gameplay/Commands/Ministers/ToggleMinistersCommand.cs b/FrEee.Gameplay/Commands/Ministers/ToggleMinistersCommand.cs index 10d060d5..3409aaf4 100644 --- a/FrEee.Gameplay/Commands/Ministers/ToggleMinistersCommand.cs +++ b/FrEee.Gameplay/Commands/Ministers/ToggleMinistersCommand.cs @@ -1,10 +1,7 @@ -using FrEee.Gameplay.Commands.Messages; +using System.Collections.Generic; using FrEee.Objects.Civilization; -using FrEee.Objects.GameState; using FrEee.Objects.LogMessages; -using FrEee.Serialization; using FrEee.Utility; -using System.Collections.Generic; namespace FrEee.Gameplay.Commands.Ministers; @@ -12,20 +9,20 @@ namespace FrEee.Gameplay.Commands.Ministers; /// Toggles AI ministers. /// public class ToggleMinistersCommand - : Command, IToggleMinistersCommand + : Command, IToggleMinistersCommand { - public ToggleMinistersCommand() - : base(Empire.Current) - { - } + public ToggleMinistersCommand() + : base(Empire.Current) + { + } - public SafeDictionary> EnabledMinisters { get; set; } + public SafeDictionary> EnabledMinisters { get; set; } - public override void Execute() - { - if (Executor.AI == null) - Executor.RecordLog(Executor, $"Could not toggle AI ministers for {Executor} because there is no AI for this empire.", LogMessageType.Error); - else - Executor.EnabledMinisters = EnabledMinisters; - } + public override void Execute() + { + if (Executor.AI == null) + Executor.RecordLog(Executor, $"Could not toggle AI ministers for {Executor} because there is no AI for this empire.", LogMessageType.Error); + else + Executor.EnabledMinisters = EnabledMinisters; + } } diff --git a/FrEee.Gameplay/Commands/Notes/ClearPlayerNoteCommand.cs b/FrEee.Gameplay/Commands/Notes/ClearPlayerNoteCommand.cs index 2c48294c..da91c8f8 100644 --- a/FrEee.Gameplay/Commands/Notes/ClearPlayerNoteCommand.cs +++ b/FrEee.Gameplay/Commands/Notes/ClearPlayerNoteCommand.cs @@ -1,7 +1,7 @@ -using FrEee.Objects.Civilization; -using FrEee.Serialization; -using FrEee.Extensions; +using FrEee.Extensions; +using FrEee.Objects.Civilization; using FrEee.Objects.GameState; +using FrEee.Serialization; namespace FrEee.Gameplay.Commands.Notes; diff --git a/FrEee.Gameplay/Commands/Notes/ClearPrivateNameCommand.cs b/FrEee.Gameplay/Commands/Notes/ClearPrivateNameCommand.cs index b17abea5..d69648ce 100644 --- a/FrEee.Gameplay/Commands/Notes/ClearPrivateNameCommand.cs +++ b/FrEee.Gameplay/Commands/Notes/ClearPrivateNameCommand.cs @@ -1,7 +1,7 @@ -using FrEee.Objects.Civilization; -using FrEee.Serialization; -using FrEee.Extensions; +using FrEee.Extensions; +using FrEee.Objects.Civilization; using FrEee.Objects.GameState; +using FrEee.Serialization; namespace FrEee.Gameplay.Commands.Notes; diff --git a/FrEee.Gameplay/Commands/Notes/NoteCommandFactory.cs b/FrEee.Gameplay/Commands/Notes/NoteCommandFactory.cs index 1d092774..002b7537 100644 --- a/FrEee.Gameplay/Commands/Notes/NoteCommandFactory.cs +++ b/FrEee.Gameplay/Commands/Notes/NoteCommandFactory.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using FrEee.Objects.Civilization; -using FrEee.Objects.Civilization.Orders; +using FrEee.Objects.Civilization; using FrEee.Objects.GameState; namespace FrEee.Gameplay.Commands.Notes; diff --git a/FrEee.Gameplay/Commands/Notes/SetPlayerInfoCommand.cs b/FrEee.Gameplay/Commands/Notes/SetPlayerInfoCommand.cs index d27e78ef..221bb85e 100644 --- a/FrEee.Gameplay/Commands/Notes/SetPlayerInfoCommand.cs +++ b/FrEee.Gameplay/Commands/Notes/SetPlayerInfoCommand.cs @@ -1,7 +1,7 @@ -using FrEee.Objects.Civilization; -using FrEee.Objects.GameState; -using System; +using System; using System.Collections.Generic; +using FrEee.Objects.Civilization; +using FrEee.Objects.GameState; namespace FrEee.Gameplay.Commands.Notes; diff --git a/FrEee.Gameplay/Commands/Notes/SetPlayerNoteCommand.cs b/FrEee.Gameplay/Commands/Notes/SetPlayerNoteCommand.cs index bb8d66ee..d83b07dc 100644 --- a/FrEee.Gameplay/Commands/Notes/SetPlayerNoteCommand.cs +++ b/FrEee.Gameplay/Commands/Notes/SetPlayerNoteCommand.cs @@ -1,7 +1,7 @@ -using FrEee.Objects.Civilization; -using FrEee.Serialization; -using FrEee.Extensions; +using FrEee.Extensions; +using FrEee.Objects.Civilization; using FrEee.Objects.GameState; +using FrEee.Serialization; namespace FrEee.Gameplay.Commands.Notes; diff --git a/FrEee.Gameplay/Commands/Notes/SetPrivateNameCommand.cs b/FrEee.Gameplay/Commands/Notes/SetPrivateNameCommand.cs index 4d739dd2..3cad8146 100644 --- a/FrEee.Gameplay/Commands/Notes/SetPrivateNameCommand.cs +++ b/FrEee.Gameplay/Commands/Notes/SetPrivateNameCommand.cs @@ -1,7 +1,7 @@ -using FrEee.Objects.Civilization; -using FrEee.Serialization; -using FrEee.Extensions; +using FrEee.Extensions; +using FrEee.Objects.Civilization; using FrEee.Objects.GameState; +using FrEee.Serialization; namespace FrEee.Gameplay.Commands.Notes; diff --git a/FrEee.Gameplay/Commands/Orders/AddOrderCommand.cs b/FrEee.Gameplay/Commands/Orders/AddOrderCommand.cs index 0f5f4b3e..5b00508d 100644 --- a/FrEee.Gameplay/Commands/Orders/AddOrderCommand.cs +++ b/FrEee.Gameplay/Commands/Orders/AddOrderCommand.cs @@ -1,10 +1,10 @@ -using FrEee.Objects.Civilization; +using System; +using System.Collections.Generic; +using FrEee.Objects.Civilization; using FrEee.Objects.Civilization.Construction; using FrEee.Objects.Civilization.Orders; using FrEee.Objects.GameState; using FrEee.Objects.LogMessages; -using System; -using System.Collections.Generic; namespace FrEee.Gameplay.Commands.Orders; diff --git a/FrEee.Gameplay/Commands/Orders/OrderCommand.cs b/FrEee.Gameplay/Commands/Orders/OrderCommand.cs index 00d63cd8..6fa8e107 100644 --- a/FrEee.Gameplay/Commands/Orders/OrderCommand.cs +++ b/FrEee.Gameplay/Commands/Orders/OrderCommand.cs @@ -1,10 +1,10 @@ -using FrEee.Serialization; -using FrEee.Extensions; -using System; +using System; using System.Collections.Generic; -using FrEee.Objects.Civilization.Orders; +using FrEee.Extensions; using FrEee.Objects.Civilization; +using FrEee.Objects.Civilization.Orders; using FrEee.Objects.GameState; +using FrEee.Serialization; namespace FrEee.Gameplay.Commands.Orders; diff --git a/FrEee.Gameplay/Commands/Orders/OrderCommandFactory.cs b/FrEee.Gameplay/Commands/Orders/OrderCommandFactory.cs index 12906fad..05f800e2 100644 --- a/FrEee.Gameplay/Commands/Orders/OrderCommandFactory.cs +++ b/FrEee.Gameplay/Commands/Orders/OrderCommandFactory.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using FrEee.Objects.Civilization; +using FrEee.Objects.Civilization; using FrEee.Objects.Civilization.Orders; namespace FrEee.Gameplay.Commands.Orders; diff --git a/FrEee.Gameplay/Commands/Orders/RearrangeOrdersCommand.cs b/FrEee.Gameplay/Commands/Orders/RearrangeOrdersCommand.cs index 9a8268c7..97828cb0 100644 --- a/FrEee.Gameplay/Commands/Orders/RearrangeOrdersCommand.cs +++ b/FrEee.Gameplay/Commands/Orders/RearrangeOrdersCommand.cs @@ -1,8 +1,8 @@ -using FrEee.Objects.Civilization; +using System; +using FrEee.Objects.Civilization; using FrEee.Objects.Civilization.Orders; using FrEee.Objects.GameState; using FrEee.Objects.LogMessages; -using System; namespace FrEee.Gameplay.Commands.Orders; diff --git a/FrEee.Gameplay/Commands/Orders/RemoveOrderCommand.cs b/FrEee.Gameplay/Commands/Orders/RemoveOrderCommand.cs index 53295435..2cadca69 100644 --- a/FrEee.Gameplay/Commands/Orders/RemoveOrderCommand.cs +++ b/FrEee.Gameplay/Commands/Orders/RemoveOrderCommand.cs @@ -1,9 +1,9 @@ -using FrEee.Objects.LogMessages; +using System; using FrEee.Extensions; -using System; -using FrEee.Objects.Civilization.Orders; using FrEee.Objects.Civilization; +using FrEee.Objects.Civilization.Orders; using FrEee.Objects.GameState; +using FrEee.Objects.LogMessages; namespace FrEee.Gameplay.Commands.Orders; diff --git a/FrEee.Gameplay/Commands/Projects/ProjectCommandFactory.cs b/FrEee.Gameplay/Commands/Projects/ProjectCommandFactory.cs index 63a56edb..e317ab40 100644 --- a/FrEee.Gameplay/Commands/Projects/ProjectCommandFactory.cs +++ b/FrEee.Gameplay/Commands/Projects/ProjectCommandFactory.cs @@ -1,15 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using FrEee.Gameplay.Commands.Notes; -using FrEee.Objects.Civilization; -using FrEee.Objects.Civilization.Orders; -using FrEee.Objects.GameState; -using FrEee.Objects.Vehicles; - -namespace FrEee.Gameplay.Commands.Projects; +namespace FrEee.Gameplay.Commands.Projects; public class ProjectCommandFactory : IProjectCommandFactory diff --git a/FrEee.Gameplay/Commands/Projects/ResearchCommand.cs b/FrEee.Gameplay/Commands/Projects/ResearchCommand.cs index 1dc91794..5b353d3c 100644 --- a/FrEee.Gameplay/Commands/Projects/ResearchCommand.cs +++ b/FrEee.Gameplay/Commands/Projects/ResearchCommand.cs @@ -1,8 +1,8 @@ -using FrEee.Objects.Civilization; +using System.Linq; using FrEee.Extensions; -using System.Linq; -using Tech = FrEee.Objects.Technology.Technology; using FrEee.Modding; +using FrEee.Objects.Civilization; +using Tech = FrEee.Objects.Technology.Technology; namespace FrEee.Gameplay.Commands.Projects; @@ -10,46 +10,46 @@ namespace FrEee.Gameplay.Commands.Projects; /// Command to set an empire's research priorities. /// public class ResearchCommand - : Command, IResearchCommand + : Command, IResearchCommand { - public ResearchCommand() - : base(Empire.Current) - { - } + public ResearchCommand() + : base(Empire.Current) + { + } - public ModReferenceList Queue { get; private set; } = new(); - public ModReferenceKeyedDictionary Spending { get; private set; } = new(); + public ModReferenceList Queue { get; private set; } = new(); + public ModReferenceKeyedDictionary Spending { get; private set; } = new(); - public override void Execute() - { - // make sure spending is not over 100% - var totalSpending = Spending.Sum(kvp => kvp.Value); - if (totalSpending > 100) - { - foreach (var kvp in Spending.ToArray()) - { - Spending[kvp.Key] = kvp.Value / totalSpending / 100; - } - } + public override void Execute() + { + // make sure spending is not over 100% + var totalSpending = Spending.Sum(kvp => kvp.Value); + if (totalSpending > 100) + { + foreach (var kvp in Spending.ToArray()) + { + Spending[kvp.Key] = kvp.Value / totalSpending / 100; + } + } - // make sure no techs are prioritized or queued that the empire can't research - foreach (var kvp in Spending.ToArray()) - { - if (!Executor.HasUnlocked(kvp.Key)) - Spending[kvp.Key] = 0; - } - foreach (Tech tech in Queue.ToArray()) - { - if (!Executor.HasUnlocked(tech)) - Queue.Remove(tech); - } + // make sure no techs are prioritized or queued that the empire can't research + foreach (var kvp in Spending.ToArray()) + { + if (!Executor.HasUnlocked(kvp.Key)) + Spending[kvp.Key] = 0; + } + foreach (Tech tech in Queue.ToArray()) + { + if (!Executor.HasUnlocked(tech)) + Queue.Remove(tech); + } - // save to empire - Executor.ResearchSpending.Clear(); - foreach (var kvp in Spending) - Executor.ResearchSpending.Add(kvp); - Executor.ResearchQueue.Clear(); - foreach (var tech in Queue) - Executor.ResearchQueue.Add(tech); - } + // save to empire + Executor.ResearchSpending.Clear(); + foreach (var kvp in Spending) + Executor.ResearchSpending.Add(kvp); + Executor.ResearchQueue.Clear(); + foreach (var tech in Queue) + Executor.ResearchQueue.Add(tech); + } } \ No newline at end of file diff --git a/FrEee.Gameplay/Commands/Waypoints/CreateWaypointCommand.cs b/FrEee.Gameplay/Commands/Waypoints/CreateWaypointCommand.cs index e60c0d40..5e4a5256 100644 --- a/FrEee.Gameplay/Commands/Waypoints/CreateWaypointCommand.cs +++ b/FrEee.Gameplay/Commands/Waypoints/CreateWaypointCommand.cs @@ -1,6 +1,6 @@ -using FrEee.Objects.Civilization; +using System.Collections.Generic; +using FrEee.Objects.Civilization; using FrEee.Objects.GameState; -using System.Collections.Generic; namespace FrEee.Gameplay.Commands.Waypoints; diff --git a/FrEee.Gameplay/Commands/Waypoints/DeleteWaypointCommand.cs b/FrEee.Gameplay/Commands/Waypoints/DeleteWaypointCommand.cs index 8ad168e0..c100a5ee 100644 --- a/FrEee.Gameplay/Commands/Waypoints/DeleteWaypointCommand.cs +++ b/FrEee.Gameplay/Commands/Waypoints/DeleteWaypointCommand.cs @@ -1,5 +1,5 @@ -using FrEee.Objects.Civilization; -using FrEee.Extensions; +using FrEee.Extensions; +using FrEee.Objects.Civilization; using FrEee.Objects.LogMessages; namespace FrEee.Gameplay.Commands.Waypoints; diff --git a/FrEee.Gameplay/Commands/Waypoints/HotkeyWaypointCommand.cs b/FrEee.Gameplay/Commands/Waypoints/HotkeyWaypointCommand.cs index 791c1b95..958f8008 100644 --- a/FrEee.Gameplay/Commands/Waypoints/HotkeyWaypointCommand.cs +++ b/FrEee.Gameplay/Commands/Waypoints/HotkeyWaypointCommand.cs @@ -1,11 +1,10 @@  -using FrEee.Objects.Civilization; -using FrEee.Objects.Space; -using FrEee.Extensions; using System; +using FrEee.Extensions; +using FrEee.Objects.Civilization; using FrEee.Objects.Civilization.Orders; -using FrEee.Objects.GameState; using FrEee.Objects.LogMessages; +using FrEee.Objects.Space; namespace FrEee.Gameplay.Commands.Waypoints; diff --git a/FrEee.Gameplay/Commands/Waypoints/WaypointCommandFactory.cs b/FrEee.Gameplay/Commands/Waypoints/WaypointCommandFactory.cs index f18ed1d5..80f78617 100644 --- a/FrEee.Gameplay/Commands/Waypoints/WaypointCommandFactory.cs +++ b/FrEee.Gameplay/Commands/Waypoints/WaypointCommandFactory.cs @@ -1,15 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using FrEee.Gameplay.Commands.Designs; -using FrEee.Gameplay.Commands.Notes; -using FrEee.Objects.Civilization; -using FrEee.Objects.Civilization.Orders; -using FrEee.Objects.GameState; -using FrEee.Objects.Space; -using FrEee.Objects.Vehicles; +using FrEee.Objects.Civilization; namespace FrEee.Gameplay.Commands.Waypoints; public class WaypointCommandFactory diff --git a/FrEee.Processes/Combat/Grid/Battle.cs b/FrEee.Processes/Combat/Grid/Battle.cs index 586d8a87..9930f3b0 100644 --- a/FrEee.Processes/Combat/Grid/Battle.cs +++ b/FrEee.Processes/Combat/Grid/Battle.cs @@ -2,7 +2,6 @@ using FrEee.Objects.LogMessages; using FrEee.Objects.Space; using FrEee.Objects.Technology; -using FrEee.Objects.Vehicles; using FrEee.Modding; using FrEee.Utility; using FrEee.Serialization; @@ -16,6 +15,8 @@ using FrEee.Objects.GameState; using FrEee.Modding.Abilities; using FrEee.Processes.Combat.Events; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; namespace FrEee.Processes.Combat.Grid; @@ -266,7 +267,7 @@ int GetCombatSpeedThisRound(ICombatant c) var targetiness = new SafeDictionary(); foreach (var target in alives.Where(x => c.IsHostileTo(x.Owner) && - (c.CanTarget(x) || x is Planet && c is ICargoContainer cc && cc.Cargo.Units.OfType().Any()))) + (c.CanTarget(x) || x is Planet && c is ICargoContainer cc && cc.Cargo.Units.Where(q => q.CanInvadeAndPoliceColonies).Any()))) { targetiness[target] = 1d / (locations[target] - locations[c]).LengthEightWay; } @@ -395,14 +396,14 @@ int GetCombatSpeedThisRound(ICombatant c) foreach (var c in turnorder) { // find launchable units - var unitsToLaunch = new List<(ICombatant Launcher, SpaceVehicle Launchee)>(); + var unitsToLaunch = new List<(ICombatant Launcher, ISpaceVehicle Launchee)>(); if (c is Planet) { // planets can launch infinite units per turn var p = (Planet)c; if (p.Cargo != null && p.Cargo.Units != null) { - foreach (var u in p.Cargo.Units.OfType()) + foreach (var u in p.Cargo.Units.OfType()) unitsToLaunch.Add((p, u)); } } @@ -413,7 +414,7 @@ int GetCombatSpeedThisRound(ICombatant c) foreach (var vt in Enum.GetValues(typeof(VehicleTypes)).Cast().Distinct()) { var rate = ct.GetAbilityValue("Launch/Recover " + vt.ToSpacedString() + "s").ToInt(); - foreach (var u in ct.Cargo.Units.Where(u => u.Design.VehicleType == vt).OfType().Take(rate)) + foreach (var u in ct.Cargo.Units.Where(u => u.Design.VehicleType == vt).OfType().Take(rate)) unitsToLaunch.Add((c, u)); } } @@ -491,7 +492,7 @@ int GetCombatSpeedThisRound(ICombatant c) // phase 8: drop troops foreach (var c in turnorder.Reverse()) { - if (c is ICargoTransferrer cc && cc.AllUnits.OfType().Any()) + if (c is ICargoTransferrer cc && cc.AllUnits.Where(q => q.CanInvadeAndPoliceColonies).Any()) { // find enemy planets in the same square var dropTargets = locations.Where(q => q.Key != c && q.Value == locations[c] && q.Key is Planet p && c.IsHostileTo(p.Owner)).Select(q => q.Key).Cast(); diff --git a/FrEee.Processes/Combat/Grid/GroundBattle.cs b/FrEee.Processes/Combat/Grid/GroundBattle.cs index fa975b88..5e5d1d3a 100644 --- a/FrEee.Processes/Combat/Grid/GroundBattle.cs +++ b/FrEee.Processes/Combat/Grid/GroundBattle.cs @@ -1,6 +1,5 @@ using FrEee.Objects.Civilization; using FrEee.Objects.Space; -using FrEee.Objects.Vehicles; using FrEee.Modding; using FrEee.Utility; using FrEee.Extensions; @@ -8,6 +7,7 @@ using System.Collections.Generic; using System.Linq; using FrEee.Objects.GameState; +using FrEee.Vehicles; namespace FrEee.Processes.Combat.Grid; @@ -25,11 +25,11 @@ public GroundBattle(Planet location) Sector = location.Sector ?? throw new Exception("Ground battles require a sector location."); // TODO - should weapon platforms participate in ground combat like in SE5? - Empires = Planet.Cargo.Units.OfType().Select(t => t.Owner).Distinct(); - var combatants = new HashSet(Planet.Cargo.Units.OfType()); + Empires = Planet.Cargo.Units.Where(q => q.CanInvadeAndPoliceColonies).Select(t => t.Owner).Distinct(); + var combatants = new HashSet(Planet.Cargo.Units.Where(q => q.CanInvadeAndPoliceColonies)); for (var i = 0; i < Planet.PopulationFill.Value / Mod.Current.Settings.PopulationFactor / (Mod.Current.Settings.PopulationPerMilitia == 0 ? 20 : Mod.Current.Settings.PopulationPerMilitia); i++) { - var militia = Design.MilitiaDesign.Instantiate(); + var militia = DIRoot.Designs.Militia.Instantiate(); militia.Owner = Planet.Owner; combatants.Add(militia); } @@ -47,7 +47,8 @@ public override void Initialize(IEnumerable combatants) { base.Initialize(combatants); - Empires = Planet.Cargo.Units.OfType().Select(t => t.Owner).Distinct(); + // TODO: should weapon platforms take part in ground combat like in SE5? + Empires = Planet.Cargo.Units.Where(q => q.CanInvadeAndPoliceColonies).Select(t => t.Owner).Distinct(); int moduloID = (int)(Planet.ID % 100000); Dice = new PRNG((int)(moduloID / Game.Current.Timestamp * 10)); diff --git a/FrEee.Processes/TurnProcessor.cs b/FrEee.Processes/TurnProcessor.cs index f767688f..05a2fdb6 100644 --- a/FrEee.Processes/TurnProcessor.cs +++ b/FrEee.Processes/TurnProcessor.cs @@ -6,7 +6,6 @@ using FrEee.Processes.Combat.Grid; using FrEee.Objects.LogMessages; using FrEee.Objects.Space; -using FrEee.Objects.Vehicles; using FrEee.Objects.VictoryConditions; using FrEee.Modding; using FrEee.Extensions; @@ -20,6 +19,8 @@ using FrEee.Modding.Scripts; using System.Threading.Tasks; using FrEee.Gameplay.Commands; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; namespace FrEee.Processes; @@ -215,9 +216,8 @@ public IEnumerable ProcessTurn(Game game, bool safeMode, Status status = // unlike most other operations, miners that are out of supplies still function // because having to resupply miners would be a pain :P var miner = kvp.Key.Item1; - if (miner is SpaceVehicle) + if (miner is ISpaceVehicle sv) { - var sv = miner as SpaceVehicle; var miningComps = sv.Components.Where(c => c.Abilities().Any(a => a.Rule.StartsWith("Remote Resource Generation - "))); var burn = miningComps.Sum(c => c.Template.SupplyUsage); sv.SupplyRemaining -= burn; @@ -260,8 +260,10 @@ public IEnumerable ProcessTurn(Game game, bool safeMode, Status status = // pay maintenance on on ships/bases // TODO - allow mod to specify maintenance on units/facilities too? - foreach (var v in emp.OwnedSpaceObjects.OfType().Where(x => !x.IsMemory)) - emp.StoredResources -= v.MaintenanceCost; + foreach (var v in emp.OwnedSpaceObjects.OfType().Where(x => !x.IsMemory)) + { + emp.StoredResources -= ((IVehicle)v).MaintenanceCost; + } // if not enough funds, lose ships/bases (weighted by maintenance cost) // TODO - if mods allow ground-unit/facility maintenance, lose those too? @@ -271,7 +273,7 @@ public IEnumerable ProcessTurn(Game game, bool safeMode, Status status = var lostShips = deficit / Mod.Current.Settings.MaintenanceDeficitToDestroyOneShip; for (int i = 0; i < lostShips; i++) { - var ship = emp.OwnedSpaceObjects.OfType().PickWeighted(x => x.MaintenanceCost.Sum(y => y.Value)); + var ship = emp.OwnedSpaceObjects.OfType().PickWeighted(x => ((IVehicle)x).MaintenanceCost.Sum(y => y.Value)); if (ship != null) { emp.Log.Add(ship.CreateLogMessage(ship + " fell into disrepair and was scuttled due to lack of funding for maintenance.", LogMessageType.Warning)); @@ -487,7 +489,7 @@ public IEnumerable ProcessTurn(Game game, bool safeMode, Status status = game.Galaxy.FindSpaceObjects().SafeForeach(o => o.ReplenishShields()); // modify colony anger - foreach (var ship in game.Galaxy.FindSpaceObjects().Where(x => !x.IsDestroyed)) + foreach (var ship in game.Galaxy.FindSpaceObjects().Where(x => !x.IsDestroyed)) { foreach (var emp in game.Empires.Where(e => e.CanSee(ship))) { @@ -507,7 +509,7 @@ public IEnumerable ProcessTurn(Game game, bool safeMode, Status status = { if (c.Cargo.Units.Any(u => u.IsHostileTo(c.Owner))) c.TriggerHappinessChange(hm => hm.EnemyTroopsOnPlanet); - c.TriggerHappinessChange(hm => hm.OurTroopOnPlanet * c.Cargo.Units.OfType().Count()); + c.TriggerHappinessChange(hm => hm.OurTroopOnPlanet * c.Cargo.Units.Where(q => q.CanInvadeAndPoliceColonies).Count()); }); game.Galaxy.FindSpaceObjects().Where(p => p.Colony != null).Select(p => p.Colony).ParallelSafeForeach(c => { @@ -555,7 +557,7 @@ public IEnumerable ProcessTurn(Game game, bool safeMode, Status status = { // component repair is per sector per turn per empire, so we need to track it that way var usedPts = new SafeDictionary(); - foreach (var v in game.Galaxy.FindSpaceObjects().Where(v => v.Owner == emp && v.Sector != null && (v is Ship || v is Base || v is Fleet))) + foreach (var v in game.Galaxy.FindSpaceObjects().Where(v => v.Owner == emp && v.Sector != null && (v is IMajorSpaceVehicle || v is Fleet))) { var pts = v.Sector.GetEmpireAbilityValue(emp, "Component Repair").ToInt() - usedPts[v.Sector]; usedPts[v.Sector] += pts - v.Repair(pts).Value; diff --git a/FrEee.Root/Configuration.cs b/FrEee.Root/Configuration.cs index 51dfc4c8..7db143e9 100644 --- a/FrEee.Root/Configuration.cs +++ b/FrEee.Root/Configuration.cs @@ -15,6 +15,7 @@ using FrEee.Processes.Combat; using FrEee.Processes.Combat.Grid; using FrEee.Utility; +using FrEee.Vehicles; namespace FrEee.Root; @@ -42,6 +43,11 @@ public static void ConfigureDI() DI.RegisterSingleton(); DI.RegisterSingleton(); + // vehicles + DI.RegisterSingleton(); + DI.RegisterSingleton(); + DI.RegisterSingleton(); + // run this in the background, without awaiting it DI.Run(); } diff --git a/FrEee.Root/FrEee.Root.csproj b/FrEee.Root/FrEee.Root.csproj index fbc34a02..915cc97c 100644 --- a/FrEee.Root/FrEee.Root.csproj +++ b/FrEee.Root/FrEee.Root.csproj @@ -19,6 +19,9 @@ all + + all + diff --git a/FrEee.Tests/Modding/FormulaTest.cs b/FrEee.Tests/Modding/FormulaTest.cs index 281deaf4..91124f68 100644 --- a/FrEee.Tests/Modding/FormulaTest.cs +++ b/FrEee.Tests/Modding/FormulaTest.cs @@ -1,13 +1,15 @@ using FrEee.Objects.Civilization; using FrEee.Processes.Combat; using FrEee.Objects.Technology; -using FrEee.Objects.Vehicles; using FrEee.Modding.Templates; using NUnit.Framework; using System.Collections.Generic; using System.Linq; using FrEee.Objects.GameState; using FrEee.Modding.Loaders; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; +using FrEee.Utility; namespace FrEee.Modding; @@ -35,15 +37,14 @@ public void DynamicFormula() mount.DurabilityPercent = 200; mount.SizePercent = new ComputedFormula("design.Hull.Size", mount, true); Mod.Current.Mounts.Add(mount); - var hull = new Hull(); + var hull = DIRoot.Hulls.Build(VehicleTypes.Ship); hull.ModID = hull.Name = "Generic Hull"; hull.Size = 150; Mod.Current.Hulls.Add(hull); - var design = new Design(); + var design = DIRoot.Designs.Build(hull); Game.Current.AssignID(design); var mct = new MountedComponentTemplate(design, armor, mount); - design.Hull = hull; design.Components.Add(mct); mct.Container = design; design.Owner = emp; diff --git a/FrEee.Tests/Objects/Abilities/AbilityTest.cs b/FrEee.Tests/Objects/Abilities/AbilityTest.cs index 488810dc..6485aa46 100644 --- a/FrEee.Tests/Objects/Abilities/AbilityTest.cs +++ b/FrEee.Tests/Objects/Abilities/AbilityTest.cs @@ -5,8 +5,8 @@ using FrEee.Objects.Civilization; using FrEee.Objects.GameState; using FrEee.Objects.Space; -using FrEee.Objects.Technology; -using FrEee.Objects.Vehicles; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; using NUnit.Framework; namespace FrEee.Objects.Abilities; @@ -18,9 +18,9 @@ public class AbilityTest { StarSystem sys; Empire emp; - IDesign design; - IHull hull; - Ship ship; + IDesign design; + IHull hull; + IVehicle ship; [SetUp] public void SetUp() @@ -34,8 +34,8 @@ public void SetUp() // create stuff emp = TestUtilities.CreateEmpire(); - design = TestUtilities.CreateDesign(emp); - hull = TestUtilities.CreateHull(design); + hull = TestUtilities.CreateHull(VehicleTypes.Ship, design.Name); + design = TestUtilities.CreateDesign(emp, hull); ship = TestUtilities.CreateVehicle(design, emp); } diff --git a/FrEee.Tests/Objects/Space/MemoryTest.cs b/FrEee.Tests/Objects/Space/MemoryTest.cs index 778c0ae6..74644bcd 100644 --- a/FrEee.Tests/Objects/Space/MemoryTest.cs +++ b/FrEee.Tests/Objects/Space/MemoryTest.cs @@ -3,7 +3,8 @@ using FrEee.Modding; using FrEee.Objects.Civilization; using FrEee.Objects.GameState; -using FrEee.Objects.Vehicles; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; using NUnit.Framework; namespace FrEee.Objects.Space; @@ -16,7 +17,7 @@ public class MemoryTest /// /// The ship that is looking for an enemy ship. /// - private Ship destroyer; + private IMajorSpaceVehicle destroyer; /// /// Where the ships are. @@ -36,7 +37,7 @@ public class MemoryTest /// /// The ship that is hiding. /// - private Ship submarine; + private IMajorSpaceVehicle submarine; /// /// Where the submarine is going. @@ -48,7 +49,7 @@ public void CreatingMemory() { // make sure a memory is created when the vehicle is seen submarine.UpdateEmpireMemories(); - var mem = (Ship)seekers.Memory[submarine.ID]; + var mem = (IMajorSpaceVehicle)seekers.Memory[submarine.ID]; Assert.AreEqual(Visibility.Visible, submarine.CheckVisibility(seekers), "Ship is not visible to empire in same star system."); Assert.IsNotNull(mem, "Memory was not created for visible ship."); Assert.IsNotNull(mem.StarSystem, "Memory was not placed in a star system for visible ship."); @@ -110,17 +111,17 @@ public void Setup() // initialize ships Assert.IsNotNull(Mod.Current); - var dsDesign = new Design(); + var dsHull = TestUtilities.CreateHull(VehicleTypes.Ship, "Destroyer"); + var dsDesign = TestUtilities.CreateDesign(seekers, dsHull, "Destroyer"); dsDesign.BaseName = "Destroyer"; - dsDesign.CreateHull(); dsDesign.Owner = seekers; - destroyer = dsDesign.Instantiate(); + destroyer = (IMajorSpaceVehicle)dsDesign.Instantiate(); destroyer.Owner = seekers; - var subDesign = new Design(); + var subHull = TestUtilities.CreateHull(VehicleTypes.Ship, "Submarine"); + var subDesign = TestUtilities.CreateDesign(seekers, dsHull, "Submarine"); subDesign.BaseName = "Submarine"; - subDesign.CreateHull(); subDesign.Owner = hiders; - submarine = subDesign.Instantiate(); + submarine = (IMajorSpaceVehicle)subDesign.Instantiate(); submarine.Owner = hiders; // place ships diff --git a/FrEee.Tests/Objects/Vehicles/CloakingTest.cs b/FrEee.Tests/Objects/Vehicles/CloakingTest.cs index 7a941b67..79f7ac0f 100644 --- a/FrEee.Tests/Objects/Vehicles/CloakingTest.cs +++ b/FrEee.Tests/Objects/Vehicles/CloakingTest.cs @@ -6,7 +6,8 @@ using FrEee.Objects.Civilization; using FrEee.Objects.GameState; using FrEee.Objects.Space; -using FrEee.Objects.Technology; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; using NUnit.Framework; namespace FrEee.Objects.Vehicles; @@ -19,7 +20,7 @@ public class CloakingTest /// /// The ship that is looking for an enemy ship. /// - private static Ship destroyer; + private static IMajorSpaceVehicle destroyer; /// /// They're controlling the submarine. @@ -34,7 +35,7 @@ public class CloakingTest /// /// The ship that is hiding. /// - private static Ship submarine; + private static IMajorSpaceVehicle submarine; /// /// Where the ships are. @@ -56,17 +57,17 @@ public static void ClassInit() // initialize ships Assert.IsNotNull(Mod.Current); - var dsDesign = new Design(); + var dsHull = TestUtilities.CreateHull(VehicleTypes.Ship); + var dsDesign = TestUtilities.CreateDesign(seekers, dsHull); dsDesign.BaseName = "TestDestroyer"; - dsDesign.CreateHull(); dsDesign.Owner = seekers; - destroyer = dsDesign.Instantiate(); + destroyer = (IMajorSpaceVehicle)dsDesign.Instantiate(); destroyer.Owner = seekers; - var subDesign = new Design(); + var subHull = TestUtilities.CreateHull(VehicleTypes.Ship); + var subDesign = TestUtilities.CreateDesign(seekers, subHull); subDesign.BaseName = "TestSubmarine"; - subDesign.CreateHull(); subDesign.Owner = hiders; - submarine = subDesign.Instantiate(); + submarine = (IMajorSpaceVehicle)subDesign.Instantiate(); submarine.Owner = hiders; } diff --git a/FrEee.Tests/Objects/Vehicles/DamageTest.cs b/FrEee.Tests/Objects/Vehicles/DamageTest.cs index 9e700259..787f32fc 100644 --- a/FrEee.Tests/Objects/Vehicles/DamageTest.cs +++ b/FrEee.Tests/Objects/Vehicles/DamageTest.cs @@ -8,6 +8,9 @@ using FrEee.Objects.Civilization; using FrEee.Objects.GameState; using FrEee.Objects.Technology; +using FrEee.Processes.Combat; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; using NUnit.Framework; namespace FrEee.Objects.Vehicles; @@ -35,7 +38,7 @@ public class DamageTest /// /// The ship that is taking damage. /// - private static Ship ship; + private static IMajorSpaceVehicle ship; [OneTimeSetUp] public static void ClassInit() @@ -60,9 +63,9 @@ public static void ClassInit() engineTemplate.Durability = 10; // initialize ship's design - var design = new Design(); + var hull = TestUtilities.CreateHull(VehicleTypes.Ship); + var design = TestUtilities.CreateDesign(empire, hull); design.BaseName = "Punching Bag"; - var hull = new Hull(); Mod.Current.AssignID(hull, new List()); design.Hull = hull; design.Hull.ThrustPerMove = 1; @@ -73,7 +76,7 @@ public static void ClassInit() // TODO - account for C&C and supply requirements once those are a thing // initialize ship - ship = design.Instantiate(); + ship = (IMajorSpaceVehicle)design.Instantiate(); ship.Owner = empire; } @@ -98,7 +101,7 @@ public void EngineDamage() } } - private int GetExpectedSpeed(Ship ship) + private int GetExpectedSpeed(IMajorSpaceVehicle ship) { // add up thrust of all working engines, and divide by hull mass (engines per move, not tonnage) // HACK - assumes standard ability rules! diff --git a/FrEee.Tests/Objects/Vehicles/ResupplyTest.cs b/FrEee.Tests/Objects/Vehicles/ResupplyTest.cs index fadd4226..5ab89244 100644 --- a/FrEee.Tests/Objects/Vehicles/ResupplyTest.cs +++ b/FrEee.Tests/Objects/Vehicles/ResupplyTest.cs @@ -8,6 +8,8 @@ using FrEee.Objects.GameState; using FrEee.Objects.Space; using FrEee.Objects.Technology; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; using NUnit.Framework; namespace FrEee.Objects.Vehicles; @@ -19,7 +21,7 @@ public class ResupplyTest { private static Empire empire; private static Fleet fleet; - private static Ship ship1, ship2; + private static IMajorSpaceVehicle ship1, ship2; private static ComponentTemplate storageComp; private static int supplyPerComp; private static StarSystem sys; @@ -43,21 +45,21 @@ public static void ClassInit() // initialize ships Assert.IsNotNull(Mod.Current); - var dsn1 = new Design(); + var hull1 = TestUtilities.CreateHull(VehicleTypes.Ship); + var dsn1 = TestUtilities.CreateDesign(empire, hull1); dsn1.BaseName = "Shippy McShipface"; - dsn1.CreateHull(); dsn1.Components.Add(new MountedComponentTemplate(dsn1, storageComp)); dsn1.Owner = empire; - ship1 = dsn1.Instantiate(); + ship1 = (IMajorSpaceVehicle)dsn1.Instantiate(); ship1.Owner = empire; - var dsn2 = new Design(); + var hull2 = TestUtilities.CreateHull(VehicleTypes.Ship); + var dsn2 = TestUtilities.CreateDesign(empire, hull2); dsn2.BaseName = "Shippy McShipface Mk2"; - dsn2.CreateHull(); dsn2.Components.Add(new MountedComponentTemplate(dsn1, storageComp)); dsn2.Components.Add(new MountedComponentTemplate(dsn1, storageComp)); dsn2.Components.Add(new MountedComponentTemplate(dsn1, storageComp)); dsn2.Owner = empire; - ship2 = dsn2.Instantiate(); + ship2 = (IMajorSpaceVehicle)dsn2.Instantiate(); ship2.Owner = empire; // initialize fleet diff --git a/FrEee.Tests/Processes/Combat/DamageTypesTest.cs b/FrEee.Tests/Processes/Combat/DamageTypesTest.cs index 1273ce45..e6c86a05 100644 --- a/FrEee.Tests/Processes/Combat/DamageTypesTest.cs +++ b/FrEee.Tests/Processes/Combat/DamageTypesTest.cs @@ -4,7 +4,9 @@ using FrEee.Modding; using FrEee.Modding.Loaders; using FrEee.Objects.GameState; -using FrEee.Objects.Vehicles; +using FrEee.Utility; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; using NUnit.Framework; namespace FrEee.Processes.Combat; @@ -13,10 +15,10 @@ public class DamageTypesTest { private static Mod mod; - private Ship attacker; - private IDesign attackerDesign; - private Ship defender; - private IDesign defenderDesign; + private IMajorSpaceVehicle attacker; + private IDesign attackerDesign; + private IMajorSpaceVehicle defender; + private IDesign defenderDesign; [OneTimeSetUp] public static void ClassInit() @@ -34,13 +36,13 @@ public static void ClassInit() public void Init() { // create dummy designs - attackerDesign = new Design(); + attackerDesign = (IDesign)DIRoot.Designs.Build(VehicleTypes.Ship); attackerDesign.AddComponent(mod.ComponentTemplates.FindByName("Bridge")); attackerDesign.AddComponent(mod.ComponentTemplates.FindByName("Life Support")); attackerDesign.AddComponent(mod.ComponentTemplates.FindByName("Crew Quarters")); attackerDesign.AddComponent(mod.ComponentTemplates.FindByName("Quantum Reactor")); - defenderDesign = new Design(); - defenderDesign.AddComponent(mod.ComponentTemplates.FindByName("Bridge")); + defenderDesign = (IDesign)DIRoot.Designs.Build(VehicleTypes.Ship); + defenderDesign.AddComponent(mod.ComponentTemplates.FindByName("Bridge")); defenderDesign.AddComponent(mod.ComponentTemplates.FindByName("Life Support")); defenderDesign.AddComponent(mod.ComponentTemplates.FindByName("Crew Quarters")); defenderDesign.AddComponent(mod.ComponentTemplates.FindByName("Quantum Reactor")); @@ -141,7 +143,7 @@ private void AddComponents(IDesign d, params string[] compNames) d.AddComponent(Mod.Current.ComponentTemplates.FindByName(cn)); } - private void Heal(Ship ship) + private void Heal(IMajorSpaceVehicle ship) { ship.Repair(); ship.ReplenishShields(); @@ -153,7 +155,7 @@ private void SetupDefender() Heal(defender); } - private void TestDamage(Ship attacker, IDamageable defender, int dmg, int expectedHullDmg = 0, int expectedArmorDmg = 0, int expectedPhasedShieldDmg = 0, int expectedNormalShieldDmg = 0) + private void TestDamage(IMajorSpaceVehicle attacker, IDamageable defender, int dmg, int expectedHullDmg = 0, int expectedArmorDmg = 0, int expectedPhasedShieldDmg = 0, int expectedNormalShieldDmg = 0) { var hhp = defender.HullHitpoints; var ahp = defender.ArmorHitpoints; diff --git a/FrEee.Tests/TestUtilities.cs b/FrEee.Tests/TestUtilities.cs index a2aa5c8d..ee1b17f1 100644 --- a/FrEee.Tests/TestUtilities.cs +++ b/FrEee.Tests/TestUtilities.cs @@ -1,9 +1,10 @@ using FrEee.Objects.Civilization; -using FrEee.Objects.Technology; -using FrEee.Objects.Vehicles; using FrEee.Modding; using FrEee.Objects.GameState; using FrEee.Modding.Loaders; +using FrEee.Vehicles; +using FrEee.Utility; +using FrEee.Vehicles.Types; namespace FrEee; @@ -19,37 +20,25 @@ public static Game CreateGalaxyWithMod(string? modPath = null) public static Empire CreateEmpire(string name = "Galactic Empire") => new() { Name = name }; - public static IHull CreateHull(string name) - where T : IVehicle + public static IHull CreateHull(VehicleTypes vehicleType, string name = "Generic Hull") { - Hull hull = new() - { - Name = name, - ModID = name, - ThrustPerMove = 1 - }; + var hull = DIRoot.Hulls.Build(vehicleType); + hull.Name = name; + hull.ModID = name; + hull.ThrustPerMove = 1; Mod.Current.Hulls.Add(hull); return hull; } - public static IHull CreateHull(this IDesign design, string? name = null) - where T : IVehicle + public static IDesign CreateDesign(Empire owner, IHull hull, string name = "Generic Design") { - var hull = CreateHull(name ?? design.BaseName); - design.Hull = hull; - return hull; + var design = DIRoot.Designs.Build(hull); + design.BaseName = name; + design.Owner = owner; + return design; } - public static IDesign CreateDesign(Empire owner, string name = "Generic Design") - where T : IVehicle - => new Design() - { - BaseName = name, - Owner = owner, - }; - - public static T CreateVehicle(IDesign design, Empire owner) - where T : IVehicle + public static IVehicle CreateVehicle(IDesign design, Empire owner) { var vehicle = design.Instantiate(); vehicle.Owner = owner; diff --git a/FrEee.Tests/Utility/SerializerTest.cs b/FrEee.Tests/Utility/SerializerTest.cs index 5d80dc47..cfaa8fca 100644 --- a/FrEee.Tests/Utility/SerializerTest.cs +++ b/FrEee.Tests/Utility/SerializerTest.cs @@ -1,5 +1,4 @@ using FrEee.Objects.Civilization; -using FrEee.Objects.Vehicles; using FrEee.Modding; using FrEee.Serialization; using FrEee.Extensions; @@ -11,6 +10,8 @@ using FrEee.Modding.Templates; using FrEee.Modding.Scripts; using FrEee.Modding.Loaders; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; namespace FrEee.Utility; @@ -107,11 +108,12 @@ public void LookUpComplexType() var st = new SafeType(tname); Assert.AreEqual(typeof(List>), st.Type); } - { + // TODO: figure out how to do this when the Ship type is not available + /*{ var tname = "FrEee.Objects.Orders.ConstructionOrder`2[[FrEee.Objects.Vehicles.Ship, FrEee.Core],[FrEee.Objects.Vehicles.Design`1[[FrEee.Objects.Vehicles.Ship, FrEee.Core]], FrEee.Core"; var st = new SafeType(tname); Assert.AreEqual(typeof(ConstructionOrder>), st.Type); - } + }*/ { var tname = "System.Collections.Generic.Dictionary`2[[FrEee.Modding.Abilities.AbilityRule, FrEee.Core],[FrEee.Modding.Formula`1[[System.Int32, System.Private.CoreLib]], System.Private.CoreLib"; var st = new SafeType(tname); diff --git a/FrEee.UI.WinForms/Controls/BattleView.cs b/FrEee.UI.WinForms/Controls/BattleView.cs index 8ce888fe..a07d8411 100644 --- a/FrEee.UI.WinForms/Controls/BattleView.cs +++ b/FrEee.UI.WinForms/Controls/BattleView.cs @@ -1,5 +1,4 @@ using FrEee.Objects.Space; -using FrEee.Objects.Vehicles; using FrEee.Utility; using FrEee.Extensions; using System; @@ -10,6 +9,8 @@ using System.Windows.Forms; using FrEee.Processes.Combat; using FrEee.Processes.Combat.Events; +using FrEee.Vehicles.Types; +using FrEee.Vehicles; namespace FrEee.UI.WinForms.Controls; @@ -210,7 +211,7 @@ protected override void OnPaint(PaintEventArgs pe) if (here.OfType().Any()) { var largest = here.OfType().Largest(); - if (largest is SpaceVehicle v) + if (largest is ISpaceVehicle v) pic = v.Icon.Resize(drawsize); // spacecraft get the icon, not the portrait, drawn, since the icon is topdown else pic = largest.Portrait.Resize(drawsize); @@ -226,9 +227,9 @@ protected override void OnPaint(PaintEventArgs pe) else pe.Graphics.DrawImage(pic, drawx - drawsize / 2f, drawy - drawsize / 2f, drawsize, drawsize); } - if (here.OfType().Any()) + if (here.OfType().Any(q => q.CanInvadeAndPoliceColonies)) { - var largest = here.OfType().WithMax(t => t.Hull.Size).First(); + var largest = here.OfType().Where(q => q.CanInvadeAndPoliceColonies).WithMax(t => t.Hull.Size).First(); pic = largest.Icon.Resize(drawsize); if (useSquares) pe.Graphics.FillRectangle(new SolidBrush(largest.Owner?.Color ?? Color.White), drawx - drawsize / 2f, drawy - drawsize / 2f, drawsize, drawsize); diff --git a/FrEee.UI.WinForms/Controls/Cargolist.cs b/FrEee.UI.WinForms/Controls/Cargolist.cs index 50d87972..fe02f037 100644 --- a/FrEee.UI.WinForms/Controls/Cargolist.cs +++ b/FrEee.UI.WinForms/Controls/Cargolist.cs @@ -8,7 +8,8 @@ using System.Linq; using System.Windows.Forms; using FrEee.Objects.Civilization.CargoStorage; -using FrEee.Objects.Vehicles; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; namespace FrEee.UI.WinForms.Controls; diff --git a/FrEee.UI.WinForms/Controls/DesignReport.cs b/FrEee.UI.WinForms/Controls/DesignReport.cs index 62558d59..43c745eb 100644 --- a/FrEee.UI.WinForms/Controls/DesignReport.cs +++ b/FrEee.UI.WinForms/Controls/DesignReport.cs @@ -5,8 +5,8 @@ using FrEee.UI.WinForms.Utility.Extensions; using System.Linq; using System.Windows.Forms; -using FrEee.Objects.Vehicles; using FrEee.Modding.Abilities; +using FrEee.Vehicles; namespace FrEee.UI.WinForms.Controls; diff --git a/FrEee.UI.WinForms/Controls/FleetReport.cs b/FrEee.UI.WinForms/Controls/FleetReport.cs index 1b048afe..bd5ae9c1 100644 --- a/FrEee.UI.WinForms/Controls/FleetReport.cs +++ b/FrEee.UI.WinForms/Controls/FleetReport.cs @@ -1,6 +1,5 @@ using FrEee.Objects.Civilization; using FrEee.Objects.Space; -using FrEee.Objects.Vehicles; using FrEee.Utility; using FrEee.Extensions; using FrEee.UI.WinForms.Interfaces; @@ -12,6 +11,8 @@ using FrEee.Objects.Civilization.Orders; using FrEee.Modding.Abilities; using FrEee.Gameplay.Commands.Orders; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; namespace FrEee.UI.WinForms.Controls; @@ -97,7 +98,7 @@ public void Bind() lstVehicleSummary.Initialize(32, 32); foreach (var f in Fleet.Vehicles.OfType()) lstVehicleSummary.AddItemWithImage("Subfleets", f.Name, f, f.Icon); - foreach (var g in Fleet.Vehicles.OfType().GroupBy(v => v.Design)) + foreach (var g in Fleet.Vehicles.OfType().GroupBy(v => v.Design)) lstVehicleSummary.AddItemWithImage(g.Key.Role + "s", g.Count() + "x " + g.Key.Name, g.Key, g.Key.Icon); // cargo space free @@ -318,10 +319,10 @@ private void treeVehicles_NodeMouseClick(object sender, TreeNodeMouseClickEventA var f = (Fleet)e.Node.Tag; FindForm().ShowChildForm(new FleetReport(f).CreatePopupForm(f.Name)); } - else if (e.Node.Tag is SpaceVehicle) + else if (e.Node.Tag is ISpaceVehicle) { - var v = (SpaceVehicle)e.Node.Tag; - FindForm().ShowChildForm(new SpaceVehicleReport(v).CreatePopupForm(v.Name)); + var v = (ISpaceVehicle)e.Node.Tag; + FindForm().ShowChildForm(new SpaceVehicleReport(v).CreatePopupForm(((INameable)v).Name)); } } } diff --git a/FrEee.UI.WinForms/Controls/SpaceVehicleReport.cs b/FrEee.UI.WinForms/Controls/SpaceVehicleReport.cs index 5fd52780..aabd16b9 100644 --- a/FrEee.UI.WinForms/Controls/SpaceVehicleReport.cs +++ b/FrEee.UI.WinForms/Controls/SpaceVehicleReport.cs @@ -1,6 +1,5 @@ using FrEee.Objects.Civilization; using FrEee.Objects.Technology; -using FrEee.Objects.Vehicles; using FrEee.Utility; using FrEee.Extensions; using FrEee.UI.WinForms.Interfaces; @@ -14,29 +13,31 @@ using FrEee.Objects.Civilization.CargoStorage; using FrEee.Modding.Abilities; using FrEee.Gameplay.Commands.Orders; +using FrEee.Vehicles.Types; +using FrEee.Vehicles; namespace FrEee.UI.WinForms.Controls; /// /// A report on a space vehicle. /// -public partial class SpaceVehicleReport : UserControl, IBindable +public partial class SpaceVehicleReport : UserControl, IBindable { public SpaceVehicleReport() { InitializeComponent(); } - public SpaceVehicleReport(SpaceVehicle vehicle) + public SpaceVehicleReport(ISpaceVehicle vehicle) { InitializeComponent(); Vehicle = vehicle; } - public SpaceVehicle Vehicle { get { return vehicle; } set { vehicle = value; Bind(); } } - private SpaceVehicle vehicle; + public ISpaceVehicle Vehicle { get { return vehicle; } set { vehicle = value; Bind(); } } + private ISpaceVehicle vehicle; - public void Bind(SpaceVehicle data) + public void Bind(ISpaceVehicle data) { Vehicle = data; Bind(); @@ -60,7 +61,7 @@ public void Bind() txtAge.BackColor = txtAge.Text == "Current" ? Color.Transparent : Color.FromArgb(64, 64, 0); // name and stuff - txtName.Text = vehicle.Name; + txtName.Text = ((INameable)vehicle).Name; txtRole.Text = vehicle.Design.Role; txtClass.Text = vehicle.Design.Name; txtHullSize.Text = vehicle.Design.Hull.Name + " (" + vehicle.Design.Hull.Size.Kilotons() + ")"; @@ -90,7 +91,7 @@ public void Bind() // income // TODO - research and intel income var remoteMining = vehicle.Owner.RemoteMiners.Where(kvp => kvp.Key.Item1 == vehicle).Sum(kvp => kvp.Value); - var maintenance = vehicle.MaintenanceCost; + var maintenance = ((IVehicle)vehicle).MaintenanceCost; var rawResources = vehicle.RawResourceIncome(); var netIncome = remoteMining + rawResources - maintenance; resIncomeMin.Amount = netIncome[Resource.Minerals]; diff --git a/FrEee.UI.WinForms/Controls/StarSystemReport.cs b/FrEee.UI.WinForms/Controls/StarSystemReport.cs index a6e5d3d7..6197a516 100644 --- a/FrEee.UI.WinForms/Controls/StarSystemReport.cs +++ b/FrEee.UI.WinForms/Controls/StarSystemReport.cs @@ -1,12 +1,12 @@ using FrEee.Objects.Civilization; using FrEee.Objects.Space; -using FrEee.Objects.Vehicles; using FrEee.Extensions; using FrEee.UI.WinForms.Interfaces; using System.Linq; using System.Windows.Forms; using FrEee.Objects.Civilization.CargoStorage; using FrEee.Modding.Abilities; +using FrEee.Vehicles.Types; namespace FrEee.UI.WinForms.Controls; @@ -59,7 +59,7 @@ public void Bind() txtNeutralFacilities.Text = colonies.Where(c => Empire.Current.IsNeutralTo(c.Owner, StarSystem)).Sum(c => c.Facilities.Count).ToString(); txtEnemyFacilities.Text = colonies.Where(c => Empire.Current.IsEnemyOf(c.Owner, StarSystem)).Sum(c => c.Facilities.Count).ToString(); - var vehicles = StarSystem.FindSpaceObjects(); + var vehicles = StarSystem.FindSpaceObjects(); txtOurVehicles.Text = vehicles.Where(v => v.Owner == Empire.Current).Sum(v => v.Design.Hull.Size).Kilotons(); txtAllyVehicles.Text = vehicles.Where(v => Empire.Current.IsAllyOf(v.Owner, StarSystem)).Sum(v => v.Design.Hull.Size).Kilotons(); txtNeutralVehicles.Text = vehicles.Where(v => Empire.Current.IsNeutralTo(v.Owner, StarSystem)).Sum(v => v.Design.Hull.Size).Kilotons(); diff --git a/FrEee.UI.WinForms/Controls/StarSystemView.cs b/FrEee.UI.WinForms/Controls/StarSystemView.cs index dbfac4c5..5a8359f6 100644 --- a/FrEee.UI.WinForms/Controls/StarSystemView.cs +++ b/FrEee.UI.WinForms/Controls/StarSystemView.cs @@ -1,6 +1,5 @@ using FrEee.Objects.Civilization; using FrEee.Objects.Space; -using FrEee.Objects.Vehicles; using FrEee.Extensions; using System; using System.Drawing; @@ -8,6 +7,7 @@ using System.Windows.Forms; using FrEee.Objects.GameState; using FrEee.Modding.Abilities; +using FrEee.Vehicles.Types; namespace FrEee.UI.WinForms.Controls; @@ -156,7 +156,7 @@ protected override void OnPaint(PaintEventArgs pe) if (largest != null) { Image pic; - if (largest is SpaceVehicle) + if (largest is ISpaceVehicle) pic = largest.Icon.Resize((int)drawsize); // spacecraft get the icon, not the portrait, drawn, since the icon is topdown else pic = largest.Portrait.Resize((int)drawsize); diff --git a/FrEee.UI.WinForms/Forms/ActivateAbilityForm.cs b/FrEee.UI.WinForms/Forms/ActivateAbilityForm.cs index 272f0bc6..785d2bc5 100644 --- a/FrEee.UI.WinForms/Forms/ActivateAbilityForm.cs +++ b/FrEee.UI.WinForms/Forms/ActivateAbilityForm.cs @@ -7,12 +7,12 @@ using System.Data; using System.Linq; using System.Windows.Forms; -using FrEee.Objects.Technology; using FrEee.Objects.GameState; using FrEee.Objects.Civilization.Orders; using FrEee.Modding.Abilities; using FrEee.Utility; using FrEee.Gameplay.Commands.Orders; +using FrEee.Vehicles; namespace FrEee.UI.WinForms.Forms; diff --git a/FrEee.UI.WinForms/Forms/BattleReplayForm.cs b/FrEee.UI.WinForms/Forms/BattleReplayForm.cs index 985f16de..f8da462f 100644 --- a/FrEee.UI.WinForms/Forms/BattleReplayForm.cs +++ b/FrEee.UI.WinForms/Forms/BattleReplayForm.cs @@ -1,6 +1,5 @@ using FrEee.Objects.Civilization; using FrEee.Objects.Space; -using FrEee.Objects.Vehicles; using FrEee.Extensions; using FrEee.UI.WinForms.Controls; using FrEee.UI.WinForms.Interfaces; @@ -11,6 +10,7 @@ using System.Windows.Forms; using FrEee.Processes.Combat; using FrEee.Processes.Combat.Events; +using FrEee.Vehicles.Types; namespace FrEee.UI.WinForms.Forms; @@ -32,7 +32,7 @@ public ICombatant SelectedCombatant { selectedCombatant = value; reportPanel.Controls.Clear(); - if (value is SpaceVehicle v) + if (value is ISpaceVehicle v) reportPanel.Controls.Add(new SpaceVehicleReport(v) { Dock = DockStyle.Fill }); else if (value is Planet p) reportPanel.Controls.Add(new PlanetReport(p) { Dock = DockStyle.Fill }); diff --git a/FrEee.UI.WinForms/Forms/BattleResultsForm.cs b/FrEee.UI.WinForms/Forms/BattleResultsForm.cs index ef4a0b54..b1f660b1 100644 --- a/FrEee.UI.WinForms/Forms/BattleResultsForm.cs +++ b/FrEee.UI.WinForms/Forms/BattleResultsForm.cs @@ -10,8 +10,8 @@ using System.Drawing; using System.Linq; using System.Windows.Forms; -using FrEee.Objects.Vehicles; using FrEee.Processes.Combat; +using FrEee.Vehicles; namespace FrEee.UI.WinForms.Forms; diff --git a/FrEee.UI.WinForms/Forms/CombatSimulatorForm.cs b/FrEee.UI.WinForms/Forms/CombatSimulatorForm.cs index 5a1cfda3..bec02db7 100644 --- a/FrEee.UI.WinForms/Forms/CombatSimulatorForm.cs +++ b/FrEee.UI.WinForms/Forms/CombatSimulatorForm.cs @@ -1,7 +1,6 @@ using FrEee.Objects; using FrEee.Objects.Civilization; using FrEee.Objects.Space; -using FrEee.Objects.Vehicles; using FrEee.Modding; using FrEee.Extensions; using FrEee.UI.WinForms.Utility.Extensions; @@ -14,6 +13,8 @@ using FrEee.Objects.GameState; using FrEee.Processes.Combat; using FrEee.Utility; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; namespace FrEee.UI.WinForms.Forms; @@ -165,7 +166,8 @@ private void btnAddVehicle_Click(object sender, EventArgs e) } if (IsGroundCombat) { - if (!(dsn is IDesign)) + // TODO: weapon platforms in ground combat? + if (!(dsn.CanInvadeAndPoliceColonies)) { MessageBox.Show("Only troop designs can be added to the vehicle list for ground combat."); return; @@ -173,7 +175,7 @@ private void btnAddVehicle_Click(object sender, EventArgs e) } else { - if (!(dsn is IDesign)) + if (!(dsn.IsSpaceVehicleDesign)) { MessageBox.Show("Only space vehicle designs can be added to the vehicle list for space combat."); return; @@ -183,15 +185,15 @@ private void btnAddVehicle_Click(object sender, EventArgs e) // need to set owner *after* copying vehicle! if (IsGroundCombat) { - var sv = new SimulatedUnit((Troop)dsn.Instantiate()); - var v = (Troop)sv.Unit; + var sv = new SimulatedUnit((IUnit)dsn.Instantiate()); + var v = sv.Unit; v.Owner = CurrentEmpire.Empire; CurrentEmpire.Troops.Add(sv); } else { - var sv = new SimulatedSpaceObject((SpaceVehicle)dsn.Instantiate()); - var v = (SpaceVehicle)sv.SpaceObject; + var sv = new SimulatedSpaceObject((ISpaceVehicle)dsn.Instantiate()); + var v = (ISpaceVehicle)sv.SpaceObject; v.Owner = CurrentEmpire.Empire; v.SupplyRemaining = v.SupplyStorage; CurrentEmpire.SpaceObjects.Add(sv); @@ -253,7 +255,7 @@ private void btnOK_Click(object sender, EventArgs e) simPlanet.Colony = new Colony(); simPlanet.Colony.Owner = Empires.First().Empire; simPlanet.Sector = new Sector(new StarSystem(0) { Name = "Simulation" }, new Point()); - foreach (Troop t in Empires.SelectMany(se => se.Troops.Select(ss => ss.Unit))) + foreach (IUnit t in Empires.SelectMany(se => se.Troops.Select(ss => ss.Unit))) planet.Cargo.Units.Add(t); battle = DIRoot.Battles.BuildGroundBattle(planet); diff --git a/FrEee.UI.WinForms/Forms/ConstructionQueueForm.cs b/FrEee.UI.WinForms/Forms/ConstructionQueueForm.cs index a7b65c9f..ee4c05c9 100644 --- a/FrEee.UI.WinForms/Forms/ConstructionQueueForm.cs +++ b/FrEee.UI.WinForms/Forms/ConstructionQueueForm.cs @@ -13,7 +13,6 @@ using System.Linq; using System.Windows.Forms; using FrEee.Objects.Civilization.Construction; -using FrEee.Objects.Vehicles; using FrEee.Objects.Civilization.Orders; using FrEee.Objects.GameState; using FrEee.Objects.Civilization.CargoStorage; @@ -21,6 +20,7 @@ using FrEee.Gameplay.Commands; using FrEee.Gameplay.Commands.Orders; using FrEee.Gameplay.Commands.Designs; +using FrEee.Vehicles; namespace FrEee.UI.WinForms.Forms; diff --git a/FrEee.UI.WinForms/Forms/DesignListForm.cs b/FrEee.UI.WinForms/Forms/DesignListForm.cs index eb68f153..c03d708c 100644 --- a/FrEee.UI.WinForms/Forms/DesignListForm.cs +++ b/FrEee.UI.WinForms/Forms/DesignListForm.cs @@ -10,11 +10,12 @@ using System.Linq; using System.Windows.Forms; using FrEee.Objects.Civilization.Construction; -using FrEee.Objects.Vehicles; using FrEee.Objects.GameState; using FrEee.Objects.Space; using FrEee.Gameplay.Commands.Orders; using FrEee.Gameplay.Commands.Designs; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; namespace FrEee.UI.WinForms.Forms; diff --git a/FrEee.UI.WinForms/Forms/DiplomacyForm.cs b/FrEee.UI.WinForms/Forms/DiplomacyForm.cs index bf06ad88..33ff568b 100644 --- a/FrEee.UI.WinForms/Forms/DiplomacyForm.cs +++ b/FrEee.UI.WinForms/Forms/DiplomacyForm.cs @@ -3,7 +3,6 @@ using FrEee.Objects.Civilization.Diplomacy.Clauses; using FrEee.Objects.Space; using FrEee.Objects.Technology; -using FrEee.Objects.Vehicles; using FrEee.Modding; using FrEee.Utility; using FrEee.Extensions; @@ -18,6 +17,8 @@ using FrEee.Objects.Civilization.Diplomacy.Actions; using FrEee.Modding.Abilities; using FrEee.Gameplay.Commands; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; namespace FrEee.UI.WinForms.Forms; @@ -108,8 +109,8 @@ private void btnReturn_Click(object sender, EventArgs e) package.TreatyClauses.Remove((Clause)node.Tag); else if (node.Tag is Planet) package.Planets.Remove((Planet)node.Tag); - else if (node.Tag is Vehicle) - package.Vehicles.Remove((Vehicle)node.Tag); + else if (node.Tag is IVehicle) + package.Vehicles.Remove((IVehicle)node.Tag); else if (node.Tag is KeyValuePair) { var kvp = (KeyValuePair)node.Tag; @@ -388,7 +389,7 @@ private void PopulateSomeoneHas(Empire emp, TreeView tree, Package package) // sort vehicles descending by size, then alphabetically // no trading units that are in cargo var vehiclesNode = tree.AddItemWithImage("Vehicles", "Vehicles", Pictures.GetVehicleTypeImage(emp.ShipsetPath, VehicleTypes.Ship)); - foreach (var v in emp.OwnedSpaceObjects.OfType().Where(v => !package.Vehicles.Contains(v) && !(v is IUnit && ((IUnit)v).Container is ISpaceObject)).OrderByDescending(v => v.Design.Hull.Size).ThenBy(v => v.Name)) + foreach (var v in emp.OwnedSpaceObjects.OfType().Where(v => !package.Vehicles.Contains(v) && !(v is IUnit && ((IUnit)v).Container is ISpaceObject)).OrderByDescending(v => v.Design.Hull.Size).ThenBy(v => v.Name)) vehiclesNode.AddItemWithImage(v.Name, v, v.Icon); // resources @@ -477,7 +478,7 @@ private void Transfer(TreeView tree, Package package) } else if (type == "Vehicles") { - var v = (Vehicle)node.Tag; + var v = (IVehicle)node.Tag; package.Vehicles.Add(v); } else if (type == "Resources") diff --git a/FrEee.UI.WinForms/Forms/FleetTransferForm.cs b/FrEee.UI.WinForms/Forms/FleetTransferForm.cs index 1adfddcc..58a58d52 100644 --- a/FrEee.UI.WinForms/Forms/FleetTransferForm.cs +++ b/FrEee.UI.WinForms/Forms/FleetTransferForm.cs @@ -1,7 +1,6 @@  using FrEee.Objects.Civilization; using FrEee.Objects.Space; -using FrEee.Objects.Vehicles; using FrEee.Utility; using FrEee.Extensions; using FrEee.UI.WinForms.Controls; @@ -14,6 +13,8 @@ using System.Windows.Forms; using FrEee.Gameplay.Commands; using FrEee.Gameplay.Commands.Fleets; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; namespace FrEee.UI.WinForms.Forms; @@ -146,17 +147,17 @@ private void BindVehicles(IMobileSpaceObject selected = null) var vehicles = new HashSet(); // find vehicles in sector that are not fleets - foreach (var v in sector.SpaceObjects.OfType().OwnedBy(Empire.Current)) + foreach (var v in sector.SpaceObjects.OfType().OwnedBy(Empire.Current)) vehicles.Add(v); // add vehicles that are being removed from fleets (but not fleets themselves, those go in the fleets tree) - foreach (var v in newCommands.OfType().Select(c => c.Executor).OfType()) + foreach (var v in newCommands.OfType().Select(c => c.Executor).OfType()) vehicles.Add(v); - foreach (var v in newCommands.OfType().SelectMany(c => c.Executor.Vehicles.OfType())) + foreach (var v in newCommands.OfType().SelectMany(c => c.Executor.Vehicles.OfType())) vehicles.Add(v); // remove vehicles that are being added to fleets - foreach (var v in newCommands.OfType().Select(c => c.Executor).OfType()) + foreach (var v in newCommands.OfType().Select(c => c.Executor).OfType()) vehicles.Remove(v); // make a tree of vehicles @@ -444,9 +445,9 @@ private void treeFleets_NodeMouseClick(object sender, TreeNodeMouseClickEventArg // show report if you right click if (e.Button == MouseButtons.Right) { - if (e.Node.Tag is SpaceVehicle) + if (e.Node.Tag is ISpaceVehicle) { - var v = e.Node.Tag as SpaceVehicle; + var v = e.Node.Tag as ISpaceVehicle; this.ShowPopupForm(new SpaceVehicleReport(v), v.Name); } else if (e.Node.Tag is Fleet) @@ -464,8 +465,8 @@ private void treeFleets_NodeMouseClick(object sender, TreeNodeMouseClickEventArg private void treeFleets_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) { - if (e.Node.Tag is SpaceVehicle) - RemoveFromFleet(e.Node.Tag as SpaceVehicle); + if (e.Node.Tag is ISpaceVehicle) + RemoveFromFleet(e.Node.Tag as ISpaceVehicle); else if (e.Node.Tag is Fleet) { // if it's a root fleet, disband it, otherwise remove it @@ -482,9 +483,9 @@ private void treeVehicles_NodeMouseClick(object sender, TreeNodeMouseClickEventA // show report if you right click if (e.Button == MouseButtons.Right) { - if (e.Node.Tag is SpaceVehicle) + if (e.Node.Tag is ISpaceVehicle) { - var v = e.Node.Tag as SpaceVehicle; + var v = e.Node.Tag as ISpaceVehicle; this.ShowPopupForm(new SpaceVehicleReport(v), v.Name); } else if (e.Node.Tag is Fleet) diff --git a/FrEee.UI.WinForms/Forms/GameSetupForm.cs b/FrEee.UI.WinForms/Forms/GameSetupForm.cs index 7d2a9a14..c1fa7586 100644 --- a/FrEee.UI.WinForms/Forms/GameSetupForm.cs +++ b/FrEee.UI.WinForms/Forms/GameSetupForm.cs @@ -1,6 +1,5 @@ using FrEee.Objects.Space; using FrEee.Objects.Technology; -using FrEee.Objects.Vehicles; using FrEee.Objects.VictoryConditions; using FrEee.Modding; using FrEee.Modding.Templates; @@ -21,6 +20,7 @@ using FrEee.Processes.Setup; using FrEee.Processes.Setup.WarpPointPlacementStrategies; using FrEee.Modding.Loaders; +using FrEee.Vehicles; namespace FrEee.UI.WinForms.Forms; @@ -523,7 +523,7 @@ private void btnStart_Click(object sender, EventArgs e) var turn = Game.Current.TurnNumber; status.Message = "Loading game"; Game.Load(name + "_" + turn + "_0001.gam"); - Design.ImportFromLibrary(); + DIRoot.Designs.ImportFromLibrary(); Hide(); MainMenuForm.GetInstance().ShowChildForm(new MainGameForm(false, true)); } diff --git a/FrEee.UI.WinForms/Forms/HostConsoleForm.cs b/FrEee.UI.WinForms/Forms/HostConsoleForm.cs index 1d4b3890..e47337b2 100644 --- a/FrEee.UI.WinForms/Forms/HostConsoleForm.cs +++ b/FrEee.UI.WinForms/Forms/HostConsoleForm.cs @@ -1,5 +1,4 @@ using FrEee.Objects.Civilization; -using FrEee.Objects.Vehicles; using FrEee.Processes; using FrEee.Utility; using FrEee.Serialization; @@ -12,6 +11,7 @@ using System.Threading; using System.Windows.Forms; using FrEee.Objects.GameState; +using FrEee.Vehicles; namespace FrEee.UI.WinForms.Forms; @@ -85,7 +85,7 @@ private void btnPlayerView_Click(object sender, EventArgs e) Game.Current.CurrentEmpire = emp; Game.Current.Redact(); } - Design.ImportFromLibrary(); + DIRoot.Designs.ImportFromLibrary(); var form = new MainGameForm(true, false); Hide(); this.ShowChildForm(form); diff --git a/FrEee.UI.WinForms/Forms/HullPickerForm.cs b/FrEee.UI.WinForms/Forms/HullPickerForm.cs index 01567aff..e1a6d0fc 100644 --- a/FrEee.UI.WinForms/Forms/HullPickerForm.cs +++ b/FrEee.UI.WinForms/Forms/HullPickerForm.cs @@ -7,8 +7,8 @@ using System.Drawing; using System.Linq; using System.Windows.Forms; -using FrEee.Objects.Technology; -using FrEee.Objects.Vehicles; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; namespace FrEee.UI.WinForms.Forms; diff --git a/FrEee.UI.WinForms/Forms/LogForm.cs b/FrEee.UI.WinForms/Forms/LogForm.cs index 05b3d3b5..b7a8d86c 100644 --- a/FrEee.UI.WinForms/Forms/LogForm.cs +++ b/FrEee.UI.WinForms/Forms/LogForm.cs @@ -10,10 +10,11 @@ using System.Drawing; using System.Linq; using System.Windows.Forms; -using FrEee.Objects.Vehicles; using FrEee.Objects.Civilization.Diplomacy.Messages; using FrEee.Objects.GameState; using FrEee.Processes.Combat; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; namespace FrEee.UI.WinForms.Forms; diff --git a/FrEee.UI.WinForms/Forms/MainGameForm.cs b/FrEee.UI.WinForms/Forms/MainGameForm.cs index 5dc05dd3..627bad31 100644 --- a/FrEee.UI.WinForms/Forms/MainGameForm.cs +++ b/FrEee.UI.WinForms/Forms/MainGameForm.cs @@ -1,7 +1,6 @@ using FrEee.Objects.Civilization; using FrEee.Objects.Space; using FrEee.Objects.Technology; -using FrEee.Objects.Vehicles; using FrEee.Processes; using FrEee.Utility; using FrEee.Extensions; @@ -29,6 +28,8 @@ using FrEee.Gameplay.Commands; using FrEee.Gameplay.Commands.Orders; using FrEee.Gameplay.Commands.Messages; +using FrEee.Vehicles; +using FrEee.Vehicles.Types; namespace FrEee.UI.WinForms.Forms; @@ -598,24 +599,21 @@ private void ClearOrders() { if (SelectedSpaceObject.Owner == Empire.Current) { - if (SelectedSpaceObject is SpaceVehicle) + if (SelectedSpaceObject is ISpaceVehicle v) { - var v = (SpaceVehicle)SelectedSpaceObject; foreach (var order in v.Orders.ToArray()) v.RemoveOrderClientSide(order); BindReport(); } - else if (SelectedSpaceObject is Fleet) + else if (SelectedSpaceObject is Fleet f) { - var f = (Fleet)SelectedSpaceObject; foreach (var order in f.Orders.ToArray()) f.RemoveOrderClientSide(order); f.Orders.Clear(); BindReport(); } - else if (SelectedSpaceObject is Planet) + else if (SelectedSpaceObject is Planet p) { - var p = (Planet)SelectedSpaceObject; foreach (var order in p.Orders.ToArray()) p.RemoveOrderClientSide(order); p.Orders.Clear(); @@ -638,9 +636,9 @@ private Control CreateSpaceObjectReport(ISpaceObject sobj) return new StormReport((Storm)sobj); if (sobj is WarpPoint) return new WarpPointReport((WarpPoint)sobj); - if (sobj is SpaceVehicle) + if (sobj is ISpaceVehicle sv) { - var r = new SpaceVehicleReport((SpaceVehicle)sobj); + var r = new SpaceVehicleReport(sv); r.OrdersChanged += VehicleFleetReport_OrdersChanged; return r; }; @@ -713,7 +711,7 @@ private IEnumerable FindTodos() { var todos = new List(); - var ships = Empire.Current.OwnedSpaceObjects.OfType().Where(v => v.Container == null && v.StrategicSpeed > 0 && !v.Orders.Any()).Count(); + var ships = Empire.Current.OwnedSpaceObjects.OfType().Where(v => v.Container == null && v.StrategicSpeed > 0 && !v.Orders.Any()).Count(); if (ships == 1) todos.Add("1 idle ship"); else if (ships > 1) @@ -1302,7 +1300,7 @@ private void SetUpGui() SelectTab(AddTab(highlyPopulated.First())); else { - var withManyShips = Empire.Current.OwnedSpaceObjects.OfType().GroupBy(g => g.StarSystem).WithMax(g => g.Count()); + var withManyShips = Empire.Current.OwnedSpaceObjects.OfType().GroupBy(g => g.StarSystem).WithMax(g => g.Count()); if (withManyShips.Any()) SelectTab(AddTab(withManyShips.First().Key)); else diff --git a/FrEee.UI.WinForms/Forms/MainMenuForm.cs b/FrEee.UI.WinForms/Forms/MainMenuForm.cs index 47aa8e46..446815a4 100644 --- a/FrEee.UI.WinForms/Forms/MainMenuForm.cs +++ b/FrEee.UI.WinForms/Forms/MainMenuForm.cs @@ -1,4 +1,3 @@ -using FrEee.Objects.Vehicles; using FrEee.Modding; using FrEee.Utility; using FrEee.Extensions; @@ -18,6 +17,7 @@ using FrEee.Objects.GameState; using FrEee.Processes.Setup; using FrEee.Modding.Loaders; +using FrEee.Vehicles; namespace FrEee.UI.WinForms.Forms; @@ -115,7 +115,7 @@ private void btnQuickStart_Click(object sender, EventArgs e) if (status.Exception == null && !warnings.Any()) { - Design.ImportFromLibrary(); + DIRoot.Designs.ImportFromLibrary(); var game = new MainGameForm(false, true); this.ShowChildForm(game); game.FormClosed += (s, args) => @@ -165,7 +165,7 @@ private void LoadGalaxyFromFile(string filename, bool? loadPlr = null) } // load library designs - Design.ImportFromLibrary(); + DIRoot.Designs.ImportFromLibrary(); // display game view var form = new MainGameForm(false, true); diff --git a/FrEee.UI.WinForms/Forms/MountPickerForm.cs b/FrEee.UI.WinForms/Forms/MountPickerForm.cs index fae971a9..37a1cb34 100644 --- a/FrEee.UI.WinForms/Forms/MountPickerForm.cs +++ b/FrEee.UI.WinForms/Forms/MountPickerForm.cs @@ -6,6 +6,7 @@ using System.Drawing; using System.Linq; using System.Windows.Forms; +using FrEee.Vehicles; namespace FrEee.UI.WinForms.Forms; diff --git a/FrEee.UI.WinForms/Forms/PlanetListForm.cs b/FrEee.UI.WinForms/Forms/PlanetListForm.cs index 71dabb56..e639066c 100644 --- a/FrEee.UI.WinForms/Forms/PlanetListForm.cs +++ b/FrEee.UI.WinForms/Forms/PlanetListForm.cs @@ -1,7 +1,6 @@ using FrEee.Objects.Civilization; using FrEee.Objects.Civilization.Orders; using FrEee.Objects.Space; -using FrEee.Objects.Vehicles; using FrEee.Utility; using FrEee.Extensions; using FrEee.UI.WinForms.DataGridView; @@ -16,6 +15,7 @@ using FrEee.Objects.GameState; using FrEee.Objects.Civilization.CargoStorage; using FrEee.Modding.Abilities; +using FrEee.Vehicles.Types; namespace FrEee.UI.WinForms.Forms; @@ -31,7 +31,7 @@ public PlanetListForm() //BindTabs(); } - private IEnumerable colonizers, availableColonizers; + private IEnumerable colonizers, availableColonizers; private IEnumerable planets; @@ -56,7 +56,7 @@ private void colonizeToolStripMenuItem_Click(object sender, EventArgs e) MessageBox.Show("We have no colonizers capable of reaching " + p + "."); } var shortest = paths.WithMin(path => path.Path.Count()).First(); - var colonizer = (MajorSpaceVehicle)shortest.Colonizer; // HACK - what if units want to colonize? + var colonizer = (IMajorSpaceVehicle)shortest.Colonizer; // HACK - what if units want to colonize? // load population // prefer population of breathers of target planet's atmosphere - don't load nonbreathers races if breathers are present @@ -157,7 +157,7 @@ private void PlanetListForm_Load(object sender, EventArgs e) txtBreathableOther.Text = uncolonized.Where(p => otherAtmospheres.Contains(p.Atmosphere)).Count().ToString(); // show colony ship counts - colonizers = Galaxy.Current.FindSpaceObjects(v => + colonizers = Galaxy.Current.FindSpaceObjects(v => v.Owner == Empire.Current && ( v.Abilities().Any(a => a.Rule.Name.StartsWith("Colonize Planet - ")) diff --git a/FrEee.UI.WinForms/Forms/RecycleForm.cs b/FrEee.UI.WinForms/Forms/RecycleForm.cs index 9e2ab0fc..db89be99 100644 --- a/FrEee.UI.WinForms/Forms/RecycleForm.cs +++ b/FrEee.UI.WinForms/Forms/RecycleForm.cs @@ -1,7 +1,6 @@ using FrEee.Objects.Civilization; using FrEee.Objects.Space; using FrEee.Objects.Technology; -using FrEee.Objects.Vehicles; using FrEee.Extensions; using FrEee.UI.WinForms.Utility.Extensions; using System; @@ -16,6 +15,7 @@ using FrEee.Gameplay.Commands; using FrEee.Gameplay.Commands.Orders; using FrEee.Utility; +using FrEee.Vehicles.Types; namespace FrEee.UI.WinForms.Forms; @@ -68,17 +68,17 @@ private IEnumerable SelectedUnitsInCargo /// /// Finds all space vehicles that are selected (including units in space, but not units in cargo). /// - private IEnumerable SelectedVehiclesInSpace + private IEnumerable SelectedVehiclesInSpace { get { return treeVehicles.GetAllNodes() .Where(n => - n.Tag is SpaceVehicle && n.Checked) + n.Tag is ISpaceVehicle && n.Checked) .Select(n => - n.Tag as SpaceVehicle) + n.Tag as ISpaceVehicle) .Where(v => - !(v is IUnit && ((IUnit)v).Container != null)) + !(v is IUnit unit && unit.Container != null)) .ExceptNull(); } } @@ -131,7 +131,7 @@ private void Bind() // cargo of planets BindUnitsIn(p, pnode); } - foreach (var v in Sector.SpaceObjects.OfType().Where(v => v.Owner == Empire.Current)) + foreach (var v in Sector.SpaceObjects.OfType().Where(v => v.Owner == Empire.Current)) { // our space vehicles var vnode = treeVehicles.AddItemWithImage(v.Name, v, v.Icon); diff --git a/FrEee.UI.WinForms/Forms/ShipListForm.cs b/FrEee.UI.WinForms/Forms/ShipListForm.cs index 6e9fdcaf..720642f4 100644 --- a/FrEee.UI.WinForms/Forms/ShipListForm.cs +++ b/FrEee.UI.WinForms/Forms/ShipListForm.cs @@ -1,7 +1,6 @@ using FrEee.Objects.Civilization; using FrEee.Objects.Space; -using FrEee.Objects.Vehicles; using FrEee.Utility; using FrEee.Extensions; using FrEee.UI.WinForms.DataGridView; @@ -14,6 +13,7 @@ using System.Reflection; using System.Windows.Forms; using FrEee.Objects.GameState; +using FrEee.Vehicles.Types; namespace FrEee.UI.WinForms.Forms; @@ -68,13 +68,13 @@ private void ShipListForm_Load(object sender, EventArgs e) // show ship/unit/fleet counts sobjs = Galaxy.Current.FindSpaceObjects().Where(o => !(o is Planet) && (!(o is IUnit && ((IUnit)o).Container == null))); var ours = sobjs.Where(o => o.Owner == Empire.Current); - var ourShips = ours.OfType(); + var ourShips = ours.OfType(); txtShips.Text = ourShips.Count().ToString(); txtShipsOutsideFleets.Text = ourShips.Where(s => s.Container == null).Count().ToString(); var ourFleets = ours.OfType(); txtFleets.Text = ourFleets.Count().ToString(); txtFleetsOutsideFleets.Text = ourFleets.Where(f => f.Container == null).Count().ToString(); - var alienShips = sobjs.OfType(); + var alienShips = sobjs.OfType(); txtAlienShips.Text = alienShips.Count().ToString(); txtAllyShips.Text = alienShips.Where(s => s.Owner.IsAllyOf(Empire.Current, null)).Count().ToString(); txtEnemyShips.Text = alienShips.Where(s => s.Owner.IsEnemyOf(Empire.Current, null)).Count().ToString(); diff --git a/FrEee.UI.WinForms/Forms/TechTreeForm.cs b/FrEee.UI.WinForms/Forms/TechTreeForm.cs index 9e937bbf..8b66fd35 100644 --- a/FrEee.UI.WinForms/Forms/TechTreeForm.cs +++ b/FrEee.UI.WinForms/Forms/TechTreeForm.cs @@ -13,6 +13,7 @@ using System.Linq; using System.Windows.Forms; using FrEee.Objects.GameState; +using FrEee.Vehicles; namespace FrEee.UI.WinForms.Forms; diff --git a/FrEee.UI.WinForms/Forms/VehicleDesignForm.cs b/FrEee.UI.WinForms/Forms/VehicleDesignForm.cs index ccb2e103..16842f54 100644 --- a/FrEee.UI.WinForms/Forms/VehicleDesignForm.cs +++ b/FrEee.UI.WinForms/Forms/VehicleDesignForm.cs @@ -12,9 +12,9 @@ using System.Drawing; using System.Linq; using System.Windows.Forms; -using FrEee.Objects.Vehicles; using FrEee.Objects.GameState; using FrEee.Modding.Abilities; +using FrEee.Vehicles; namespace FrEee.UI.WinForms.Forms; @@ -33,7 +33,7 @@ public VehicleDesignForm(IHull hull) { InitializeComponent(); ShowComponentDetails(null); - Design = FrEee.Objects.Vehicles.Design.Create(hull); + Design = DIRoot.Designs.Build(hull); try { this.Icon = new Icon(FrEee.UI.WinForms.Properties.Resources.FrEeeIcon); } catch { } @@ -290,7 +290,7 @@ private void btnHull_Click(object sender, EventArgs e) // Changing vehicle types requires starting over, so warn the user if (MessageBox.Show("Changing the vehicle type requires starting over with your design. Abandon your old design?", "FrEee", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes) { - var d = FrEee.Objects.Vehicles.Design.Create(form.Hull.VehicleType); + var d = DIRoot.Designs.Build(form.Hull.VehicleType); d.TurnNumber = Game.Current.TurnNumber; d.Owner = Empire.Current; d.Hull = form.Hull; @@ -306,7 +306,7 @@ private void btnHull_Click(object sender, EventArgs e) } else { - var d = FrEee.Objects.Vehicles.Design.Create(form.Hull.VehicleType); + var d = DIRoot.Designs.Build(form.Hull.VehicleType); d.TurnNumber = Game.Current.TurnNumber; d.Owner = Empire.Current; d.Hull = form.Hull; diff --git a/FrEee.UI.WinForms/Objects/GalaxyViewModes/ForcesMode.cs b/FrEee.UI.WinForms/Objects/GalaxyViewModes/ForcesMode.cs index e74f6e5b..e00c8c15 100644 --- a/FrEee.UI.WinForms/Objects/GalaxyViewModes/ForcesMode.cs +++ b/FrEee.UI.WinForms/Objects/GalaxyViewModes/ForcesMode.cs @@ -1,7 +1,7 @@ using FrEee.Objects.Civilization; using FrEee.Objects.GameState; using FrEee.Objects.Space; -using FrEee.Objects.Vehicles; +using FrEee.Vehicles.Types; using System; using System.Collections.Generic; using System.Drawing; @@ -21,9 +21,9 @@ public override string Name protected override int GetAlpha(StarSystem sys) { - var forces = Galaxy.Current.StarSystemLocations.Select(l => new { System = l.Item, Vehicles = l.Item.FindSpaceObjects() }); + var forces = Galaxy.Current.StarSystemLocations.Select(l => new { System = l.Item, Vehicles = l.Item.FindSpaceObjects() }); var maxTonnage = forces.Max(f => f.Vehicles.Sum(v => v.Design.Hull.Size)); - var vehicles = sys.FindSpaceObjects().ToArray(); + var vehicles = sys.FindSpaceObjects().ToArray(); var tonnageHere = vehicles.Sum(v => v.Design.Hull.Size); return 255 * tonnageHere / maxTonnage; } @@ -31,7 +31,7 @@ protected override int GetAlpha(StarSystem sys) protected override IEnumerable> GetAmounts(StarSystem sys) { // find relative tonnage of friendly, allied, neutral, and and enemy forces - var vehicles = sys.FindSpaceObjects().ToArray(); + var vehicles = sys.FindSpaceObjects().ToArray(); var byOwner = vehicles.GroupBy(v => v.Owner); var friendlyTonnage = byOwner.Where(f => f.Key == Empire.Current).SelectMany(f => f).Sum(v => v.Design.Hull.Size); var allyTonnage = byOwner.Where(f => f.Key.IsAllyOf(Empire.Current, sys)).SelectMany(f => f).Sum(v => v.Design.Hull.Size); diff --git a/FrEee.UI.WinForms/Program.cs b/FrEee.UI.WinForms/Program.cs index 67a61e4f..9d93b35b 100644 --- a/FrEee.UI.WinForms/Program.cs +++ b/FrEee.UI.WinForms/Program.cs @@ -1,5 +1,4 @@ using FrEee.Objects.Civilization; -using FrEee.Objects.Vehicles; using FrEee.Processes; using FrEee.Utility; using FrEee.Extensions; @@ -16,6 +15,7 @@ using System.Windows.Forms; using FrEee.Objects.GameState; using FrEee.Root; +using FrEee.Vehicles; namespace FrEee.UI.WinForms; @@ -180,7 +180,7 @@ private static int PlayTurn(string plrfile = null) MessageBox.Show(plrfile + " does not exist. You will need to start your turn from the beginning."); } - Design.ImportFromLibrary(); + DIRoot.Designs.ImportFromLibrary(); var form = new MainGameForm(false, true); form.KeyPreview = true; diff --git a/FrEee.Core.Domain/Objects/Vehicles/Design.cs b/FrEee.Vehicles/Design.cs similarity index 85% rename from FrEee.Core.Domain/Objects/Vehicles/Design.cs rename to FrEee.Vehicles/Design.cs index a5b4cf59..b7c7546f 100644 --- a/FrEee.Core.Domain/Objects/Vehicles/Design.cs +++ b/FrEee.Vehicles/Design.cs @@ -18,110 +18,9 @@ using FrEee.Gameplay.Commands; using FrEee.Gameplay.Commands.Designs; using FrEee.Gameplay.Commands.Orders; +using FrEee.Vehicles.Types; -namespace FrEee.Objects.Vehicles; - -/// -/// Creates designs. -/// -public static class Design -{ - static Design() - { - militiaDesign = new Design(); - militiaDesign.BaseName = "Militia"; - var militiaWeapon = new ComponentTemplate(); - militiaWeapon.Durability = Mod.Current.Settings.MilitiaHitpoints; - militiaWeapon.Name = "Small Arms"; - militiaWeapon.WeaponInfo = new DirectFireWeaponInfo - { - Damage = Mod.Current.Settings.MilitiaFirepower, - MinRange = 0, - MaxRange = 1, - }; - militiaDesign.Components.Add(new MountedComponentTemplate(militiaDesign, militiaWeapon)); - } - - public static IDesign Create(VehicleTypes vt) - { - IDesign d; - switch (vt) - { - case VehicleTypes.Ship: - d = new Design(); - break; - - case VehicleTypes.Base: - d = new Design(); - break; - - case VehicleTypes.Fighter: - d = new Design(); - break; - - case VehicleTypes.Troop: - d = new Design(); - break; - - case VehicleTypes.Mine: - d = new Design(); - break; - - case VehicleTypes.Satellite: - d = new Design(); - break; - - case VehicleTypes.Drone: - d = new Design(); - break; - - case VehicleTypes.WeaponPlatform: - d = new Design(); - break; - - default: - throw new Exception("Cannot create a design for vehicle type " + vt + "."); - } - d.Owner = Empire.Current; - return d; - } - - public static IDesign Create(IHull hull) - { - var d = Create(hull.VehicleType); - d.Hull = hull; - return d; - } - - /// - /// Imports designs from the library into the game that aren't already in the game. - /// Requires a current empire. Should only be called client side. - /// - /// Copied designs imported. - public static IEnumerable ImportFromLibrary() - { - if (Empire.Current == null) - throw new InvalidOperationException("Can't import designs without a current empire."); - - var designs = Library.Import(d => d.IsValidInMod && !Empire.Current.KnownDesigns.Any(d2 => d2.Equals(d))).ToArray(); - - designs.SafeForeach(d => - { - d.IsNew = true; - d.Owner = Empire.Current; - d.TurnNumber = Game.Current.TurnNumber; - d.Iteration = Empire.Current.KnownDesigns.OwnedBy(Empire.Current).Where(x => x.BaseName == d.BaseName && x.IsUnlocked()).MaxOrDefault(x => x.Iteration) + 1; // auto assign nex available iteration - d.IsObsolete = d.IsObsolescent; - Empire.Current.KnownDesigns.Add(d); // only client side, don't need to worry about other players spying :) - }); - - return designs; - } - - public static Design militiaDesign; - - public static Design MilitiaDesign => militiaDesign; -} +namespace FrEee.Vehicles; /// /// A vehicle design. @@ -153,7 +52,7 @@ public int Accuracy public int ArmorHitpoints { - get { return this.Components.Where(c => c.ComponentTemplate.HasAbility("Armor")).Sum(c => c.Durability); } + get { return Components.Where(c => c.ComponentTemplate.HasAbility("Armor")).Sum(c => c.Durability); } } public string BaseName { get; set; } @@ -233,7 +132,7 @@ IHull IDesign.Hull public int HullHitpoints { - get { return this.Components.Where(c => !c.ComponentTemplate.HasAbility("Armor")).Sum(c => c.Durability); } + get { return Components.Where(c => !c.ComponentTemplate.HasAbility("Armor")).Sum(c => c.Durability); } } [DoNotSerialize] @@ -625,7 +524,7 @@ public IEnumerable Warnings if (!Owner.HasUnlocked(Hull)) yield return "You have not unlocked the " + Hull + "."; var comps = Components.Select(comp => comp.ComponentTemplate); - if (Hull.NeedsBridge && (!comps.Any(comp => comp.HasAbility("Ship Bridge")) && !comps.Any(comp => comp.HasAbility("Master Computer")))) + if (Hull.NeedsBridge && !comps.Any(comp => comp.HasAbility("Ship Bridge")) && !comps.Any(comp => comp.HasAbility("Master Computer"))) yield return "This hull requires a bridge or master computer."; if (comps.Count(comp => comp.HasAbility("Ship Bridge")) > 1) yield return "A vehicle can have no more than one bridge"; @@ -641,11 +540,11 @@ public IEnumerable Warnings yield return "This hull requires at least " + Hull.MinCrewQuarters + " life support modules or a Master Computer."; if (comps.Count(comp => comp.HasAbility("Ship Crew Quarters")) < Hull.MinCrewQuarters && !comps.Any(comp => comp.HasAbility("Master Computer"))) yield return "This hull requires at least " + Hull.MinCrewQuarters + " crew quarters or a Master Computer."; - if ((double)Components.Where(comp => comp.HasAbility("Cargo Storage")).Sum(comp => comp.Size) / (double)Hull.Size * 100d < Hull.MinPercentCargoBays) + if (Components.Where(comp => comp.HasAbility("Cargo Storage")).Sum(comp => comp.Size) / (double)Hull.Size * 100d < Hull.MinPercentCargoBays) yield return "This hull requires at least " + Hull.MinPercentCargoBays + "% of its space to be used by cargo-class components."; - if ((double)Components.Where(comp => comp.HasAbility("Launch/Recover Fighters")).Sum(comp => comp.Size) / (double)Hull.Size * 100d < Hull.MinPercentFighterBays) + if (Components.Where(comp => comp.HasAbility("Launch/Recover Fighters")).Sum(comp => comp.Size) / (double)Hull.Size * 100d < Hull.MinPercentFighterBays) yield return "This hull requires at least " + Hull.MinPercentFighterBays + "% of its space to be used by fighter bays."; - if ((double)Components.Where(comp => comp.HasAbility("Colonize Planet - Rock") || comp.HasAbility("Colonize Planet - Ice") || comp.HasAbility("Colonize Planet - Gas")).Sum(comp => comp.Size) / (double)Hull.Size * 100d < Hull.MinPercentColonyModules) + if (Components.Where(comp => comp.HasAbility("Colonize Planet - Rock") || comp.HasAbility("Colonize Planet - Ice") || comp.HasAbility("Colonize Planet - Gas")).Sum(comp => comp.Size) / (double)Hull.Size * 100d < Hull.MinPercentColonyModules) yield return "This hull requires at least " + Hull.MinPercentColonyModules + "% of its space to be used by colony modules."; foreach (var g in comps.GroupBy(comp => comp.Family)) { @@ -692,6 +591,11 @@ public IEnumerable Warnings /// private GameReference owner { get; set; } + // TODO: make this an ability + public bool CanInvadeAndPoliceColonies => typeof(T).IsAssignableTo(typeof(Troop)); + + public bool IsSpaceVehicleDesign => typeof(T).IsAssignableTo(typeof(ISpaceVehicle)); + public void AddComponent(ComponentTemplate ct, Mount m = null) { Components.Add(new MountedComponentTemplate(this, ct, m)); @@ -867,6 +771,8 @@ private IEnumerable GetPaths(string pathtype) return paths; } + + IDesign IDesign.Upgrade() => Upgrade(); } diff --git a/FrEee.Vehicles/DesignFactory.cs b/FrEee.Vehicles/DesignFactory.cs new file mode 100644 index 00000000..94268e17 --- /dev/null +++ b/FrEee.Vehicles/DesignFactory.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Extensions; +using FrEee.Modding; +using FrEee.Modding.Templates; +using FrEee.Objects.Civilization; +using FrEee.Objects.GameState; +using FrEee.Objects.Technology; +using FrEee.Utility; +using FrEee.Vehicles.Types; + +namespace FrEee.Vehicles; +public class DesignFactory + : IDesignFactory +{ + public IDesign Militia { get; } = BuildMilitia(); + + private static IDesign BuildMilitia() + { + var militiaDesign = new Design(); + militiaDesign.BaseName = "Militia"; + var militiaWeapon = new ComponentTemplate(); + militiaWeapon.Durability = Mod.Current.Settings.MilitiaHitpoints; + militiaWeapon.Name = "Small Arms"; + militiaWeapon.WeaponInfo = new DirectFireWeaponInfo + { + // TODO: rebuild militia design when mod changes + Damage = Mod.Current.Settings.MilitiaFirepower, + MinRange = 0, + MaxRange = 1, + }; + militiaDesign.Components.Add(new MountedComponentTemplate(militiaDesign, militiaWeapon)); + return militiaDesign; + } + + public IDesign Build(VehicleTypes vehicleType) + { + return vehicleType switch + { + VehicleTypes.Ship => new Design(), + VehicleTypes.Base => new Design(), + VehicleTypes.Fighter => new Design(), + VehicleTypes.Satellite => new Design(), + VehicleTypes.Troop => new Design(), + VehicleTypes.WeaponPlatform => new Design(), + VehicleTypes.Mine => new Design(), + VehicleTypes.Drone => new Design(), + var x => throw new NotSupportedException($"Can't build a design of type {x}. Only single vehicle types can be built."), + }; + } + + public IDesign Build(IHull hull) + { + var design = Build(hull.VehicleType); + design.Hull = hull; + return design; + } + + /// + /// Imports designs from the library into the game that aren't already in the game. + /// Requires a current empire. Should only be called client side. + /// + /// Copied designs imported. + public IEnumerable ImportFromLibrary() + { + if (Empire.Current == null) + throw new InvalidOperationException("Can't import designs without a current empire."); + + var designs = Library.Import(d => d.IsValidInMod && !Empire.Current.KnownDesigns.Any(d2 => d2.Equals(d))).ToArray(); + + designs.SafeForeach(d => + { + d.IsNew = true; + d.Owner = Empire.Current; + d.TurnNumber = Game.Current.TurnNumber; + d.Iteration = Empire.Current.KnownDesigns.OwnedBy(Empire.Current).Where(x => x.BaseName == d.BaseName && x.IsUnlocked()).MaxOrDefault(x => x.Iteration) + 1; // auto assign nex available iteration + d.IsObsolete = d.IsObsolescent; + Empire.Current.KnownDesigns.Add(d); // only client side, don't need to worry about other players spying :) + }); + + return designs; + } +} diff --git a/FrEee.Vehicles/FrEee.Vehicles.csproj b/FrEee.Vehicles/FrEee.Vehicles.csproj new file mode 100644 index 00000000..e6d9a67c --- /dev/null +++ b/FrEee.Vehicles/FrEee.Vehicles.csproj @@ -0,0 +1,22 @@ + + + + net9 + Library + FrEee.Vehicles + Stock implementations of vehicles for FrEee. + + + + + + + + + + + false + FrEee.Vehicles + + + \ No newline at end of file diff --git a/FrEee.Core.Domain/Objects/Technology/Hull.cs b/FrEee.Vehicles/Hull.cs similarity index 99% rename from FrEee.Core.Domain/Objects/Technology/Hull.cs rename to FrEee.Vehicles/Hull.cs index 2aebf7b8..08f766cc 100644 --- a/FrEee.Core.Domain/Objects/Technology/Hull.cs +++ b/FrEee.Vehicles/Hull.cs @@ -1,5 +1,4 @@ using FrEee.Objects.Civilization; -using FrEee.Objects.Vehicles; using FrEee.Modding; using FrEee.Utility; using FrEee.Serialization; @@ -10,8 +9,10 @@ using System.IO; using FrEee.Objects.GameState; using FrEee.Modding.Abilities; +using FrEee.Vehicles.Types; +using FrEee.Objects.Technology; -namespace FrEee.Objects.Technology; +namespace FrEee.Vehicles; /// /// A vehicle hull. diff --git a/FrEee.Vehicles/HullFactory.cs b/FrEee.Vehicles/HullFactory.cs new file mode 100644 index 00000000..89781a35 --- /dev/null +++ b/FrEee.Vehicles/HullFactory.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Vehicles.Types; + +namespace FrEee.Vehicles; +public class HullFactory + : IHullFactory +{ + public IHull Build(VehicleTypes vehicleType) + { + return vehicleType switch + { + VehicleTypes.Ship => new Hull(), + VehicleTypes.Base => new Hull(), + VehicleTypes.Fighter => new Hull(), + VehicleTypes.Satellite => new Hull(), + VehicleTypes.Troop => new Hull(), + VehicleTypes.WeaponPlatform => new Hull(), + VehicleTypes.Mine => new Hull(), + VehicleTypes.Drone => new Hull(), + var x => throw new NotSupportedException($"Can't build a hull of type {x}. Only single vehicle types can be built."), + }; + } +} diff --git a/FrEee.Core.Domain/Objects/Vehicles/Base.cs b/FrEee.Vehicles/Types/Base.cs similarity index 95% rename from FrEee.Core.Domain/Objects/Vehicles/Base.cs rename to FrEee.Vehicles/Types/Base.cs index 79abe027..ac3ac536 100644 --- a/FrEee.Core.Domain/Objects/Vehicles/Base.cs +++ b/FrEee.Vehicles/Types/Base.cs @@ -2,7 +2,7 @@ using FrEee.Objects.Space; using System; -namespace FrEee.Objects.Vehicles; +namespace FrEee.Vehicles.Types; [Serializable] public class Base : MajorSpaceVehicle diff --git a/FrEee.Core.Domain/Objects/Vehicles/Drone.cs b/FrEee.Vehicles/Types/Drone.cs similarity index 87% rename from FrEee.Core.Domain/Objects/Vehicles/Drone.cs rename to FrEee.Vehicles/Types/Drone.cs index 06fa4aa1..88d66080 100644 --- a/FrEee.Core.Domain/Objects/Vehicles/Drone.cs +++ b/FrEee.Vehicles/Types/Drone.cs @@ -7,7 +7,7 @@ using FrEee.Processes.Combat; using FrEee.Modding.Abilities; -namespace FrEee.Objects.Vehicles; +namespace FrEee.Vehicles.Types; [Serializable] public class Drone : SpaceVehicle, IUnit @@ -24,7 +24,7 @@ public override bool CanWarp ICargoContainer IContainable.Container { - get { return CommonExtensions.FindContainer(this); } + get { return this.FindContainer(); } } public override bool ParticipatesInGroundCombat @@ -62,4 +62,8 @@ public override void Place(ISpaceObject target) } public override bool FillsCombatTile => false; + + public bool CanInvadeAndPoliceColonies => false; + + public bool CanFireIntoSpaceFromPlanetaryCargo => false; } diff --git a/FrEee.Core.Domain/Objects/Vehicles/Fighter.cs b/FrEee.Vehicles/Types/Fighter.cs similarity index 86% rename from FrEee.Core.Domain/Objects/Vehicles/Fighter.cs rename to FrEee.Vehicles/Types/Fighter.cs index 8d934634..4236ba33 100644 --- a/FrEee.Core.Domain/Objects/Vehicles/Fighter.cs +++ b/FrEee.Vehicles/Types/Fighter.cs @@ -8,7 +8,7 @@ using FrEee.Processes.Combat; using FrEee.Modding.Abilities; -namespace FrEee.Objects.Vehicles; +namespace FrEee.Vehicles.Types; [Serializable] public class Fighter : SpaceVehicle, IUnit @@ -25,7 +25,7 @@ public override bool CanWarp ICargoContainer IContainable.Container { - get { return CommonExtensions.FindContainer(this); } + get { return this.FindContainer(); } } public override bool ParticipatesInGroundCombat @@ -64,7 +64,11 @@ public override void Place(ISpaceObject target) // HACK - until we end our game and this can be purged [DoNotSerialize] - private Cargo Cargo { get; set;} + private Cargo Cargo { get; set; } public override bool FillsCombatTile => false; + + public bool CanInvadeAndPoliceColonies => false; + + public bool CanFireIntoSpaceFromPlanetaryCargo => false; } diff --git a/FrEee.Core.Domain/Objects/Vehicles/MajorSpaceVehicle.cs b/FrEee.Vehicles/Types/MajorSpaceVehicle.cs similarity index 91% rename from FrEee.Core.Domain/Objects/Vehicles/MajorSpaceVehicle.cs rename to FrEee.Vehicles/Types/MajorSpaceVehicle.cs index 92422bcb..f2f25ec5 100644 --- a/FrEee.Core.Domain/Objects/Vehicles/MajorSpaceVehicle.cs +++ b/FrEee.Vehicles/Types/MajorSpaceVehicle.cs @@ -10,12 +10,10 @@ using FrEee.Objects.GameState; using FrEee.Processes.Combat; -namespace FrEee.Objects.Vehicles; +namespace FrEee.Vehicles.Types; -/// -/// A space vehicle which can contain cargo and is not a unit. -/// -public abstract class MajorSpaceVehicle : SpaceVehicle, ICargoTransferrer, IConstructor +public abstract class MajorSpaceVehicle + : SpaceVehicle, IMajorSpaceVehicle { protected MajorSpaceVehicle() : base() @@ -151,7 +149,7 @@ public ConstructionQueue ConstructionQueue } } - public override bool IsIdle => base.IsIdle || (ConstructionQueue != null && ConstructionQueue.IsIdle); + public override bool IsIdle => base.IsIdle || ConstructionQueue != null && ConstructionQueue.IsIdle; public override bool FillsCombatTile => true; } diff --git a/FrEee.Core.Domain/Objects/Vehicles/Mine.cs b/FrEee.Vehicles/Types/Mine.cs similarity index 79% rename from FrEee.Core.Domain/Objects/Vehicles/Mine.cs rename to FrEee.Vehicles/Types/Mine.cs index 7c532aae..a9177fd4 100644 --- a/FrEee.Core.Domain/Objects/Vehicles/Mine.cs +++ b/FrEee.Vehicles/Types/Mine.cs @@ -7,7 +7,7 @@ using FrEee.Processes.Combat; using System; -namespace FrEee.Objects.Vehicles; +namespace FrEee.Vehicles.Types; [Serializable] public class Mine : SpaceVehicle, IUnit @@ -24,7 +24,7 @@ public override bool CanWarp ICargoContainer IContainable.Container { - get { return CommonExtensions.FindContainer(this); } + get { return this.FindContainer(); } } public override bool ParticipatesInGroundCombat @@ -66,4 +66,13 @@ public override void Place(ISpaceObject target) } public override bool FillsCombatTile => false; + + /// + /// Mines, unlike other vehicles, do detonate when enemies enter their sector. + /// + public override bool DetonatesWhenEnemiesEnterSector => true; + + public bool CanInvadeAndPoliceColonies => false; + + public bool CanFireIntoSpaceFromPlanetaryCargo => false; } diff --git a/FrEee.Core.Domain/Objects/Vehicles/Satellite.cs b/FrEee.Vehicles/Types/Satellite.cs similarity index 87% rename from FrEee.Core.Domain/Objects/Vehicles/Satellite.cs rename to FrEee.Vehicles/Types/Satellite.cs index 760f662a..9e8833a9 100644 --- a/FrEee.Core.Domain/Objects/Vehicles/Satellite.cs +++ b/FrEee.Vehicles/Types/Satellite.cs @@ -7,7 +7,7 @@ using FrEee.Processes.Combat; using FrEee.Modding.Abilities; -namespace FrEee.Objects.Vehicles; +namespace FrEee.Vehicles.Types; [Serializable] public class Satellite : SpaceVehicle, IUnit @@ -24,7 +24,7 @@ public override bool CanWarp ICargoContainer IContainable.Container { - get { return CommonExtensions.FindContainer(this); } + get { return this.FindContainer(); } } public override bool ParticipatesInGroundCombat @@ -62,4 +62,8 @@ public override void Place(ISpaceObject target) } public override bool FillsCombatTile => false; -} + + public bool CanInvadeAndPoliceColonies => false; + + public bool CanFireIntoSpaceFromPlanetaryCargo => false; +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Objects/Vehicles/Ship.cs b/FrEee.Vehicles/Types/Ship.cs similarity index 94% rename from FrEee.Core.Domain/Objects/Vehicles/Ship.cs rename to FrEee.Vehicles/Types/Ship.cs index 6763ec1b..cb5f922b 100644 --- a/FrEee.Core.Domain/Objects/Vehicles/Ship.cs +++ b/FrEee.Vehicles/Types/Ship.cs @@ -2,7 +2,7 @@ using FrEee.Processes.Combat; using System; -namespace FrEee.Objects.Vehicles; +namespace FrEee.Vehicles.Types; [Serializable] public class Ship : MajorSpaceVehicle diff --git a/FrEee.Core.Domain/Objects/Vehicles/SpaceVehicle.cs b/FrEee.Vehicles/Types/SpaceVehicle.cs similarity index 96% rename from FrEee.Core.Domain/Objects/Vehicles/SpaceVehicle.cs rename to FrEee.Vehicles/Types/SpaceVehicle.cs index baa34a30..46ed34db 100644 --- a/FrEee.Core.Domain/Objects/Vehicles/SpaceVehicle.cs +++ b/FrEee.Vehicles/Types/SpaceVehicle.cs @@ -11,16 +11,17 @@ using FrEee.Objects.GameState; using FrEee.Modding.Abilities; -namespace FrEee.Objects.Vehicles; +namespace FrEee.Vehicles.Types; /// /// A vehicle which operates in space. /// /// [Serializable] -public abstract class SpaceVehicle : Vehicle, IMobileSpaceObject +public abstract class SpaceVehicle + : Vehicle, ISpaceVehicle { - public SpaceVehicle() + protected SpaceVehicle() { Orders = new List(); StoredResources = new ResourceQuantity(); @@ -255,7 +256,7 @@ public int SupplyStorage /// public double TimePerMove { - get { return 1.0 / (double)StrategicSpeed; } + get { return 1.0 / StrategicSpeed; } } /// @@ -274,7 +275,7 @@ public void AddOrder(IOrder order) { if (!(order is IOrder)) throw new Exception("Can't add a " + order.GetType() + " to a space vehicle's orders."); - Orders.Add((IOrder)order); + Orders.Add(order); } /// @@ -307,7 +308,7 @@ public override void Dispose() public bool ExecuteOrders() { - return this.ExecuteMobileSpaceObjectOrders(); + return this.ExecuteMobileSpaceObjectOrders(); } public override bool IsObsoleteMemory(Empire emp) @@ -321,7 +322,7 @@ public void RearrangeOrder(IOrder order, int delta) { if (order != null && !(order is IOrder)) throw new Exception("Can't rearrange a " + order.GetType() + " in a space vehicle's orders."); - var o = (IOrder)order; + var o = order; var newpos = Orders.IndexOf(o) + delta; Orders.Remove(o); if (newpos < 0) @@ -357,7 +358,7 @@ public void RemoveOrder(IOrder order) { if (order != null && !(order is IOrder)) return; // order can't exist here anyway - Orders.Remove((IOrder)order); + Orders.Remove(order); } /// diff --git a/FrEee.Core.Domain/Objects/Vehicles/Troop.cs b/FrEee.Vehicles/Types/Troop.cs similarity index 91% rename from FrEee.Core.Domain/Objects/Vehicles/Troop.cs rename to FrEee.Vehicles/Types/Troop.cs index 328a74dc..e7167ce1 100644 --- a/FrEee.Core.Domain/Objects/Vehicles/Troop.cs +++ b/FrEee.Vehicles/Types/Troop.cs @@ -10,7 +10,7 @@ using FrEee.Processes.Combat; using FrEee.Modding.Abilities; -namespace FrEee.Objects.Vehicles; +namespace FrEee.Vehicles.Types; [Serializable] public class Troop : Vehicle, IUnit @@ -27,7 +27,7 @@ public ICargoContainer Container { get { - return CommonExtensions.FindContainer(this); + return this.FindContainer(); } } @@ -110,8 +110,12 @@ public override void Place(ISpaceObject target) if (cc2.AddUnit(this)) return; } - target.Owner.Log.Add(this.CreateLogMessage(this + " could not be placed in cargo at " + target + " because there is not enough cargo space available.", LogMessages.LogMessageType.Generic)); + target.Owner.Log.Add(this.CreateLogMessage(this + " could not be placed in cargo at " + target + " because there is not enough cargo space available.", Objects.LogMessages.LogMessageType.Generic)); } public override bool FillsCombatTile => false; + + public bool CanInvadeAndPoliceColonies => true; + + public bool CanFireIntoSpaceFromPlanetaryCargo => false; } \ No newline at end of file diff --git a/FrEee.Core.Domain/Objects/Vehicles/WeaponPlatform.cs b/FrEee.Vehicles/Types/WeaponPlatform.cs similarity index 92% rename from FrEee.Core.Domain/Objects/Vehicles/WeaponPlatform.cs rename to FrEee.Vehicles/Types/WeaponPlatform.cs index eb2a0ae6..cef3fdce 100644 --- a/FrEee.Core.Domain/Objects/Vehicles/WeaponPlatform.cs +++ b/FrEee.Vehicles/Types/WeaponPlatform.cs @@ -9,7 +9,7 @@ using FrEee.Processes.Combat; using FrEee.Modding.Abilities; -namespace FrEee.Objects.Vehicles; +namespace FrEee.Vehicles.Types; [Serializable] public class WeaponPlatform : Vehicle, IUnit @@ -23,7 +23,7 @@ public override AbilityTargets AbilityTarget public ICargoContainer Container { - get { return CommonExtensions.FindContainer(this); } + get { return this.FindContainer(); } } public override int MaxTargets => int.MaxValue; @@ -98,4 +98,8 @@ public override void Place(ISpaceObject target) } public override bool FillsCombatTile => false; + + public bool CanInvadeAndPoliceColonies => false; + + public bool CanFireIntoSpaceFromPlanetaryCargo => true; } \ No newline at end of file diff --git a/FrEee.Core.Domain/Objects/Vehicles/Vehicle.cs b/FrEee.Vehicles/Vehicle.cs similarity index 96% rename from FrEee.Core.Domain/Objects/Vehicles/Vehicle.cs rename to FrEee.Vehicles/Vehicle.cs index 53803386..0a612fce 100644 --- a/FrEee.Core.Domain/Objects/Vehicles/Vehicle.cs +++ b/FrEee.Vehicles/Vehicle.cs @@ -15,8 +15,9 @@ using FrEee.Objects.Civilization.CargoStorage; using FrEee.Processes.Combat; using FrEee.Modding.Abilities; +using FrEee.Vehicles.Types; -namespace FrEee.Objects.Vehicles; +namespace FrEee.Vehicles; /// /// A ship, base, or unit. @@ -144,9 +145,6 @@ public SafeDictionary> Damage [SerializationPriority(1)] public IDesign Design { get; set; } - /// - /// Emergency speed generated by activated emergency propulsion components. Only available for one turn. - /// [DoNotSerialize] public int EmergencySpeed { get; set; } @@ -282,12 +280,12 @@ public ResourceQuantity MaintenanceCost if (pct > 0) { if (Sector != null) - pct -= this.Sector.GetEmpireAbilityValue(Owner, "Reduced Maintenance Cost - Sector").ToInt(); + pct -= Sector.GetEmpireAbilityValue(Owner, "Reduced Maintenance Cost - Sector").ToInt(); if (StarSystem != null) - pct -= this.StarSystem.GetEmpireAbilityValue(Owner, "Reduced Maintenance Cost - System").ToInt(); + pct -= StarSystem.GetEmpireAbilityValue(Owner, "Reduced Maintenance Cost - System").ToInt(); if (Owner != null) { - pct -= this.Owner.GetAbilityValue("Reduced Maintenance Cost - Empire").ToInt(); + pct -= Owner.GetAbilityValue("Reduced Maintenance Cost - Empire").ToInt(); pct -= Owner.Culture.MaintenanceReduction; if (Owner.PrimaryRace.Aptitudes.ContainsKey(Aptitude.Maintenance.Name)) pct -= Owner.PrimaryRace.Aptitudes[Aptitude.Maintenance.Name] - 100; @@ -525,7 +523,7 @@ public int ShieldPercentageModifiers { // TODO: make these multiplicative, at least some of them? return - + Sector.GetEmpireAbilityValue(Owner, "Shield Modifier - Sector").ToInt() + +Sector.GetEmpireAbilityValue(Owner, "Shield Modifier - Sector").ToInt() + StarSystem.GetEmpireAbilityValue(Owner, "Shield Modifier - System").ToInt() + Owner.GetAbilityValue("Shield Modifier - Empire").ToInt(); } @@ -643,7 +641,7 @@ public virtual void Redact(Empire emp) if (Design.CheckVisibility(emp) < Visibility.Scanned) { // create fake design - var d = Vehicles.Design.Create(Design.VehicleType); + var d = DIRoot.Designs.Build(Design.VehicleType); d.Hull = Design.Hull; d.Owner = Design.Owner; Design = d; @@ -681,7 +679,7 @@ public virtual void Redact(Empire emp) { // repair most-damaged components first // TODO - other repair priorities - foreach (var comp in Components.Where(x => x.Hitpoints < x.MaxHitpoints).OrderBy(c => (double)c.Hitpoints / (double)c.MaxHitpoints)) + foreach (var comp in Components.Where(x => x.Hitpoints < x.MaxHitpoints).OrderBy(c => c.Hitpoints / (double)c.MaxHitpoints)) { if (amount <= 0) break; @@ -783,4 +781,9 @@ public override string ToString() IEnumerable ICombatant.Components => Components; public abstract bool FillsCombatTile { get; } + + /// + /// By default, vehicles don't detonate when enemies enter their sector. + /// + public virtual bool DetonatesWhenEnemiesEnterSector => false; } diff --git a/FrEee.Vehicles/VehicleFactory.cs b/FrEee.Vehicles/VehicleFactory.cs new file mode 100644 index 00000000..67df17e1 --- /dev/null +++ b/FrEee.Vehicles/VehicleFactory.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Vehicles.Types; + +namespace FrEee.Vehicles; +public class VehicleFactory + : IVehicleFactory +{ + public IVehicle Build(VehicleTypes vehicleType) + { + return vehicleType switch + { + VehicleTypes.Ship => new Ship(), + VehicleTypes.Base => new Base(), + VehicleTypes.Fighter => new Fighter(), + VehicleTypes.Satellite => new Satellite(), + VehicleTypes.Troop => new Troop(), + VehicleTypes.WeaponPlatform => new WeaponPlatform(), + VehicleTypes.Mine => new Mine(), + VehicleTypes.Drone => new Drone(), + var x => throw new NotSupportedException($"Can't build a vehicle of type {x}. Only single vehicle types can be built."), + }; + } +} diff --git a/FrEee.sln b/FrEee.sln index 8a2f36e7..b9d9a28f 100644 --- a/FrEee.sln +++ b/FrEee.sln @@ -28,6 +28,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FrEee.Root", "FrEee.Root\Fr EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FrEee.Gameplay", "FrEee.Gameplay\FrEee.Gameplay.csproj", "{B79ED9FD-82A2-4806-80EC-CD505CD4A2DC}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FrEee.Vehicles", "FrEee.Vehicles\FrEee.Vehicles.csproj", "{A048D0D7-7ECE-4FCD-856A-A56A1644104A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -146,6 +148,18 @@ Global {B79ED9FD-82A2-4806-80EC-CD505CD4A2DC}.Release|x64.Build.0 = Release|Any CPU {B79ED9FD-82A2-4806-80EC-CD505CD4A2DC}.Release|x86.ActiveCfg = Release|Any CPU {B79ED9FD-82A2-4806-80EC-CD505CD4A2DC}.Release|x86.Build.0 = Release|Any CPU + {A048D0D7-7ECE-4FCD-856A-A56A1644104A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A048D0D7-7ECE-4FCD-856A-A56A1644104A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A048D0D7-7ECE-4FCD-856A-A56A1644104A}.Debug|x64.ActiveCfg = Debug|Any CPU + {A048D0D7-7ECE-4FCD-856A-A56A1644104A}.Debug|x64.Build.0 = Debug|Any CPU + {A048D0D7-7ECE-4FCD-856A-A56A1644104A}.Debug|x86.ActiveCfg = Debug|Any CPU + {A048D0D7-7ECE-4FCD-856A-A56A1644104A}.Debug|x86.Build.0 = Debug|Any CPU + {A048D0D7-7ECE-4FCD-856A-A56A1644104A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A048D0D7-7ECE-4FCD-856A-A56A1644104A}.Release|Any CPU.Build.0 = Release|Any CPU + {A048D0D7-7ECE-4FCD-856A-A56A1644104A}.Release|x64.ActiveCfg = Release|Any CPU + {A048D0D7-7ECE-4FCD-856A-A56A1644104A}.Release|x64.Build.0 = Release|Any CPU + {A048D0D7-7ECE-4FCD-856A-A56A1644104A}.Release|x86.ActiveCfg = Release|Any CPU + {A048D0D7-7ECE-4FCD-856A-A56A1644104A}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE