diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index b4332d02..14e0e436 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -60,7 +60,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v1
with:
- dotnet-version: 9.x
+ dotnet-version: 10.x
- name: Install dependencies
run: dotnet restore
- name: Build
diff --git a/.github/workflows/dotnet-core.yml b/.github/workflows/dotnet-core.yml
index 6ea3e561..e4aab27d 100644
--- a/.github/workflows/dotnet-core.yml
+++ b/.github/workflows/dotnet-core.yml
@@ -16,7 +16,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v1
with:
- dotnet-version: 9.x
+ dotnet-version: 10.x
- name: Install dependencies
run: dotnet restore
- name: Build
diff --git a/.github/workflows/release-creator.yml b/.github/workflows/release-creator.yml
index 9f29e313..4ad2e269 100644
--- a/.github/workflows/release-creator.yml
+++ b/.github/workflows/release-creator.yml
@@ -16,7 +16,7 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
- dotnet-version: 9.x
+ dotnet-version: 10.x
- name: Install dependencies
run: dotnet restore
- name: Build
diff --git a/.github/workflows/sonarscan.yml b/.github/workflows/sonarscan.yml
index b0951504..a72c3636 100644
--- a/.github/workflows/sonarscan.yml
+++ b/.github/workflows/sonarscan.yml
@@ -19,7 +19,7 @@ jobs:
- name: Set up .NET Core
uses: actions/setup-dotnet@v1
with:
- dotnet-version: 9.x
+ dotnet-version: 10.x
- name: Set up dotnet coverage
shell: bash
run: |
@@ -51,8 +51,8 @@ jobs:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
shell: bash
run: |
- dotnet-sonarscanner begin /k:"Sofistico_MagiRogue" /o:"sofistico" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.vscoveragexml.reportsPaths=coverage.xml
+ dotnet-sonarscanner begin /k:"Sofistico_MagiRogue" /o:"sofistico" /d:sonar.login="$SONAR_TOKEN" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.vscoveragexml.reportsPaths=coverage.xml
dotnet restore
dotnet build --configuration Release --no-restore
dotnet-coverage collect 'dotnet test' -f xml -o 'coverage.xml'
- dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}"
+ dotnet-sonarscanner end /d:sonar.login="$SONAR_TOKEN"
diff --git a/.vscode/launch.json b/.vscode/launch.json
index c5a5df84..bbd7d4b7 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -9,7 +9,7 @@
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
- "program": "${workspaceFolder}/src/MagiRogue/bin/Debug/net9.0/MagiRogue.dll",
+ "program": "${workspaceFolder}/src/MagiRogue/bin/Debug/net10.0/MagiRogue.dll",
"args": [],
"cwd": "${workspaceFolder}/src/MagiRogue",
"console": "internalConsole",
@@ -20,7 +20,7 @@
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
- "program": "${workspaceFolder}/src/MagiRogue/bin/Debug/net9.0/MagiRogue.dll",
+ "program": "${workspaceFolder}/src/MagiRogue/bin/Debug/net10.0/MagiRogue.dll",
"args": ["test"],
"cwd": "${workspaceFolder}/src/MagiRogue",
"console": "internalConsole",
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 6127a781..d57b9182 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -7,7 +7,7 @@
"type": "process",
"args": [
"build",
- "${workspaceFolder}/MagiRogue.sln",
+ "${workspaceFolder}/MagiRogue.slnx",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary;ForceNoAlign"
],
@@ -19,7 +19,7 @@
"type": "process",
"args": [
"publish",
- "${workspaceFolder}/MagiRogue.sln",
+ "${workspaceFolder}/MagiRogue.slnx",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary;ForceNoAlign"
],
@@ -38,4 +38,4 @@
"problemMatcher": "$msCompile"
}
]
-}
\ No newline at end of file
+}
diff --git a/MagiRogue.sln b/MagiRogue.sln
deleted file mode 100644
index 149037b0..00000000
--- a/MagiRogue.sln
+++ /dev/null
@@ -1,95 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.3.32922.545
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "src\MagiRogue", "src\MagiRogue\MagiRogue.csproj", "{07446F58-66E1-4B55-84FB-70C67E6E0BC8}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "src\MagiRogue.Test", "src\MagiRogue.Test\MagiRogue.Test.csproj", "{16CADFB2-73B0-4322-B266-0527B9A12B49}"
- ProjectSection(ProjectDependencies) = postProject
- {07446F58-66E1-4B55-84FB-70C67E6E0BC8} = {07446F58-66E1-4B55-84FB-70C67E6E0BC8}
- EndProjectSection
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "src\MagiRogue.LegendsConsoleViewer", "src\MagiRogue.LegendsConsoleViewer\MagiRogue.LegendsConsoleViewer.csproj", "{6AA2F259-2D24-4663-B56B-242700954B45}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "1 - Game", "1 - Game", "{8454D3F7-7624-4B8C-BD1D-BBFF955E8251}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2 - Tools", "2 - Tools", "{6EEDFB15-2116-49D2-B091-CF68027EC580}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3 - Test", "3 - Test", "{CEC24325-48A3-475C-B109-92CA2C13C327}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "src\MagiRogue.Benchmarks", "src\MagiRogue.Benchmarks\MagiRogue.Benchmarks.csproj", "{ABB63633-6A69-4AB2-AC9B-A81B0D6D5C48}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "1.2 - Engine", "1.2 - Engine", "{3CD9D6CB-0811-4B61-AE22-01682A8C1BBA}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "1.3 - Render", "1.3 - Render", "{F2FC3775-ED52-48AA-A445-F047A661CDEA}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "1.1 - Data", "1.1 - Data", "{D827073E-B105-43FF-B31F-562E0D027FF7}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "src\MagusEngine", "src\MagusEngine\MagusEngine.csproj", "{EAEC4804-2679-4AF4-9950-603FCD26637B}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "src\Diviner", "src\Diviner\Diviner.csproj", "{97163240-F09C-4D10-AD6C-C0B5EECA8AF3}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "src\Arquimedes", "src\Arquimedes\Arquimedes.csproj", "{080269A8-61A1-4BC4-BE3F-97783290A92A}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "src\AccidentalNoiseLibrary", "src\AccidentalNoiseLibrary\AccidentalNoiseLibrary.csproj", "{7035D27D-B870-4D0F-8FAC-3B3C2682B5DA}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {07446F58-66E1-4B55-84FB-70C67E6E0BC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {07446F58-66E1-4B55-84FB-70C67E6E0BC8}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {07446F58-66E1-4B55-84FB-70C67E6E0BC8}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {07446F58-66E1-4B55-84FB-70C67E6E0BC8}.Release|Any CPU.Build.0 = Release|Any CPU
- {16CADFB2-73B0-4322-B266-0527B9A12B49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {16CADFB2-73B0-4322-B266-0527B9A12B49}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {16CADFB2-73B0-4322-B266-0527B9A12B49}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {16CADFB2-73B0-4322-B266-0527B9A12B49}.Release|Any CPU.Build.0 = Release|Any CPU
- {6AA2F259-2D24-4663-B56B-242700954B45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {6AA2F259-2D24-4663-B56B-242700954B45}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {6AA2F259-2D24-4663-B56B-242700954B45}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {6AA2F259-2D24-4663-B56B-242700954B45}.Release|Any CPU.Build.0 = Release|Any CPU
- {ABB63633-6A69-4AB2-AC9B-A81B0D6D5C48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {ABB63633-6A69-4AB2-AC9B-A81B0D6D5C48}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {ABB63633-6A69-4AB2-AC9B-A81B0D6D5C48}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {ABB63633-6A69-4AB2-AC9B-A81B0D6D5C48}.Release|Any CPU.Build.0 = Release|Any CPU
- {EAEC4804-2679-4AF4-9950-603FCD26637B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {EAEC4804-2679-4AF4-9950-603FCD26637B}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {EAEC4804-2679-4AF4-9950-603FCD26637B}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {EAEC4804-2679-4AF4-9950-603FCD26637B}.Release|Any CPU.Build.0 = Release|Any CPU
- {97163240-F09C-4D10-AD6C-C0B5EECA8AF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {97163240-F09C-4D10-AD6C-C0B5EECA8AF3}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {97163240-F09C-4D10-AD6C-C0B5EECA8AF3}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {97163240-F09C-4D10-AD6C-C0B5EECA8AF3}.Release|Any CPU.Build.0 = Release|Any CPU
- {080269A8-61A1-4BC4-BE3F-97783290A92A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {080269A8-61A1-4BC4-BE3F-97783290A92A}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {080269A8-61A1-4BC4-BE3F-97783290A92A}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {080269A8-61A1-4BC4-BE3F-97783290A92A}.Release|Any CPU.Build.0 = Release|Any CPU
- {7035D27D-B870-4D0F-8FAC-3B3C2682B5DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {7035D27D-B870-4D0F-8FAC-3B3C2682B5DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {7035D27D-B870-4D0F-8FAC-3B3C2682B5DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {7035D27D-B870-4D0F-8FAC-3B3C2682B5DA}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(NestedProjects) = preSolution
- {07446F58-66E1-4B55-84FB-70C67E6E0BC8} = {8454D3F7-7624-4B8C-BD1D-BBFF955E8251}
- {16CADFB2-73B0-4322-B266-0527B9A12B49} = {CEC24325-48A3-475C-B109-92CA2C13C327}
- {6AA2F259-2D24-4663-B56B-242700954B45} = {6EEDFB15-2116-49D2-B091-CF68027EC580}
- {ABB63633-6A69-4AB2-AC9B-A81B0D6D5C48} = {6EEDFB15-2116-49D2-B091-CF68027EC580}
- {3CD9D6CB-0811-4B61-AE22-01682A8C1BBA} = {8454D3F7-7624-4B8C-BD1D-BBFF955E8251}
- {F2FC3775-ED52-48AA-A445-F047A661CDEA} = {8454D3F7-7624-4B8C-BD1D-BBFF955E8251}
- {D827073E-B105-43FF-B31F-562E0D027FF7} = {8454D3F7-7624-4B8C-BD1D-BBFF955E8251}
- {EAEC4804-2679-4AF4-9950-603FCD26637B} = {3CD9D6CB-0811-4B61-AE22-01682A8C1BBA}
- {97163240-F09C-4D10-AD6C-C0B5EECA8AF3} = {F2FC3775-ED52-48AA-A445-F047A661CDEA}
- {080269A8-61A1-4BC4-BE3F-97783290A92A} = {D827073E-B105-43FF-B31F-562E0D027FF7}
- {7035D27D-B870-4D0F-8FAC-3B3C2682B5DA} = {D827073E-B105-43FF-B31F-562E0D027FF7}
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {2FE90E55-E44A-4EF3-9614-020E1112F28A}
- EndGlobalSection
-EndGlobal
diff --git a/MagiRogue.slnx b/MagiRogue.slnx
new file mode 100644
index 00000000..4218a2b2
--- /dev/null
+++ b/MagiRogue.slnx
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 00000000..343d04a0
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,8 @@
+build:
+ dotnet build
+
+run:
+ dotnet run --project ./src/MagiRogue -- test
+
+watch:
+ dotnet watch --project ./src/MagiRogue
diff --git a/README.md b/README.md
index 0a38fc78..40c97930 100644
--- a/README.md
+++ b/README.md
@@ -19,5 +19,3 @@ The game also includes a coven of wizards, with deep master-apprentice relations
As you progress through the game, you can play as an apprentice, honing your magical skills and climbing the ranks to become a powerful archmage. Alternatively, you can choose to abandon magic altogether and live as a common person, or even strive to become a god. The possibilities are endless in MagiRogue, and the choices you make will have a profound impact on your journey through the game.
-
-
diff --git a/build.cmd b/build.cmd
deleted file mode 100644
index 6b11cb56..00000000
--- a/build.cmd
+++ /dev/null
@@ -1 +0,0 @@
-dotnet build
diff --git a/run.cmd b/run.cmd
deleted file mode 100644
index 0fd9a4eb..00000000
--- a/run.cmd
+++ /dev/null
@@ -1 +0,0 @@
-dotnet run --project ./src/MagiRogue -- test
diff --git a/src/AccidentalNoiseLibrary/AccidentalNoiseLibrary.csproj b/src/AccidentalNoiseLibrary/AccidentalNoiseLibrary.csproj
index 125f4c93..b7601447 100644
--- a/src/AccidentalNoiseLibrary/AccidentalNoiseLibrary.csproj
+++ b/src/AccidentalNoiseLibrary/AccidentalNoiseLibrary.csproj
@@ -1,7 +1,7 @@
- net9.0
+ net10.0
enable
enable
diff --git a/src/Arquimedes/Arquimedes.csproj b/src/Arquimedes/Arquimedes.csproj
index 7b019bfc..63ec7a1f 100644
--- a/src/Arquimedes/Arquimedes.csproj
+++ b/src/Arquimedes/Arquimedes.csproj
@@ -1,14 +1,14 @@
-
+
- net9.0
+ net10.0
enable
enable
-
-
+
+
diff --git a/src/Arquimedes/Data/Materials/material_body.json b/src/Arquimedes/Data/Materials/material_body.json
index 7c1f83bf..6fbafb2c 100644
--- a/src/Arquimedes/Data/Materials/material_body.json
+++ b/src/Arquimedes/Data/Materials/material_body.json
@@ -12,12 +12,12 @@
"ColdDamageTemp": -56,
"Color": "Gray",
"Type": "Skin",
- "ShearYield": 20000,
- "ShearFracture": 20000,
- "ShearStrainAtYield": 50000,
- "ImpactYield": 10000,
- "ImpactFracture": 10000,
- "ImpactStrainsAtYield": 50000
+ "ShearYield": 1000,
+ "ShearFracture": 2000,
+ "ShearStrainAtYield": 25000,
+ "ImpactYield": 500,
+ "ImpactFracture": 1000,
+ "ImpactStrainsAtYield": 25000
},
{
"Id": "fat",
@@ -53,12 +53,12 @@
"ColdDamageTemp": -56,
"Color": "Red",
"Type": "Meat",
- "ShearYield": 10000,
- "ShearFracture": 10000,
- "ShearStrainAtYield": 50000,
- "ImpactYield": 10000,
- "ImpactFracture": 10000,
- "ImpactStrainsAtYield": 50000
+ "ShearYield": 800,
+ "ShearFracture": 1500,
+ "ShearStrainAtYield": 30000,
+ "ImpactYield": 400,
+ "ImpactFracture": 800,
+ "ImpactStrainsAtYield": 30000
},
{
"Id": "bone",
@@ -73,12 +73,12 @@
"Density": 0.5,
"Color": "White",
"Type": "Bone",
- "ShearYield": 115000,
- "ShearFracture": 130000,
- "ShearStrainAtYield": 100,
- "ImpactYield": 20000,
- "ImpactFracture": 20000,
- "ImpactStrainsAtYield": 100,
+ "ShearYield": 50000,
+ "ShearFracture": 80000,
+ "ShearStrainAtYield": 5000,
+ "ImpactYield": 15000,
+ "ImpactFracture": 25000,
+ "ImpactStrainsAtYield": 5000,
"MaxEdge": 100
},
{
@@ -95,7 +95,6 @@
"Density": 0.6,
"Color": "White",
"Type": "Teeth",
- // same from bone
"MaxEdge": 1000
},
{
@@ -191,7 +190,6 @@
"Type": "None"
},
{
- // todo: Fix these values
"Id": "hair",
"Name": "hair material",
"InheirtFrom": "skin",
@@ -203,7 +201,6 @@
"Type": "None"
},
{
- // TODO: to fix this layer
"Id": "cartilage",
"Name": "cartilage material",
"InheirtFrom": "skin",
@@ -258,7 +255,6 @@
"Density": 0.5,
"Color": "Gray",
"Type": "Bone",
- // more elastic than bone
"ImpactYield": 200000,
"ImpactFracture": 200000,
"ImpactStrainsAtYield": 5000,
diff --git a/src/Arquimedes/Data/Materials/material_metals.json b/src/Arquimedes/Data/Materials/material_metals.json
index e16f5f66..902faa32 100644
--- a/src/Arquimedes/Data/Materials/material_metals.json
+++ b/src/Arquimedes/Data/Materials/material_metals.json
@@ -8,12 +8,12 @@
"MeltingPoint": 1538,
"BoilingPoint": 2862,
"ConfersTraits": [ "Durable", "MagicallyWeak" ],
- "ShearYield": 15000,
- "ShearFracture": 15000,
- "ShearStrainAtYield": 100,
- "ImpactYield": 120000,
- "ImpactFracture": 120000,
- "ImpactStrainsAtYield": 100,
+ "ShearYield": 80000,
+ "ShearFracture": 120000,
+ "ShearStrainAtYield": 1000,
+ "ImpactYield": 200000,
+ "ImpactFracture": 300000,
+ "ImpactStrainsAtYield": 1000,
"MaxEdge": 1000
},
{
diff --git a/src/Arquimedes/Enumerators/KeymapAction.cs b/src/Arquimedes/Enumerators/KeymapAction.cs
new file mode 100644
index 00000000..8cd01a9d
--- /dev/null
+++ b/src/Arquimedes/Enumerators/KeymapAction.cs
@@ -0,0 +1,36 @@
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+
+namespace Arquimedes.Enumerators
+{
+ [JsonConverter(typeof(StringEnumConverter))]
+ public enum KeymapAction
+ {
+ MoveNorth,
+ MoveSouth,
+ MoveLeft,
+ MoveRight,
+ MoveNorthLeft,
+ MoveNorthRight,
+ MoveSouthLeft,
+ MoveSouthRight,
+ MoveUp,
+ MoveDown,
+ OpenInventory,
+ ThownItem,
+ EscapeMenu,
+ WaitTillRested,
+ WaitOneSecond,
+ WaitOneMoment,
+ PickUp,
+ DropItem,
+ CloseDoor,
+ OpenDoor,
+ Look,
+ SpellCasting,
+ WaitScreen,
+ ConfirmAction,
+ CancelAction,
+ Interact
+ }
+}
diff --git a/src/Arquimedes/Enumerators/WindowTag.cs b/src/Arquimedes/Enumerators/WindowTag.cs
index e7bf6287..d52cf624 100644
--- a/src/Arquimedes/Enumerators/WindowTag.cs
+++ b/src/Arquimedes/Enumerators/WindowTag.cs
@@ -8,5 +8,7 @@ public enum WindowTag
Status,
Wait,
Look,
+ Inv,
+ SpellCasting,
}
}
diff --git a/src/Arquimedes/MagiPalette.cs b/src/Arquimedes/MagiPalette.cs
index 51e8312d..c078ddf2 100644
--- a/src/Arquimedes/MagiPalette.cs
+++ b/src/Arquimedes/MagiPalette.cs
@@ -1,5 +1,4 @@
-using SadConsole.UI;
-using SadRogue.Primitives;
+using SadRogue.Primitives;
namespace Arquimedes
{
@@ -8,7 +7,7 @@ public static class MagiPalette
// Height Map Colors
public static readonly Color DeepWaterColor = new(0, 0, 0.5f, 1);
public static readonly Color ShallowWaterColor = new(25 / 255f, 25 / 255f, 150 / 255f, 1);
- public static readonly Color RiverColor = new Color(30 / 255f, 120 / 255f, 200 / 255f, 1);
+ public static readonly Color RiverColor = new(30 / 255f, 120 / 255f, 200 / 255f, 1);
public static readonly Color SandColor = new(240 / 255f, 240 / 255f, 64 / 255f, 1);
public static readonly Color GrassColor = new(50 / 255f, 220 / 255f, 20 / 255f, 1);
public static readonly Color ForestColor = new(16 / 255f, 160 / 255f, 0, 1);
@@ -18,42 +17,42 @@ public static class MagiPalette
public static readonly Color MagicColor = Color.Purple;
// Heat Map Colors
- public static readonly Color Coldest = new Color(0, 1, 1, 1);
- public static readonly Color Colder = new Color(170 / 255f, 1, 1, 1);
- public static readonly Color Cold = new Color(0, 229 / 255f, 133 / 255f, 1);
- public static readonly Color Warm = new Color(1, 1, 100 / 255f, 1);
- public static readonly Color Warmer = new Color(1, 100 / 255f, 0, 1);
- public static readonly Color Warmest = new Color(241 / 255f, 12 / 255f, 0, 1);
+ public static readonly Color Coldest = new(0, 1, 1, 1);
+ public static readonly Color Colder = new(170 / 255f, 1, 1, 1);
+ public static readonly Color Cold = new(0, 229 / 255f, 133 / 255f, 1);
+ public static readonly Color Warm = new(1, 1, 100 / 255f, 1);
+ public static readonly Color Warmer = new(1, 100 / 255f, 0, 1);
+ public static readonly Color Warmest = new(241 / 255f, 12 / 255f, 0, 1);
//Moisture map
- public static readonly Color Dryest = new Color(255 / 255f, 139 / 255f, 17 / 255f, 1);
- public static readonly Color Dryer = new Color(245 / 255f, 245 / 255f, 23 / 255f, 1);
- public static readonly Color Dry = new Color(80 / 255f, 255 / 255f, 0 / 255f, 1);
- public static readonly Color Wet = new Color(85 / 255f, 255 / 255f, 255 / 255f, 1);
- public static readonly Color Wetter = new Color(20 / 255f, 70 / 255f, 255 / 255f, 1);
- public static readonly Color Wettest = new Color(0 / 255f, 0 / 255f, 100 / 255f, 1);
+ public static readonly Color Dryest = new(255 / 255f, 139 / 255f, 17 / 255f, 1);
+ public static readonly Color Dryer = new(245 / 255f, 245 / 255f, 23 / 255f, 1);
+ public static readonly Color Dry = new(80 / 255f, 255 / 255f, 0 / 255f, 1);
+ public static readonly Color Wet = new(85 / 255f, 255 / 255f, 255 / 255f, 1);
+ public static readonly Color Wetter = new(20 / 255f, 70 / 255f, 255 / 255f, 1);
+ public static readonly Color Wettest = new(0 / 255f, 0 / 255f, 100 / 255f, 1);
- public static readonly Color IceWater = new Color(210 / 255f, 255 / 255f, 252 / 255f, 1);
- public static readonly Color ColdWater = new Color(119 / 255f, 156 / 255f, 213 / 255f, 1);
- public static readonly Color RiverWater = new Color(65 / 255f, 110 / 255f, 179 / 255f, 1);
+ public static readonly Color IceWater = new(210 / 255f, 255 / 255f, 252 / 255f, 1);
+ public static readonly Color ColdWater = new(119 / 255f, 156 / 255f, 213 / 255f, 1);
+ public static readonly Color RiverWater = new(65 / 255f, 110 / 255f, 179 / 255f, 1);
//biome map
public static readonly Color Ice = Color.White;
- public static readonly Color Desert = new Color(238 / 255f, 218 / 255f, 130 / 255f, 1);
- public static readonly Color Savanna = new Color(177 / 255f, 209 / 255f, 110 / 255f, 1);
- public static readonly Color TropicalRainforest = new Color(66 / 255f, 123 / 255f, 25 / 255f, 1);
- public static readonly Color Tundra = new Color(96 / 255f, 131 / 255f, 112 / 255f, 1);
- public static readonly Color TemperateRainforest = new Color(29 / 255f, 73 / 255f, 40 / 255f, 1);
- public static readonly Color Grassland = new Color(164 / 255f, 225 / 255f, 99 / 255f, 1);
- public static readonly Color SeasonalForest = new Color(73 / 255f, 100 / 255f, 35 / 255f, 1);
- public static readonly Color BorealForest = new Color(95 / 255f, 115 / 255f, 62 / 255f, 1);
- public static readonly Color Woodland = new Color(139 / 255f, 175 / 255f, 90 / 255f, 1);
-
- public static readonly Color Dirt = new Color(165, 103, 42);
+ public static readonly Color Desert = new(238 / 255f, 218 / 255f, 130 / 255f, 1);
+ public static readonly Color Savanna = new(177 / 255f, 209 / 255f, 110 / 255f, 1);
+ public static readonly Color TropicalRainforest = new(66 / 255f, 123 / 255f, 25 / 255f, 1);
+ public static readonly Color Tundra = new(96 / 255f, 131 / 255f, 112 / 255f, 1);
+ public static readonly Color TemperateRainforest = new(29 / 255f, 73 / 255f, 40 / 255f, 1);
+ public static readonly Color Grassland = new(164 / 255f, 225 / 255f, 99 / 255f, 1);
+ public static readonly Color SeasonalForest = new(73 / 255f, 100 / 255f, 35 / 255f, 1);
+ public static readonly Color BorealForest = new(95 / 255f, 115 / 255f, 62 / 255f, 1);
+ public static readonly Color Woodland = new(139 / 255f, 175 / 255f, 90 / 255f, 1);
+
+ public static readonly Color Dirt = new(165, 103, 42);
public static readonly Color DirtRoad = Color.Brown;
- public static readonly Color Wood = new Color(186, 140, 99);
- public static readonly Color DarkWood = new Color(87, 65, 46);
- public static readonly Color UnclearGlass = new Color(183, 183, 189);
+ public static readonly Color Wood = new(186, 140, 99);
+ public static readonly Color DarkWood = new(87, 65, 46);
+ public static readonly Color UnclearGlass = new(183, 183, 189);
public static readonly Color DarkGrassColor = GrassColor.GetDark();
public static void AddToColorDictionary()
diff --git a/src/Arquimedes/Settings/InputSetting.cs b/src/Arquimedes/Settings/InputSetting.cs
new file mode 100644
index 00000000..695fe0f4
--- /dev/null
+++ b/src/Arquimedes/Settings/InputSetting.cs
@@ -0,0 +1,32 @@
+using Arquimedes.Enumerators;
+
+namespace Arquimedes.Settings
+{
+ public class InputSetting : IEquatable
+ {
+ public required KeymapAction Action { get; set; }
+ public required string[] Keys { get; set; }
+ public string Category { get; set; } = "Misc";
+ public string[]? Modifier { get; set; }
+
+ public bool Equals(InputSetting? other)
+ {
+ if (Action == other?.Action && Category.Equals(other.Category))
+ return true;
+
+ return false;
+ }
+
+ public override bool Equals(object? obj)
+ {
+ if (obj is null)
+ return false;
+ return Equals(obj as InputSetting);
+ }
+
+ public override int GetHashCode()
+ {
+ return HashCode.Combine(Action);
+ }
+ }
+}
diff --git a/src/Arquimedes/Settings/inputs_setting.json b/src/Arquimedes/Settings/inputs_setting.json
new file mode 100644
index 00000000..3814d99b
--- /dev/null
+++ b/src/Arquimedes/Settings/inputs_setting.json
@@ -0,0 +1,127 @@
+[
+ {
+ "Keys": ["up_arrow", "numpad_8"],
+ "Action": "MoveNorth",
+ "Category": "Movement"
+ },
+ {
+ "Keys": ["down_arrow", "numpad_2"],
+ "Action": "MoveSouth",
+ "Category": "Movement"
+ },
+ {
+ "Keys": ["left_arrow", "numpad_4"],
+ "Action": "MoveLeft",
+ "Category": "Movement"
+ },
+ {
+ "Keys": ["right_arrow", "numpad_6"],
+ "Action": "MoveRight",
+ "Category": "Movement"
+ },
+ {
+ "Keys": ["numpad_7"],
+ "Action": "MoveNorthLeft",
+ "Category": "Movement"
+ },
+ {
+ "Keys": ["numpad_9"],
+ "Action": "MoveNorthRight",
+ "Category": "Movement"
+ },
+ {
+ "Keys": ["numpad_1"],
+ "Action": "MoveSouthLeft",
+ "Category": "Movement"
+ },
+ {
+ "Keys": ["numpad_3"],
+ "Action": "MoveSouthRight",
+ "Category": "Movement"
+ },
+ {
+ "Keys": ["i"],
+ "Action": "OpenInventory",
+ "Category": "Ui"
+ },
+ {
+ "Keys": ["t"],
+ "Action": "ThownItem",
+ "Category": "Interaction"
+ },
+ {
+ "Keys": ["esc"],
+ "Action": "EscapeMenu",
+ "Category": "Ui"
+ },
+ {
+ "Keys": ["."],
+ "Action": "MoveDown",
+ "Category": "Movement",
+ "Modifier": ["Shift"]
+ },
+ {
+ "Keys": [","],
+ "Action": "MoveUp",
+ "Category": "Movement",
+ "Modifier": ["Shift"]
+ },
+ {
+ "Keys": ["numpad_5"],
+ "Action": "WaitTillRested",
+ "Category": "Misc",
+ "Modifier": ["Control"]
+ },
+ {
+ "Keys": [".", "numpad_5"],
+ "Action": "WaitOneSecond",
+ "Category": "Misc"
+ },
+ {
+ "Keys": [","],
+ "Action": "WaitOneMoment",
+ "Category": "Misc"
+ },
+ {
+ "Keys": ["g"],
+ "Action": "PickUp",
+ "Category": "Interaction"
+ },
+ {
+ "Keys": ["d"],
+ "Action": "DropItem",
+ "Category": "Interaction"
+ },
+ {
+ "Keys": ["c"],
+ "Action": "CloseDoor",
+ "Category": "Interaction"
+ },
+ {
+ "Keys": ["l"],
+ "Action": "Look",
+ "Category": "Ui"
+ },
+ {
+ "Keys": ["z"],
+ "Action": "SpellCasting",
+ "Category": "Interaction",
+ "Modifier": ["Shift"]
+ },
+ {
+ "Keys": ["r"],
+ "Action": "WaitScreen",
+ "Category": "Ui",
+ "Modifier": ["Shift"]
+ },
+ {
+ "Keys": ["enter"],
+ "Action": "ConfirmAction",
+ "Category": "Ui"
+ },
+ {
+ "Keys": ["esc"],
+ "Action": "CancelAction",
+ "Category": "Ui"
+ }
+]
diff --git a/src/Diviner/Diviner.csproj b/src/Diviner/Diviner.csproj
index 03d9e894..9c6ca5e9 100644
--- a/src/Diviner/Diviner.csproj
+++ b/src/Diviner/Diviner.csproj
@@ -1,15 +1,16 @@
- net9.0
+ net10.0
enable
enable
-
-
+
+
+
diff --git a/src/Diviner/Extensions/KeyboardExtensions.cs b/src/Diviner/Extensions/KeyboardExtensions.cs
new file mode 100644
index 00000000..e9444421
--- /dev/null
+++ b/src/Diviner/Extensions/KeyboardExtensions.cs
@@ -0,0 +1,179 @@
+using Arquimedes.Enumerators;
+using Arquimedes.Settings;
+using MagusEngine;
+using SadConsole.Input;
+
+namespace Diviner.Extensions
+{
+ public static class KeyboardExtensions
+ {
+ private static readonly Dictionary _map = new(StringComparer.OrdinalIgnoreCase)
+ {
+ ["up_arrow"] = Keys.Up,
+ ["down_arrow"] = Keys.Down,
+ ["left_arrow"] = Keys.Left,
+ ["right_arrow"] = Keys.Right,
+ ["up"] = Keys.Up,
+ ["down"] = Keys.Down,
+ ["left"] = Keys.Left,
+ ["right"] = Keys.Right,
+
+ ["enter"] = Keys.Enter,
+ ["return"] = Keys.Enter,
+ ["esc"] = Keys.Escape,
+ ["escape"] = Keys.Escape,
+ ["space"] = Keys.Space,
+ ["spacebar"] = Keys.Space,
+ ["tab"] = Keys.Tab,
+ ["backspace"] = Keys.Back,
+ ["capslock"] = Keys.CapsLock,
+ ["pause"] = Keys.Pause,
+ ["shift"] = Keys.LeftShift,
+ ["left_shift"] = Keys.LeftShift,
+ ["right_shift"] = Keys.RightShift,
+ ["ctrl"] = Keys.LeftControl,
+ ["control"] = Keys.LeftControl,
+ ["left_ctrl"] = Keys.LeftControl,
+ ["right_ctrl"] = Keys.RightControl,
+ ["alt"] = Keys.LeftAlt,
+ ["left_alt"] = Keys.LeftAlt,
+ ["right_alt"] = Keys.RightAlt,
+
+ ["0"] = Keys.D0,
+ ["1"] = Keys.D1,
+ ["2"] = Keys.D2,
+ ["3"] = Keys.D3,
+ ["4"] = Keys.D4,
+ ["5"] = Keys.D5,
+ ["6"] = Keys.D6,
+ ["7"] = Keys.D7,
+ ["8"] = Keys.D8,
+ ["9"] = Keys.D9,
+
+ ["a"] = Keys.A,
+ ["b"] = Keys.B,
+ ["c"] = Keys.C,
+ ["d"] = Keys.D,
+ ["e"] = Keys.E,
+ ["f"] = Keys.F,
+ ["g"] = Keys.G,
+ ["h"] = Keys.H,
+ ["i"] = Keys.I,
+ ["j"] = Keys.J,
+ ["k"] = Keys.K,
+ ["l"] = Keys.L,
+ ["m"] = Keys.M,
+ ["n"] = Keys.N,
+ ["o"] = Keys.O,
+ ["p"] = Keys.P,
+ ["q"] = Keys.Q,
+ ["r"] = Keys.R,
+ ["s"] = Keys.S,
+ ["t"] = Keys.T,
+ ["u"] = Keys.U,
+ ["v"] = Keys.V,
+ ["w"] = Keys.W,
+ ["x"] = Keys.X,
+ ["y"] = Keys.Y,
+ ["z"] = Keys.Z,
+
+ ["numpad_0"] = Keys.NumPad0,
+ ["numpad_1"] = Keys.NumPad1,
+ ["numpad_2"] = Keys.NumPad2,
+ ["numpad_3"] = Keys.NumPad3,
+ ["numpad_4"] = Keys.NumPad4,
+ ["numpad_5"] = Keys.NumPad5,
+ ["numpad_6"] = Keys.NumPad6,
+ ["numpad_7"] = Keys.NumPad7,
+ ["numpad_8"] = Keys.NumPad8,
+ ["numpad_9"] = Keys.NumPad9,
+ ["numpad_add"] = Keys.Add,
+ ["numpad_subtract"] = Keys.Subtract,
+ ["numpad_multiply"] = Keys.Multiply,
+ ["numpad_divide"] = Keys.Divide,
+ ["numpad_decimal"] = Keys.Decimal,
+
+ ["f1"] = Keys.F1,
+ ["f2"] = Keys.F2,
+ ["f3"] = Keys.F3,
+ ["f4"] = Keys.F4,
+ ["f5"] = Keys.F5,
+ ["f6"] = Keys.F6,
+ ["f7"] = Keys.F7,
+ ["f8"] = Keys.F8,
+ ["f9"] = Keys.F9,
+ ["f10"] = Keys.F10,
+ ["f11"] = Keys.F11,
+ ["f12"] = Keys.F12,
+
+ ["pageup"] = Keys.PageUp,
+ ["pagedown"] = Keys.PageDown,
+ ["home"] = Keys.Home,
+ ["end"] = Keys.End,
+ ["insert"] = Keys.Insert,
+ ["delete"] = Keys.Delete,
+
+ [";"] = Keys.OemSemicolon,
+ ["+"] = Keys.OemPlus,
+ [","] = Keys.OemComma,
+ ["-"] = Keys.OemMinus,
+ ["."] = Keys.OemPeriod,
+ ["/"] = Keys.OemQuestion,
+ ["`"] = Keys.OemTilde,
+ ["["] = Keys.OemOpenBrackets,
+ ["\\"] = Keys.OemPipe,
+ ["]"] = Keys.OemCloseBrackets,
+ ["'"] = Keys.OemQuotes,
+ ["backslash"] = Keys.OemBackslash,
+
+ ["dot"] = Keys.OemPeriod,
+ ["comma"] = Keys.OemComma,
+ ["minus"] = Keys.OemMinus,
+ ["plus"] = Keys.OemPlus,
+ ["period"] = Keys.OemPeriod,
+ ["question"] = Keys.OemQuestion,
+ ["tilde"] = Keys.OemTilde,
+ ["bracket_left"] = Keys.OemOpenBrackets,
+ ["bracket_right"] = Keys.OemCloseBrackets,
+ ["quote"] = Keys.OemQuotes,
+ ["backslash_alt"] = Keys.OemBackslash
+ };
+
+ public static Keys GetKeyFromString(string str)
+ {
+ if (!_map.TryGetValue(str, out var key))
+ return Keys.None;
+ return key;
+ }
+
+ public static KeymapAction? GetActionFromKey(this Keyboard info)
+ {
+ var inputs = Locator.GetService>();
+
+ foreach (var key in info.KeysPressed)
+ {
+ var modifiers = info.KeysDown.Where(i =>
+ i.Key == Keys.LeftShift ||
+ i.Key == Keys.RightShift ||
+ i.Key == Keys.LeftControl ||
+ i.Key == Keys.RightControl ||
+ i.Key == Keys.LeftAlt ||
+ i.Key == Keys.RightAlt
+ ).Select(i =>
+ {
+ var key = i.Key.ToString();
+ if (key.Contains("shift", StringComparison.OrdinalIgnoreCase))
+ return "Shift";
+ if (key.Contains("control", StringComparison.OrdinalIgnoreCase))
+ return "Control";
+ return "Alt";
+ }).ToArray();
+
+ if (!inputs.TryGetValue(new(key.Key, modifiers), out var input))
+ break;
+ return input.Action;
+ }
+ return null;
+ }
+ }
+}
diff --git a/src/Diviner/InputKey.cs b/src/Diviner/InputKey.cs
new file mode 100644
index 00000000..74852de0
--- /dev/null
+++ b/src/Diviner/InputKey.cs
@@ -0,0 +1,40 @@
+using System.Diagnostics.CodeAnalysis;
+using SadConsole.Input;
+
+namespace Diviner
+{
+ public readonly struct InputKey(Keys key, string[] modifiers) : IEquatable
+ {
+ public Keys Key { get; } = key;
+ public string[] Modifiers { get; } = modifiers ?? [];
+
+ public override int GetHashCode()
+ {
+ return HashCode.Combine(Key, string.Join(",", Modifiers));
+ }
+
+ public override bool Equals([NotNullWhen(true)] object? obj)
+ {
+ if (obj == null)
+ return false;
+ return Equals((InputKey)obj);
+ }
+
+ public bool Equals(InputKey o)
+ {
+ if (o.Key == Key && Modifiers.SequenceEqual(o.Modifiers))
+ return true;
+ return false;
+ }
+
+ public static bool operator ==(InputKey left, InputKey right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(InputKey left, InputKey right)
+ {
+ return !(left == right);
+ }
+ }
+}
diff --git a/src/Diviner/KeyboardHandle.cs b/src/Diviner/KeyboardHandle.cs
index a70571cd..7449a29c 100644
--- a/src/Diviner/KeyboardHandle.cs
+++ b/src/Diviner/KeyboardHandle.cs
@@ -1,22 +1,20 @@
using System.Diagnostics.CodeAnalysis;
using Arquimedes.Enumerators;
+using Diviner.Extensions;
using Diviner.Windows;
using MagusEngine;
using MagusEngine.Actions;
+using MagusEngine.Actions.Interfaces;
using MagusEngine.Bus.MapBus;
using MagusEngine.Bus.UiBus;
using MagusEngine.Components.EntityComponents;
using MagusEngine.Components.EntityComponents.Ai;
using MagusEngine.Core.Entities;
-using MagusEngine.Core.Magic;
using MagusEngine.Core.MapStuff;
-using MagusEngine.Exceptions;
using MagusEngine.Services;
using MagusEngine.Systems;
using MagusEngine.Systems.Time;
-using MagusEngine.Utils.Extensions;
using SadConsole.Input;
-using SadRogue.Primitives;
using Color = SadRogue.Primitives.Color;
namespace Diviner
@@ -26,317 +24,68 @@ public static class KeyboardHandle
[NotNull]
private static readonly Player _getPlayer = Find.Universe?.Player!;
- [AllowNull]
- private static Target? _targetCursor;
-
- private static readonly Dictionary _movementDirectionMapping = new()
+ private static readonly Dictionary> _actionFactory = new()
{
- { Keys.NumPad7, Direction.UpLeft }, { Keys.NumPad8, Direction.Up }, { Keys.NumPad9, Direction.UpRight },
- { Keys.NumPad4, Direction.Left }, { Keys.NumPad6, Direction.Right },
- { Keys.NumPad1, Direction.DownLeft }, { Keys.NumPad2, Direction.Down }, { Keys.NumPad3, Direction.DownRight },
- { Keys.Up, Direction.Up }, { Keys.Down, Direction.Down }, { Keys.Left, Direction.Left }, { Keys.Right, Direction.Right }
+ [KeymapAction.MoveNorth] = () => new MoveAction((0, -1)),
+ [KeymapAction.MoveSouth] = () => new MoveAction((0, 1)),
+ [KeymapAction.MoveLeft] = () => new MoveAction((-1, 0)),
+ [KeymapAction.MoveRight] = () => new MoveAction((1, 0)),
+ [KeymapAction.MoveNorthLeft] = () => new MoveAction((-1, -1)),
+ [KeymapAction.MoveNorthRight] = () => new MoveAction((1, -1)),
+ [KeymapAction.MoveSouthLeft] = () => new MoveAction((-1, 1)),
+ [KeymapAction.MoveSouthRight] = () => new MoveAction((1, 1)),
+ [KeymapAction.MoveUp] = () => new UpDownMovementAction(1),
+ [KeymapAction.MoveDown] = () => new UpDownMovementAction(-1),
+ [KeymapAction.OpenInventory] = () => new OpenInventoryAction(),
+ [KeymapAction.ThownItem] = () => new ThrowItemAction(),
+ [KeymapAction.EscapeMenu] = () => new EscapeMenuAction(),
+ [KeymapAction.WaitScreen] = () => new OpenWaitAction(),
+ [KeymapAction.WaitTillRested] = () => new RestAction(_getPlayer),
+ [KeymapAction.WaitOneMoment] = () => new WaitAction(TimeHelper.OneMoment),
+ [KeymapAction.WaitOneSecond] = () => new WaitAction(TimeHelper.OneSecond),
+ [KeymapAction.PickUp] = () => new PickUpPlayerAction(_getPlayer),
+ [KeymapAction.DropItem] = () => new DropItemPlayerAction(),
+ [KeymapAction.CloseDoor] = () => new OpenCloseDoorAction(_getPlayer, true),
+ [KeymapAction.OpenDoor] = () => new OpenCloseDoorAction(_getPlayer, false),
+ [KeymapAction.Look] = () => new LookAction(),
+ [KeymapAction.SpellCasting] = () => new SpellCastingPlayerAction(_getPlayer),
+ [KeymapAction.Interact] = () => new InteractAction(),
+ [KeymapAction.ConfirmAction] = () => new ConfirmAction(),
+ [KeymapAction.CancelAction] = () => new CancelAction(),
};
- public static bool HandleMapKeys(Keyboard input, UIManager ui, Universe world)
- {
- return HandleActions(input, world, ui);
- }
-
- public static bool HandleUiKeys(Keyboard info, UIManager ui)
- {
- if (info.IsKeyPressed(Keys.I))
- {
- ui.InventoryScreen.ShowItems(_getPlayer);
- return true;
- }
-
- if (info.IsKeyPressed(Keys.T))
- {
- ui.InventoryScreen.ShowItems(_getPlayer, item =>
- {
- _targetCursor ??= new Target(_getPlayer.Position);
- if (item is null)
- {
- Locator.GetService().SendMessage(new("No item selected!"));
- return;
- }
- _targetCursor.OnSelectItem(item, _getPlayer);
- ui.InventoryScreen.Hide();
- _getPlayer.Inventory.Remove(item);
- });
- }
-
- if (info.IsKeyPressed(Keys.Escape) && ui.NoPopWindow)
- {
- ui.MainMenu.Show();
- ui.MainMenu.IsFocused = true;
- return true;
- }
-
- return false;
- }
-
- private static bool HandleMove(Keyboard info, Universe world, UIManager ui)
- {
- #region WorldMovement
-
- if (CurrentMapIsPlanetView(world))
- {
- var console = ui.MapWindow.MapConsole;
-
- if (info.IsKeyDown(Keys.Left))
- {
- console.Surface.ViewPosition = console.Surface.ViewPosition.Translate((-1, 0));
- }
-
- if (info.IsKeyDown(Keys.Right))
- {
- console.Surface.ViewPosition = console.Surface.ViewPosition.Translate((1, 0));
- }
-
- if (info.IsKeyDown(Keys.Up))
- {
- console.Surface.ViewPosition = console.Surface.ViewPosition.Translate((0, -1));
- }
-
- if (info.IsKeyDown(Keys.Down))
- {
- console.Surface.ViewPosition = console.Surface.ViewPosition.Translate((0, +1));
- }
- // Must return false, because there isn't any movement of the actor
- return false;
- }
-
- #endregion WorldMovement
- if (world.CurrentMap is null)
- return false;
- var key = _movementDirectionMapping.Keys.FirstOrDefault(info.IsKeyPressed);
- if (_movementDirectionMapping.TryGetValue(key, out var moveDirection))
- {
- Point deltaMove = new(moveDirection.DeltaX, moveDirection.DeltaY);
- var actor = (Actor)world.CurrentMap.ControlledEntitiy!;
- if (world.CurrentMap.ControlledEntitiy is not Player)
- {
- if (world.CurrentMap.CheckForIndexOutOfBounds(world.CurrentMap.ControlledEntitiy!.Position + deltaMove))
- return false;
-
- int distance = HandleNonPlayerMoveAndReturnDistance(world, deltaMove);
-
- return world.CurrentMap.PlayerExplored[world.CurrentMap.ControlledEntitiy.Position + deltaMove]
- && distance <= _targetCursor?.MaxDistance
- && actor!.MoveBy(deltaMove);
- }
- return actor!.MoveBy(deltaMove);
- }
- return false;
- }
-
- private static int HandleNonPlayerMoveAndReturnDistance(Universe world, Point coorToMove)
- {
- int distance = 0;
- _ = world.CurrentMap ?? throw new NullValueException(nameof(world.CurrentMap));
-
- if (world.CurrentMap.ControlledEntitiy == _targetCursor?.Cursor)
- {
- _ = _targetCursor ?? throw new NullValueException(nameof(_targetCursor));
-
- if (_targetCursor.TravelPath is not null)
- distance = _targetCursor.TravelPath.LengthWithStart;
- if (_targetCursor.TravelPath is not null && _targetCursor.TravelPath.LengthWithStart >= _targetCursor.MaxDistance)
- {
- distance = world!.CurrentMap!.AStar!.ShortestPath(_targetCursor.OriginCoord, world!.CurrentMap!.ControlledEntitiy!.Position + coorToMove)!.Length;
- }
- }
- return distance;
- }
- private static bool HandleActions(Keyboard info, Universe uni, UIManager ui)
+ public static bool HandleKeys(Keyboard info)
{
- if (_getPlayer == null || uni == null)
- return false;
-
- // Work around for a > symbol, must be top to not make the char wait
- if (info.IsKeyDown(Keys.LeftShift) && info.IsKeyPressed(Keys.OemPeriod))
- {
- return ActionManager.EnterDownMovement(_getPlayer.Position);
- }
- // Work around for a < symbol, must be top to not make the char wait
- if (info.IsKeyDown(Keys.LeftShift) && info.IsKeyPressed(Keys.OemComma))
- {
- return ActionManager.EnterUpMovement(_getPlayer.Position);
- }
- if (HandleMove(info, uni, ui))
- {
- if (!_getPlayer.Bumped && uni?.CurrentMap?.ControlledEntitiy is Player)
- {
- Locator.GetService().SendMessage(new(TimeHelper.GetWalkTime(_getPlayer,
- uni.CurrentMap.GetTileAt(_getPlayer.Position)!), true));
- }
- else if (uni?.CurrentMap?.ControlledEntitiy is Player)
- {
- var attack = _getPlayer.GetAttacks().GetRandomItemFromList() ?? throw new NullValueException("Attack was null", null);
- Locator.GetService().SendMessage(new(TimeHelper.GetAttackTime(_getPlayer, attack), true));
- }
-
- return true;
- }
-
- if (info.IsKeyPressed(Keys.NumPad5) && info.IsKeyDown(Keys.LeftControl))
- {
- return ActionManager.RestTillFull(_getPlayer);
- }
-
- if (info.IsKeyPressed(Keys.NumPad5) || info.IsKeyPressed(Keys.OemPeriod))
- {
- Locator.GetService().SendMessage(new(TimeHelper.Wait, true));
- return true;
- }
-
- if (info.IsKeyPressed(Keys.OemComma))
- {
- Locator.GetService().SendMessage(new(10, true));
- return true;
- }
-
- //if (info.IsKeyPressed(Keys.A))
- //{
- // bool sucess = ActionManager.DirectAttack(world.Player);
- // world.ProcessTurn(TimeHelper.GetAttackTime(world.Player), sucess);
- // return sucess;
- //} // some other thing will be in here!
- if (info.IsKeyPressed(Keys.G))
- {
- Item item = uni.CurrentMap!.GetEntityAt- (uni.CurrentMap.ControlledEntitiy!.Position)!;
- bool sucess = ActionManager.PickUp(uni.Player, item!);
- Locator.GetService().SendMessage(new(TimeHelper.Interact, sucess));
- return sucess;
- }
-
- if (info.IsKeyPressed(Keys.D))
- {
- //bool sucess = ActionManager.DropTopItemInv(uni.Player);
- ui.InventoryScreen.ShowItems((Actor)uni!.CurrentMap!.ControlledEntitiy!, item =>
- {
- var sucess = ActionManager.DropItem(item, _getPlayer.Position, uni.CurrentMap);
- Locator.GetService().SendMessage(new(TimeHelper.Interact, sucess));
- });
+ var action = info.GetActionFromKey();
+ if (action is null)
return false;
- }
- if (info.IsKeyPressed(Keys.C))
- {
- bool sucess = ActionManager.CloseDoor(uni.Player);
- Locator.GetService().SendMessage(new(TimeHelper.Interact, sucess));
- ui.MapWindow.MapConsole.IsDirty = true;
- }
- if (info.IsKeyDown(Keys.LeftShift) && info.IsKeyPressed(Keys.H))
- {
- bool sucess = ActionManager.NodeDrain(_getPlayer);
- Locator.GetService().SendMessage(new(TimeHelper.MagicalThings, sucess));
- }
- if (info.IsKeyPressed(Keys.L))
- {
- _targetCursor ??= new Target(_getPlayer.Position);
-
- if (_targetCursor.State == TargetState.LookMode)
- {
- _targetCursor.EndTargetting();
- }
- else
- {
- _targetCursor.StartTargetting();
- }
-
- return true;
- }
-
- if (info.IsKeyDown(Keys.LeftShift) && info.IsKeyPressed(Keys.Z))
- {
- SpellSelectWindow spell = new(_getPlayer.Soul.CurrentMana);
-
- _targetCursor ??= new Target(_getPlayer.Position);
- var magic = _getPlayer.GetComponent();
- spell.Show(magic.KnowSpells, selectedSpell => _targetCursor.OnSelectSpell(selectedSpell, (Actor)uni.CurrentMap!.ControlledEntitiy!), _getPlayer.Soul.CurrentMana);
-
- return true;
- }
-
- if (info.IsKeyDown(Keys.LeftShift) && info.IsKeyPressed(Keys.R))
- {
- var wait = ui.GetWindow(WindowTag.Wait);
- if (wait is null)
- {
- wait = new();
- ui.AddWindowToList(wait);
- }
- wait.Show(true);
- return true;
- }
-
- if (info.IsKeyPressed(Keys.Enter) && _targetCursor is not null)
- {
- if (_targetCursor.AnyTargeted())
- {
- bool sucess = false;
- long timeTaken = 0;
- if (_targetCursor.State == TargetState.LookMode)
- {
- _targetCursor.LookTarget();
- return true;
- }
- else if (_targetCursor.State == TargetState.TargetingSpell)
- {
- (sucess, var spellCasted) = _targetCursor.EndSpellTargetting();
- if (sucess)
- timeTaken = TimeHelper.GetCastingTime(_getPlayer, spellCasted!);
- }
- else
- {
- (sucess, var item) = _targetCursor.EndItemTargetting();
- if (sucess)
- timeTaken = TimeHelper.GetShootingTime(_getPlayer, item!.Mass);
- }
- if (sucess)
- {
- _targetCursor = null;
- Locator.GetService()?.SendMessage(new(timeTaken, sucess));
- }
-
- return sucess;
- }
- else
- {
- Locator.GetService()?.SendMessage(new("Invalid target!"));
- return false;
- }
- }
-
- if (info.IsKeyPressed(Keys.Escape) && (_targetCursor is not null))
- {
- _targetCursor.EndTargetting();
-
- _targetCursor = null!;
-
- return true;
- }
-
#if DEBUG
- if (HandleDebugActions(info, uni, ui))
+ if (HandleDebugActions(info, Find.Universe))
{
return true;
}
#endif
+ var executeAction = GetExecuteAction(action.Value);
+ if (executeAction is null)
+ return false;
+ return executeAction.Execute(Find.Universe);
+ }
- return false;
+ private static IExecuteAction? GetExecuteAction(KeymapAction action)
+ {
+ if (_actionFactory.TryGetValue(action, out var factory))
+ return factory();
+ return null;
}
#if DEBUG
- private static bool HandleDebugActions(Keyboard info, Universe uni, UIManager ui)
+ private static bool HandleDebugActions(Keyboard info, Universe uni)
{
if (info.IsKeyPressed(Keys.F10))
{
ActionManager.ToggleFOV();
- ui.MapWindow.MapConsole.IsDirty = true;
int c = uni!.CurrentMap!.PlayerExplored.Count;
for (int i = 0; i < c; i++)
{
@@ -350,10 +99,10 @@ private static bool HandleDebugActions(Keyboard info, Universe uni, UIManager ui
uni!.CurrentMap!.ForceFovCalculation();
return false;
}
-
- if (info.IsKeyPressed(Keys.K) && _targetCursor?.TileInTarget() == true)
+ var targetCursor = uni.CurrentMap.TargetCursor;
+ if (info.IsKeyPressed(Keys.K) && targetCursor?.TileInTarget() == true)
{
- Tile tile = uni!.CurrentMap!.GetTileAt(_targetCursor.Position)!;
+ Tile tile = uni!.CurrentMap!.GetTileAt(targetCursor.Position)!;
tile!.IsTransparent = !tile.IsTransparent;
return false;
}
@@ -403,23 +152,23 @@ private static bool HandleDebugActions(Keyboard info, Universe uni, UIManager ui
if (info.IsKeyDown(Keys.LeftControl)
&& info.IsKeyDown(Keys.LeftShift)
- && info.IsKeyPressed(Keys.O) && _targetCursor is not null)
+ && info.IsKeyPressed(Keys.O) && targetCursor is not null)
{
- var (_, actor) = ActionManager.CreateTestEntity(_targetCursor.Cursor.Position, uni);
+ var (_, actor) = ActionManager.CreateTestEntity(targetCursor.Cursor.Position, uni);
actor.AddComponents(new MoveAndAttackAI(actor.GetViewRadius()));
return false;
}
- if (info.IsKeyDown(Keys.LeftShift) && info.IsKeyPressed(Keys.O) && _targetCursor is not null)
+ if (info.IsKeyDown(Keys.LeftShift) && info.IsKeyPressed(Keys.O) && targetCursor is not null)
{
- var (_, entity) = ActionManager.CreateTestEntity(_targetCursor.Cursor.Position, uni);
+ var (_, entity) = ActionManager.CreateTestEntity(targetCursor.Cursor.Position, uni);
entity.AddComponents(new BasicAi(entity));
return false;
}
- if (info.IsKeyDown(Keys.LeftShift) && info.IsKeyPressed(Keys.P) && _targetCursor!.EntityInTarget())
+ if (info.IsKeyDown(Keys.LeftShift) && info.IsKeyPressed(Keys.P) && targetCursor!.EntityInTarget())
{
- Actor actor = (Actor)_targetCursor.TargetEntity()!;
+ Actor actor = (Actor)targetCursor.TargetEntity()!;
actor.AddComponents(new MoveAndAttackAI(actor.GetViewRadius()));
Locator.GetService()
.SendMessage(new($"Added attack component to {actor.Name}!"));
@@ -429,9 +178,9 @@ private static bool HandleDebugActions(Keyboard info, Universe uni, UIManager ui
if (info.IsKeyDown(Keys.LeftShift)
&& info.IsKeyDown(Keys.LeftControl)
&& info.IsKeyPressed(Keys.P)
- && _targetCursor!.EntityInTarget())
+ && targetCursor!.EntityInTarget())
{
- Actor? actor = (Actor?)_targetCursor.TargetEntity();
+ Actor? actor = (Actor?)targetCursor.TargetEntity();
actor?.AddComponents(new NeedDrivenAi());
Locator.GetService()
.SendMessage(new($"Added need component to {actor?.Name}!"));
@@ -444,9 +193,9 @@ private static bool HandleDebugActions(Keyboard info, Universe uni, UIManager ui
return false;
}
- if (info.IsKeyPressed(Keys.P) && (_targetCursor?.EntityInTarget()) == true)
+ if (info.IsKeyPressed(Keys.P) && (targetCursor?.EntityInTarget()) == true)
{
- var target = _targetCursor.TargetEntity();
+ var target = targetCursor.TargetEntity();
var needs = target!.GetComponent();
for (int i = 0; i < needs.Count; i++)
{
@@ -464,8 +213,5 @@ private static bool HandleDebugActions(Keyboard info, Universe uni, UIManager ui
}
#endif
-
- private static bool CurrentMapIsPlanetView(Universe world) =>
- world.WorldMap != null && world.WorldMap.AssocietatedMap == world.CurrentMap && world.Player == null;
}
}
diff --git a/src/Diviner/UIManager.cs b/src/Diviner/UIManager.cs
index 136760a5..6620d6f2 100644
--- a/src/Diviner/UIManager.cs
+++ b/src/Diviner/UIManager.cs
@@ -6,15 +6,16 @@
using Diviner.Windows;
using GoRogue.Messaging;
using MagusEngine;
-using MagusEngine.Exceptions;
using MagusEngine.Bus;
using MagusEngine.Bus.UiBus;
using MagusEngine.Core.Entities;
+using MagusEngine.Exceptions;
using MagusEngine.Services;
using MagusEngine.Systems;
using MagusEngine.Utils;
using SadConsole;
using SadConsole.Input;
+using SadConsole.Instructions;
using Color = SadConsole.UI.AdjustableColor;
namespace Diviner
@@ -27,7 +28,12 @@ public sealed class UIManager : ScreenObject,
ISubscriber,
ISubscriber,
ISubscriber,
- ISubscriber
+ ISubscriber,
+ ISubscriber,
+ ISubscriber,
+ ISubscriber,
+ ISubscriber,
+ ISubscriber
{
private readonly Dictionary _windows = [];
private Universe? _universe;
@@ -115,7 +121,7 @@ private void ConfigureWindowsAndConsoles(int height, int width, Universe uni)
#endif
// Inventory initialization
InventoryScreen = new InventoryWindow(width / 2, height / 2);
- Children.Add(InventoryScreen);
+ AddWindowToList(InventoryScreen);
InventoryScreen.Hide();
const int statusWindowHeight = 4;
StatusWindow = new BottomStatusWindow(width - MessageLog.Width, statusWindowHeight, "Status Window");
@@ -168,11 +174,7 @@ public override bool ProcessKeyboard(Keyboard info)
&& (_universe.CurrentMap.ControlledEntitiy is not null
|| _universe.WorldMap.AssocietatedMap.Equals(_universe.CurrentMap)))
{
- if (KeyboardHandle.HandleMapKeys(info, this, _universe))
- {
- return true;
- }
- if (KeyboardHandle.HandleUiKeys(info, this))
+ if (KeyboardHandle.HandleKeys(info))
{
return true;
}
@@ -291,6 +293,46 @@ public void Handle([NotNull] ShowGlyphOnConsole message)
message.LastUsedGlyph = originalGlyph;
}
+ public void Handle(CloseWindowMessage message)
+ {
+ MagiBaseWindow window = GetWindow(message.Tag) ?? throw new NullValueException(nameof(window));
+ window.Hide();
+ }
+
+ public void Handle(ShowMainMenuMessage message)
+ {
+ if (!NoPopWindow)
+ return;
+ MainMenu.Show();
+ MainMenu.IsFocused = true;
+ }
+
+ public void Handle(ScrollConsoleMessage message)
+ {
+ var console = MapWindow.MapConsole;
+ console.Surface.ViewPosition = console.Surface.ViewPosition.Translate(message.Delta);
+ }
+
+ public void Handle(OpenWindowEvent message)
+ {
+ var window = GetWindow(message.Window);
+ if (window is null)
+ throw new NullValueException(nameof(window));
+ if (window is WaitWindow)
+ {
+ window = new WaitWindow();
+ AddWindowToList(window);
+ }
+ window?.Show(true);
+ }
+
+ public void Handle(OpenSpellCastingWindowMessage message)
+ {
+ SpellSelectWindow spell = new(message.CurrentMana);
+
+ spell.Show(message.Spells, message.OnCast!, message.CurrentMana);
+ }
+
~UIManager()
{
Locator.GetService().UnRegisterAllSubscriber(this);
diff --git a/src/Diviner/Windows/InventoryWindow.cs b/src/Diviner/Windows/InventoryWindow.cs
index 6bbb23b2..1a32e156 100644
--- a/src/Diviner/Windows/InventoryWindow.cs
+++ b/src/Diviner/Windows/InventoryWindow.cs
@@ -1,4 +1,9 @@
-using MagusEngine.Core.Entities;
+using Arquimedes.Enumerators;
+using GoRogue.Messaging;
+using MagusEngine;
+using MagusEngine.Bus.UiBus;
+using MagusEngine.Core.Entities;
+using MagusEngine.Services;
using MagusEngine.Utils.Extensions;
using SadConsole;
using SadConsole.Input;
@@ -8,8 +13,9 @@
namespace Diviner.Windows
{
- public class InventoryWindow : PopWindow
+ public class InventoryWindow : PopWindow, ISubscriber
{
+ private readonly MessageBusService _bus;
// Create the field
private readonly Console inventoryConsole;
@@ -22,6 +28,7 @@ public class InventoryWindow : PopWindow
///
public InventoryWindow(int width, int heigth, string title = "Inventory") : base(title)
{
+ _bus = Locator.GetService();
// define the inventory console
inventoryConsole = new Console(width - WindowBorderThickness, heigth - WindowBorderThickness)
{
@@ -36,6 +43,8 @@ public InventoryWindow(int width, int heigth, string title = "Inventory") : base
invScrollBar.ValueChanged += InvScrollBar_ValueChanged;
Controls.Add(invScrollBar);
+ _bus.RegisterAllSubscriber(this);
+ Tag = WindowTag.Inv;
}
public override bool ProcessKeyboard(Keyboard info)
@@ -87,5 +96,15 @@ private void RefreshControls(Actor actorInventory, Action
- ? itemAction)
SetupSelectionButtons(BuildHotKeysButtons(actorInventory.Inventory, itemAction ?? OnItemSelected));
_actionContext = itemAction;
}
+
+ public void Handle(InventoryActionBus message)
+ {
+ ShowItems(message.ActorInventory, message.Action);
+ }
+
+ ~InventoryWindow()
+ {
+ _bus.UnRegisterAllSubscriber(this);
+ }
}
}
diff --git a/src/Diviner/Windows/MainMenuWindow.cs b/src/Diviner/Windows/MainMenuWindow.cs
index b9bd8fcd..05093a17 100644
--- a/src/Diviner/Windows/MainMenuWindow.cs
+++ b/src/Diviner/Windows/MainMenuWindow.cs
@@ -1,6 +1,5 @@
using Arquimedes.Utils;
using Diviner.Controls;
-using GoRogue.Messaging;
using MagusEngine;
using MagusEngine.Bus;
using MagusEngine.Bus.UiBus;
@@ -12,8 +11,7 @@
namespace Diviner.Windows
{
- public class MainMenuWindow : MagiBaseWindow,
- ISubscriber
+ public class MainMenuWindow : MagiBaseWindow
{
private readonly MagiButton startGame;
private readonly MagiButton testMap;
@@ -21,6 +19,7 @@ public class MainMenuWindow : MagiBaseWindow,
private readonly MagiButton saveGame; // neither does this
private ListBox? savesBox;
private PopWindow? loadPop;
+
public bool GameStarted { get; set; }
public MainMenuWindow(int width, int height, string title = "Main Menu") : base(width, height, title)
@@ -38,7 +37,7 @@ public MainMenuWindow(int width, int height, string title = "Main Menu") : base(
{
Text = "Test Map"
};
- MagiButton quitGame = new MagiButton(11, 1)
+ MagiButton quitGame = new(11, 1)
{
Text = "Quit Game"
};
@@ -76,7 +75,7 @@ private void ContinueGame_Click(object? sender, EventArgs e)
loadPop = new PopWindow(30, 15, "Load Game");
const string text = "Load!";
// The load button
- MagiButton loadGame = new MagiButton(text.Length + 2)
+ MagiButton loadGame = new(text.Length + 2)
{
Text = text,
Position = new Point(3, loadPop.Height - 2)
@@ -90,7 +89,7 @@ private void ContinueGame_Click(object? sender, EventArgs e)
Position = new Point((loadPop.Width / 2) - 10, (loadPop.Height / 2) - 5)
};
const string delete = "Delete";
- MagiButton deleteSaveBtn = new MagiButton(delete.Length + 2)
+ MagiButton deleteSaveBtn = new(delete.Length + 2)
{
Text = delete,
Position = new Point((loadPop.Width / 2) - 5, loadPop.Height - 3)
@@ -113,10 +112,10 @@ private void ContinueGame_Click(object? sender, EventArgs e)
private void DeleteSaveBtn_Click(object? sender, EventArgs e)
{
- if (savesBox.SelectedItem != null)
+ if (savesBox?.SelectedItem != null)
{
- SavingService.DeleteSave(savesBox.SelectedItem?.ToString());
- savesBox.Items.Remove(savesBox.SelectedItem);
+ SavingService.DeleteSave(savesBox.SelectedItem?.ToString()!);
+ savesBox.Items.Remove(savesBox.SelectedItem!);
savesBox.IsDirty = true;
}
}
@@ -124,10 +123,10 @@ private void DeleteSaveBtn_Click(object? sender, EventArgs e)
private void LoadGame_Click(object? sender, EventArgs e)
{
if (savesBox?.SelectedItem != null
- && SavingService.CheckIfStringIsValidSave(savesBox.SelectedItem.ToString()))
+ && SavingService.CheckIfStringIsValidSave(savesBox.SelectedItem.ToString()!))
{
- loadPop.Hide();
- Universe uni = SavingService.LoadGame(savesBox.SelectedItem.ToString());
+ loadPop?.Hide();
+ Universe uni = SavingService.LoadGame(savesBox.SelectedItem.ToString()!);
Locator.GetService().SendMessage(new(uni.Player, uni));
}
}
@@ -141,7 +140,7 @@ private void PopulateListWithSaves()
for (int i = 0; i < saves.Length; i++)
{
string save = SaveUtils.GetSaveName(saves[i]);
- savesBox.Items.Add(save);
+ savesBox?.Items?.Add(save);
}
}
@@ -189,7 +188,7 @@ private void SaveGameClick(object? sender, EventArgs e)
{
// makes so that there can only be one save per player name!
Find.Universe.SaveGame(Find.Universe.Player.Name);
- PopWindow alert = new PopWindow(30, 10, "Save Done!");
+ PopWindow alert = new(30, 10, "Save Done!");
// makes it a variable so that it can be properly accounted for in the print command
const string text = "Save Sucessful!";
alert.Print((alert.Width - text.Length) / 2, 3, text);
@@ -211,26 +210,6 @@ public void RestartGame()
GameStarted = false;
Find.Universe = null!;
RefreshButtons();
-
- //foreach (SadConsole.Console item in GameLoop.UIManager.Children.Cast())
- //{
- // if (!item.Equals(this))
- // item.Dispose();
- //}
-
- //GameLoop.UIManager.MessageLog = null!;
- //GameLoop.UIManager.MapWindow = null!;
- //GameLoop.UIManager.StatusWindow = null!;
- //GameLoop.UIManager.InventoryScreen = null!;
- //GameLoop.UIManager.CharCreationWindow = null!;
- //GameLoop.UIManager.Children.Clear();
- //GameLoop.UIManager.Children.Add(this);
-
- Show();
- }
-
- public void Handle(ShowMainMenuMessage message)
- {
Show();
}
}
diff --git a/src/Diviner/Windows/MapWindow.cs b/src/Diviner/Windows/MapWindow.cs
index 03d90e25..c5d0fe93 100644
--- a/src/Diviner/Windows/MapWindow.cs
+++ b/src/Diviner/Windows/MapWindow.cs
@@ -1,5 +1,4 @@
using Arquimedes.Enumerators;
-using Diviner.Interfaces;
using GoRogue.Messaging;
using MagusEngine;
using MagusEngine.Bus.UiBus;
diff --git a/src/Diviner/Windows/PopWindow.cs b/src/Diviner/Windows/PopWindow.cs
index f814af66..f62063ee 100644
--- a/src/Diviner/Windows/PopWindow.cs
+++ b/src/Diviner/Windows/PopWindow.cs
@@ -112,6 +112,7 @@ protected List BuildHotKeysButtons(List listItems,
};
_hotKeys.Add(hotkeyLetter, (item, button.IsEnabled));
button.Click += (_, __) => button.Action.Invoke();
+ button.Focused += (_, __) => button.Action.Invoke();
controlList.Add(button);
}
diff --git a/src/Diviner/Windows/SpellSelectWindow.cs b/src/Diviner/Windows/SpellSelectWindow.cs
index 2973e422..e118d0d5 100644
--- a/src/Diviner/Windows/SpellSelectWindow.cs
+++ b/src/Diviner/Windows/SpellSelectWindow.cs
@@ -29,8 +29,7 @@ public SpellSelectWindow(double currentMana) : base("Select your spell")
};
_castButton.Click += (_, __) =>
{
- _onCast?.Invoke(_selectedSpell!);
- Hide();
+ CastSpell(_selectedSpell!);
};
}
@@ -38,10 +37,14 @@ public override bool ProcessKeyboard(Keyboard info)
{
foreach (var key in info.KeysPressed)
{
+ if (key.Key == Keys.Enter && _selectedSpell is not null)
+ {
+ CastSpell(_selectedSpell);
+ return true;
+ }
if (_hotKeys.TryGetValue(key.Character, out var tuple) && tuple.Item2)
{
- _onCast((Spell)tuple.Item1);
- Hide();
+ CastSpell((Spell)tuple.Item1);
return true;
}
@@ -49,6 +52,12 @@ public override bool ProcessKeyboard(Keyboard info)
return base.ProcessKeyboard(info);
}
+ private void CastSpell(Spell spell)
+ {
+ _onCast(spell);
+ Hide();
+ }
+
public void Show(List listSpells, Action onCast, double currentMana)
{
_currentMana = currentMana;
diff --git a/src/MagiRogue.Benchmarks/MagiRogue.Benchmarks.csproj b/src/MagiRogue.Benchmarks/MagiRogue.Benchmarks.csproj
index 6044c251..657e8804 100644
--- a/src/MagiRogue.Benchmarks/MagiRogue.Benchmarks.csproj
+++ b/src/MagiRogue.Benchmarks/MagiRogue.Benchmarks.csproj
@@ -2,14 +2,14 @@
Exe
- net9.0
+ net10.0
enable
enable
-
+
diff --git a/src/MagiRogue.LegendsConsoleViewer/MagiRogue.LegendsConsoleViewer.csproj b/src/MagiRogue.LegendsConsoleViewer/MagiRogue.LegendsConsoleViewer.csproj
index 194ca548..2fcbda60 100644
--- a/src/MagiRogue.LegendsConsoleViewer/MagiRogue.LegendsConsoleViewer.csproj
+++ b/src/MagiRogue.LegendsConsoleViewer/MagiRogue.LegendsConsoleViewer.csproj
@@ -2,7 +2,7 @@
Exe
- net9.0
+ net10.0
enable
enable
diff --git a/src/MagiRogue.Test/MagiRogue.Test.csproj b/src/MagiRogue.Test/MagiRogue.Test.csproj
index b03ddfb3..2ffd299b 100644
--- a/src/MagiRogue.Test/MagiRogue.Test.csproj
+++ b/src/MagiRogue.Test/MagiRogue.Test.csproj
@@ -1,7 +1,7 @@
- net9.0
+ net10.0
false
Library
diff --git a/src/MagiRogue/MagiRogue.csproj b/src/MagiRogue/MagiRogue.csproj
index 78f364aa..02f977bf 100644
--- a/src/MagiRogue/MagiRogue.csproj
+++ b/src/MagiRogue/MagiRogue.csproj
@@ -1,61 +1,57 @@
-
+
-
- Exe
- net9.0
- MagiRogue.GameLoop
- false
- Sofistico
- Sofistico
-
- A roguelike created with SadConsole 9.x and GoRogue 3.x
-
- Wizard.ico
- enable
- True
- Sofistico
- README.md
-
- C:\Users\joaorodrigues\source\repos\MagiRogue\LICENSE
-
-
+
+ Exe
+ net10.0
+ false
+ Sofistico
+ Sofistico
+
+ A roguelike created with SadConsole 9.x and GoRogue 3.x
+
+ Wizard.ico
+ enable
+ True
+ Sofistico
+ README.md
+
+ C:\Users\joaorodrigues\source\repos\MagiRogue\LICENSE
+
+
-
- 1701;1702;8765;8618;8604;8602;8600;8603
-
+
+ 1701;1702;8765;8618;8604;8602;8600;8603
+
-
- 1701;1702;8765;8618;8604;8602;8600;8603
-
+
+ 1701;1702;8765;8618;8604;8602;8600;8603
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
- True
- \
-
-
-
- PreserveNewest
-
-
-
+
+
+ True
+ \
+
+
+
+ PreserveNewest
+
+
+
-
-
-
-
-
-
-
+
+
+
+
-
-
-
+
+
+
diff --git a/src/MagiRogue/GameLoop.cs b/src/MagiRogue/Program.cs
similarity index 77%
rename from src/MagiRogue/GameLoop.cs
rename to src/MagiRogue/Program.cs
index d0148bd0..5f932ce3 100644
--- a/src/MagiRogue/GameLoop.cs
+++ b/src/MagiRogue/Program.cs
@@ -1,18 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.IO;
+using System.Linq;
using Arquimedes;
using Arquimedes.Settings;
using Arquimedes.Utils;
using Diviner;
+using Diviner.Extensions;
using MagusEngine;
using MagusEngine.Services;
using SadConsole;
using SadConsole.Configuration;
using SadConsole.Input;
-using System;
-using System.IO;
+using SadConsole.UI.Windows;
namespace MagiRogue
{
- public static class GameLoop
+ public static class Program
{
private static GlobalSettings settings;
private static bool beginTest;
@@ -63,7 +68,6 @@ private static void ConfigureBeforeCreateGame(string[] args)
{
foreach (var arg in args)
{
- // TODO!
if (arg.Equals("test", StringComparison.Ordinal))
beginTest = true;
}
@@ -77,6 +81,24 @@ private static void ConfigureBeforeCreateGame(string[] args)
settings = JsonUtils.JsonDeseralize(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Settings", "global_setting.json"))!;
Locator.AddService(settings);
+
+ ConfigureKeys();
+ }
+
+ private static void ConfigureKeys()
+ {
+ var listInputs = JsonUtils.JsonDeseralize
>(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Settings", "inputs_setting.json"))!;
+ var dictInput = new Dictionary(listInputs.Count);
+ foreach (var input in listInputs)
+ {
+ foreach (var key in input.Keys)
+ {
+ var keyEnum = KeyboardExtensions.GetKeyFromString(key);
+ var inputKey = new InputKey(keyEnum, input.Modifier);
+ dictInput.TryAdd(inputKey, input);
+ }
+ }
+ Locator.AddService(dictInput);
}
private static void Init(object? sender, GameHost e)
@@ -92,6 +114,9 @@ private static void Init(object? sender, GameHost e)
// Now let the UIManager create its consoles so they can use the World data
ui.InitMainMenu(GameHeight, GameWidth, beginTest);
Locator.AddService(ui);
+#if DEBUG
+ GlyphSelectPopup.AddRootComponent(Keys.F11);
+#endif
}
#endregion configuration
diff --git a/src/MagusEngine/Actions/ActionManager.cs b/src/MagusEngine/Actions/ActionManager.cs
index 3d69c6fe..4ee9ee94 100644
--- a/src/MagusEngine/Actions/ActionManager.cs
+++ b/src/MagusEngine/Actions/ActionManager.cs
@@ -27,6 +27,7 @@
using System.Linq;
using System.Text;
using MagiMap = MagusEngine.Core.MapStuff.MagiMap;
+using System;
namespace MagusEngine.Actions
{
@@ -79,7 +80,7 @@ public static long MeleeAttack(Actor attacker,
.SendMessage(new($"You are too tired to attack|{attacker.Name} is too tired to attack!",
showMessage,
isPlayer ? PointOfView.First : PointOfView.Third));
- return TimeHelper.Wait;
+ return TimeHelper.OneSecond;
}
// Create two messages that describe the outcome of the attack and defense
@@ -112,12 +113,27 @@ public static long MeleeAttack(Actor attacker,
attack,
itemUsed,
limbAttacking);
- var staminaDiscount = attacker.Body.Stamina
- - attack.PrepareVelocity * 10 + attacker.Body.Endurance * 0.5;
- // discount stamina from the attacker
- attacker.Body.Stamina = MathMagi.Round(staminaDiscount);
- return TimeHelper.GetAttackTime(attacker, attack);
+ // Improved stamina cost calculation
+ var staminaCost = CalculateStaminaCost(attacker, attack, itemUsed);
+ attacker.Body.Stamina = Math.Max(0, attacker.Body.Stamina - staminaCost);
+
+ return itemUsed != null ?
+ TimeHelper.GetAttackTimeWithWeapon(attacker, attack, itemUsed) :
+ TimeHelper.GetAttackTime(attacker, attack);
+ }
+
+ ///
+ /// Calculates realistic stamina cost for attacks based on weapon weight, strength, and endurance
+ ///
+ private static double CalculateStaminaCost(Actor attacker, Attack attack, Item? weapon)
+ {
+ double baseCost = attack.PrepareVelocity;
+ double weaponWeight = weapon?.Mass ?? 1.0;
+ double strengthFactor = Math.Max(0.1, 1.0 - (attacker.GetStrenght() * 0.01));
+ double enduranceFactor = Math.Max(0.5, 1.0 - (attacker.Body.Endurance * 0.005));
+
+ return baseCost * weaponWeight * strengthFactor * enduranceFactor;
}
public static void ShootProjectileAction(Point origin,
@@ -358,34 +374,6 @@ public static (bool, Actor) CreateTestEntity(Point pos, Universe universe)
// return false;
//}
- public static bool RestTillFull(Actor actor)
- {
- Body bodyStats = actor.Body;
- //Mind mindStats = actor.Mind;
- Soul soulStats = actor.Soul;
-
- if (bodyStats.Stamina < bodyStats.MaxStamina || soulStats.CurrentMana < soulStats.MaxMana)
- {
- // calculate here the amount of time that it will take in turns to rest to full
- double staminaDif, manaDif;
-
- staminaDif = MathMagi.Round((bodyStats.MaxStamina - bodyStats.Stamina) / actor.GetStaminaRegen());
- manaDif = MathMagi.Round((soulStats.MaxMana - soulStats.CurrentMana) / actor.GetManaRegen());
-
- double totalTurnsWait = staminaDif + manaDif;
-
- bool sus = WaitForNTurns((int)totalTurnsWait, actor);
-
- Locator.GetService().SendMessage(new($"You have rested for {totalTurnsWait} turns"));
-
- return sus;
- }
-
- Locator.GetService().SendMessage(new("You have no need to rest"));
-
- return false;
- }
-
///
/// Equips an item
///
@@ -543,7 +531,7 @@ public static bool WaitForNTurns(int turns, Actor actor, bool canBeInterrupted =
}
}
- Locator.GetService().SendMessage(new(TimeHelper.Wait, true));
+ Locator.GetService().SendMessage(new(TimeHelper.OneSecond, true));
}
return true;
}
diff --git a/src/MagusEngine/Actions/CancelAction.cs b/src/MagusEngine/Actions/CancelAction.cs
new file mode 100644
index 00000000..133658e6
--- /dev/null
+++ b/src/MagusEngine/Actions/CancelAction.cs
@@ -0,0 +1,18 @@
+using MagusEngine.Actions.Interfaces;
+using MagusEngine.Systems;
+
+namespace MagusEngine.Actions
+{
+ public class CancelAction : IExecuteAction
+ {
+ public bool Execute(Universe world)
+ {
+ var targetCursor = world?.CurrentMap?.TargetCursor;
+ targetCursor?.EndTargetting();
+
+ world?.CurrentMap?.TargetCursor = null;
+
+ return true;
+ }
+ }
+}
diff --git a/src/MagusEngine/Actions/ConfirmAction.cs b/src/MagusEngine/Actions/ConfirmAction.cs
new file mode 100644
index 00000000..08a76abc
--- /dev/null
+++ b/src/MagusEngine/Actions/ConfirmAction.cs
@@ -0,0 +1,62 @@
+using Arquimedes.Enumerators;
+using MagusEngine.Actions.Interfaces;
+using MagusEngine.Bus.MapBus;
+using MagusEngine.Bus.UiBus;
+using MagusEngine.Core.Entities;
+using MagusEngine.Services;
+using MagusEngine.Systems;
+using MagusEngine.Systems.Time;
+
+namespace MagusEngine.Actions
+{
+ public class ConfirmAction : IExecuteAction
+ {
+ private readonly MessageBusService _bus;
+
+ public ConfirmAction()
+ {
+ _bus = Locator.GetService();
+ }
+
+ public bool Execute(Universe world)
+ {
+ var targetCursor = world?.CurrentMap?.TargetCursor;
+ Actor getPlayer = world!.Player!;
+ if (targetCursor?.AnyTargeted() == true)
+ {
+ long timeTaken = 0;
+ bool sucess;
+ if (targetCursor.State == TargetState.LookMode)
+ {
+ targetCursor.LookTarget();
+ return true;
+ }
+ else if (targetCursor.State == TargetState.TargetingSpell)
+ {
+ (sucess, var spellCasted) = targetCursor.EndSpellTargetting();
+ if (sucess)
+ timeTaken = TimeHelper.GetCastingTime(getPlayer, spellCasted!);
+ }
+ else
+ {
+ (sucess, var item) = targetCursor.EndItemTargetting();
+ if (sucess)
+ timeTaken = TimeHelper.GetShootingTime(getPlayer, item!.Mass);
+ }
+ if (sucess)
+ {
+ world?.CurrentMap?.TargetCursor = null;
+ _bus.SendMessage(new(timeTaken, sucess));
+ }
+
+ return sucess;
+ }
+ else
+ {
+ _bus.SendMessage(new("Invalid target!"));
+ return false;
+ }
+ }
+ }
+}
+
diff --git a/src/MagusEngine/Actions/DropItemPlayerAction.cs b/src/MagusEngine/Actions/DropItemPlayerAction.cs
new file mode 100644
index 00000000..096d15e7
--- /dev/null
+++ b/src/MagusEngine/Actions/DropItemPlayerAction.cs
@@ -0,0 +1,31 @@
+using MagusEngine.Actions.Interfaces;
+using MagusEngine.Bus.MapBus;
+using MagusEngine.Bus.UiBus;
+using MagusEngine.Core.Entities;
+using MagusEngine.Services;
+using MagusEngine.Systems;
+using MagusEngine.Systems.Time;
+
+namespace MagusEngine.Actions
+{
+ public class DropItemPlayerAction : IExecuteAction
+ {
+ private readonly MessageBusService _bus;
+
+ public DropItemPlayerAction()
+ {
+ _bus = Locator.GetService();
+ }
+
+ public bool Execute(Universe world)
+ {
+ var controlledActor = (Actor)world!.CurrentMap!.ControlledEntitiy!;
+ _bus.SendMessage(new(controlledActor, item =>
+ {
+ var sucess = ActionManager.DropItem(item, controlledActor.Position, world.CurrentMap);
+ Locator.GetService().SendMessage(new(TimeHelper.Interact, sucess));
+ }));
+ return false;
+ }
+ }
+}
diff --git a/src/MagusEngine/Actions/EscapeMenuAction.cs b/src/MagusEngine/Actions/EscapeMenuAction.cs
new file mode 100644
index 00000000..bce923f3
--- /dev/null
+++ b/src/MagusEngine/Actions/EscapeMenuAction.cs
@@ -0,0 +1,31 @@
+using Arquimedes.Enumerators;
+using MagusEngine.Actions.Interfaces;
+using MagusEngine.Bus.UiBus;
+using MagusEngine.Services;
+using MagusEngine.Systems;
+using System.Net.NetworkInformation;
+
+namespace MagusEngine.Actions
+{
+ public class EscapeMenuAction : IExecuteAction
+ {
+ private readonly MessageBusService _bus;
+
+ public EscapeMenuAction()
+ {
+ _bus = Locator.GetService();
+ }
+
+ public bool Execute(Universe world)
+ {
+ var targetCursor = world.CurrentMap.TargetCursor;
+ if (targetCursor is not null)
+ {
+ targetCursor.EndTargetting();
+ return true;
+ }
+ _bus.SendMessage();
+ return true;
+ }
+ }
+}
diff --git a/src/MagusEngine/Actions/InteractAction.cs b/src/MagusEngine/Actions/InteractAction.cs
new file mode 100644
index 00000000..1a74e2a6
--- /dev/null
+++ b/src/MagusEngine/Actions/InteractAction.cs
@@ -0,0 +1,13 @@
+using MagusEngine.Actions.Interfaces;
+using MagusEngine.Systems;
+
+namespace MagusEngine.Actions
+{
+ public class InteractAction : IExecuteAction
+ {
+ public bool Execute(Universe world)
+ {
+ throw new System.NotImplementedException();
+ }
+ }
+}
diff --git a/src/MagusEngine/Actions/Interfaces/IExecuteAction.cs b/src/MagusEngine/Actions/Interfaces/IExecuteAction.cs
new file mode 100644
index 00000000..47da81db
--- /dev/null
+++ b/src/MagusEngine/Actions/Interfaces/IExecuteAction.cs
@@ -0,0 +1,9 @@
+using MagusEngine.Systems;
+
+namespace MagusEngine.Actions.Interfaces
+{
+ public interface IExecuteAction
+ {
+ bool Execute(Universe world);
+ }
+}
diff --git a/src/MagusEngine/Actions/LookAction.cs b/src/MagusEngine/Actions/LookAction.cs
new file mode 100644
index 00000000..b6129e3c
--- /dev/null
+++ b/src/MagusEngine/Actions/LookAction.cs
@@ -0,0 +1,27 @@
+using Arquimedes.Enumerators;
+using MagusEngine.Actions.Interfaces;
+using MagusEngine.Core.Entities;
+using MagusEngine.Systems;
+
+namespace MagusEngine.Actions
+{
+ public class LookAction : IExecuteAction
+ {
+ public bool Execute(Universe world)
+ {
+ var getPlayer = Find.ControlledEntity!;
+ var targetCursor = world!.CurrentMap!.TargetCursor ??= new Target(getPlayer.Position);
+
+ if (targetCursor.State == TargetState.LookMode)
+ {
+ targetCursor.EndTargetting();
+ }
+ else
+ {
+ targetCursor.StartTargetting();
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/src/MagusEngine/Actions/MoveAction.cs b/src/MagusEngine/Actions/MoveAction.cs
new file mode 100644
index 00000000..47040ea0
--- /dev/null
+++ b/src/MagusEngine/Actions/MoveAction.cs
@@ -0,0 +1,55 @@
+using MagusEngine.Actions.Interfaces;
+using MagusEngine.Core.Entities;
+using MagusEngine.Exceptions;
+using MagusEngine.Systems;
+
+namespace MagusEngine.Actions
+{
+ public class MoveAction : IExecuteAction
+ {
+ private readonly Point _delta;
+
+ public MoveAction(Point delta)
+ {
+ _delta = delta;
+ }
+
+ public bool Execute(Universe world)
+ {
+ if (world.CurrentMap is null)
+ return false;
+ var actor = (Actor)world.CurrentMap.ControlledEntitiy!;
+ if (world.CurrentMap.ControlledEntitiy is not Player)
+ {
+ if (world.CurrentMap.CheckForIndexOutOfBounds(world.CurrentMap.ControlledEntitiy!.Position + _delta))
+ return false;
+
+ var targetCursor = world.CurrentMap.TargetCursor;
+ int distance = HandleNonPlayerMoveAndReturnDistance(world, _delta, targetCursor);
+ return world.CurrentMap.PlayerExplored[world.CurrentMap.ControlledEntitiy.Position + _delta]
+ && distance <= targetCursor?.MaxDistance
+ && actor!.MoveBy(_delta);
+ }
+ return actor!.MoveBy(_delta);
+ }
+
+ private int HandleNonPlayerMoveAndReturnDistance(Universe world, Point delta, Target? targetCursor)
+ {
+ int distance = 0;
+ _ = world.CurrentMap ?? throw new NullValueException(nameof(world.CurrentMap));
+
+ if (world.CurrentMap.ControlledEntitiy == targetCursor?.Cursor)
+ {
+ _ = targetCursor ?? throw new NullValueException(nameof(targetCursor));
+
+ if (targetCursor.TravelPath is not null)
+ distance = targetCursor.TravelPath.LengthWithStart;
+ if (targetCursor.TravelPath is not null && targetCursor.TravelPath.LengthWithStart >= targetCursor.MaxDistance)
+ {
+ distance = world!.CurrentMap!.AStar!.ShortestPath(targetCursor.OriginCoord, world!.CurrentMap!.ControlledEntitiy!.Position + delta)!.Length;
+ }
+ }
+ return distance;
+ }
+ }
+}
diff --git a/src/MagusEngine/Actions/OpenCloseDoorAction.cs b/src/MagusEngine/Actions/OpenCloseDoorAction.cs
new file mode 100644
index 00000000..3a82420b
--- /dev/null
+++ b/src/MagusEngine/Actions/OpenCloseDoorAction.cs
@@ -0,0 +1,39 @@
+using MagusEngine.Actions.Interfaces;
+using MagusEngine.Bus.MapBus;
+using MagusEngine.Bus.UiBus;
+using MagusEngine.Core.Entities;
+using MagusEngine.Services;
+using MagusEngine.Systems;
+using MagusEngine.Systems.Time;
+
+namespace MagusEngine.Actions
+{
+ public class OpenCloseDoorAction : IExecuteAction
+ {
+ private readonly MessageBusService _bus;
+ private readonly Actor _actor;
+ private readonly bool _close;
+
+ public OpenCloseDoorAction(Actor actor, bool close)
+ {
+ _bus = Locator.GetService();
+ _actor = actor;
+ _close = close;
+ }
+
+ public bool Execute(Universe world)
+ {
+ if (_close)
+ {
+ bool sucess = ActionManager.CloseDoor(world.Player);
+ _bus.SendMessage(new(TimeHelper.Interact, sucess));
+ _bus.SendMessage();
+ return sucess;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+}
diff --git a/src/MagusEngine/Actions/OpenInventoryAction.cs b/src/MagusEngine/Actions/OpenInventoryAction.cs
new file mode 100644
index 00000000..2ed220c4
--- /dev/null
+++ b/src/MagusEngine/Actions/OpenInventoryAction.cs
@@ -0,0 +1,31 @@
+using System;
+using MagusEngine.Actions.Interfaces;
+using MagusEngine.Bus.UiBus;
+using MagusEngine.Core.Entities;
+using MagusEngine.Services;
+using MagusEngine.Systems;
+
+namespace MagusEngine.Actions
+{
+ public class OpenInventoryAction : IExecuteAction
+ {
+ private readonly MessageBusService _bus;
+ private readonly Action- ? _action;
+
+ public OpenInventoryAction(Action
- ? action = null)
+ {
+ _bus = Locator.GetService();
+ _action = action;
+ }
+
+ public bool Execute(Universe world)
+ {
+ Actor? controlledActor = (Actor?)world?.CurrentMap?.ControlledEntitiy;
+ if (controlledActor is null)
+ return false;
+
+ _bus.SendMessage(new(controlledActor, _action));
+ return true;
+ }
+ }
+}
diff --git a/src/MagusEngine/Actions/OpenWaitAction.cs b/src/MagusEngine/Actions/OpenWaitAction.cs
new file mode 100644
index 00000000..d8f97850
--- /dev/null
+++ b/src/MagusEngine/Actions/OpenWaitAction.cs
@@ -0,0 +1,24 @@
+using Arquimedes.Enumerators;
+using MagusEngine.Actions.Interfaces;
+using MagusEngine.Bus.UiBus;
+using MagusEngine.Services;
+using MagusEngine.Systems;
+
+namespace MagusEngine.Actions
+{
+ public class OpenWaitAction : IExecuteAction
+ {
+ private readonly MessageBusService _messageBus;
+
+ public OpenWaitAction()
+ {
+ _messageBus = Locator.GetService();
+ }
+
+ public bool Execute(Universe world)
+ {
+ _messageBus.SendMessage(new(WindowTag.Wait));
+ return true;
+ }
+ }
+}
diff --git a/src/MagusEngine/Actions/PickUpPlayerAction.cs b/src/MagusEngine/Actions/PickUpPlayerAction.cs
new file mode 100644
index 00000000..f2f46134
--- /dev/null
+++ b/src/MagusEngine/Actions/PickUpPlayerAction.cs
@@ -0,0 +1,29 @@
+using MagusEngine.Actions.Interfaces;
+using MagusEngine.Bus.MapBus;
+using MagusEngine.Core.Entities;
+using MagusEngine.Services;
+using MagusEngine.Systems;
+using MagusEngine.Systems.Time;
+
+namespace MagusEngine.Actions
+{
+ public class PickUpPlayerAction : IExecuteAction
+ {
+ private readonly Actor _actor;
+ private readonly MessageBusService _bus;
+
+ public PickUpPlayerAction(Actor actor)
+ {
+ _actor = actor;
+ _bus = Locator.GetService();
+ }
+
+ public bool Execute(Universe world)
+ {
+ Item item = world.CurrentMap!.GetEntityAt
- (world.CurrentMap.ControlledEntitiy!.Position)!;
+ bool sucess = ActionManager.PickUp(world.Player, item!);
+ _bus.SendMessage(new(TimeHelper.Interact, sucess));
+ return sucess;
+ }
+ }
+}
diff --git a/src/MagusEngine/Actions/PlanetMoveCameraAction.cs b/src/MagusEngine/Actions/PlanetMoveCameraAction.cs
new file mode 100644
index 00000000..dca43f3f
--- /dev/null
+++ b/src/MagusEngine/Actions/PlanetMoveCameraAction.cs
@@ -0,0 +1,32 @@
+using Arquimedes.Enumerators;
+using MagusEngine.Actions.Interfaces;
+using MagusEngine.Bus.UiBus;
+using MagusEngine.Services;
+using MagusEngine.Systems;
+
+namespace MagusEngine.Actions
+{
+ public class PlanetMoveCameraAction : IExecuteAction
+ {
+ private readonly Point _delta;
+ private readonly MessageBusService _bus;
+
+ public PlanetMoveCameraAction(Point delta)
+ {
+ _delta = delta;
+ _bus = Locator.GetService();
+ }
+
+ public bool Execute(Universe world)
+ {
+ if (!CurrentMapIsPlanetView(world))
+ return false;
+ _bus.SendMessage(new(_delta, WindowTag.Map));
+ // Must return false, because there isn't any movement of the actor
+ return false;
+ }
+
+ private static bool CurrentMapIsPlanetView(Universe world) =>
+ world.WorldMap != null && world.WorldMap.AssocietatedMap == world.CurrentMap && world.Player == null;
+ }
+}
diff --git a/src/MagusEngine/Actions/RestAction.cs b/src/MagusEngine/Actions/RestAction.cs
new file mode 100644
index 00000000..bfdaf537
--- /dev/null
+++ b/src/MagusEngine/Actions/RestAction.cs
@@ -0,0 +1,50 @@
+using MagusEngine.Actions.Interfaces;
+using MagusEngine.Bus.UiBus;
+using MagusEngine.Core.Entities;
+using MagusEngine.Core.Entities.Base;
+using MagusEngine.Services;
+using MagusEngine.Systems;
+using MagusEngine.Utils;
+
+namespace MagusEngine.Actions
+{
+ public class RestAction : IExecuteAction
+ {
+ private readonly MessageBusService _messageBus;
+ private readonly Actor _actor;
+
+ public RestAction(Actor actor)
+ {
+ _messageBus = Locator.GetService();
+ _actor = actor;
+ }
+
+ public bool Execute(Universe world)
+ {
+ Body bodyStats = _actor.Body;
+ //Mind mindStats = _actor.Mind;
+ Soul soulStats = _actor.Soul;
+
+ if (bodyStats.Stamina < bodyStats.MaxStamina || soulStats.CurrentMana < soulStats.MaxMana)
+ {
+ // calculate here the amount of time that it will take in turns to rest to full
+ double staminaDif, manaDif;
+
+ staminaDif = MathMagi.Round((bodyStats.MaxStamina - bodyStats.Stamina) / _actor.GetStaminaRegen());
+ manaDif = MathMagi.Round((soulStats.MaxMana - soulStats.CurrentMana) / _actor.GetManaRegen());
+
+ double totalTurnsWait = staminaDif + manaDif;
+
+ bool sus = ActionManager.WaitForNTurns((int)totalTurnsWait, _actor);
+
+ Locator.GetService().SendMessage(new($"You have rested for {totalTurnsWait} turns"));
+
+ return sus;
+ }
+
+ Locator.GetService().SendMessage(new("You have no need to rest"));
+
+ return false;
+ }
+ }
+}
diff --git a/src/MagusEngine/Actions/SpellCastingPlayerAction.cs b/src/MagusEngine/Actions/SpellCastingPlayerAction.cs
new file mode 100644
index 00000000..6418f5ad
--- /dev/null
+++ b/src/MagusEngine/Actions/SpellCastingPlayerAction.cs
@@ -0,0 +1,33 @@
+using Arquimedes.Enumerators;
+using MagusEngine.Actions.Interfaces;
+using MagusEngine.Bus.UiBus;
+using MagusEngine.Core.Entities;
+using MagusEngine.Core.Magic;
+using MagusEngine.Services;
+using MagusEngine.Systems;
+
+namespace MagusEngine.Actions
+{
+ public class SpellCastingPlayerAction : IExecuteAction
+ {
+ private readonly MessageBusService _bus;
+ private readonly Actor _actor;
+
+ public SpellCastingPlayerAction(Actor actor)
+ {
+ _bus = Locator.GetService();
+ _actor = actor;
+ }
+
+ public bool Execute(Universe world)
+ {
+ var getPlayer = (Actor)Find.ControlledEntity!;
+
+ var targetCursor = world!.CurrentMap!.TargetCursor ??= new Target(getPlayer.Position);
+ var magic = getPlayer.GetComponent();
+ _bus.SendMessage(new(magic.KnowSpells, getPlayer.Soul.CurrentMana, selectedSpell => targetCursor.OnSelectSpell(selectedSpell, getPlayer)));
+
+ return true;
+ }
+ }
+}
diff --git a/src/MagusEngine/Actions/ThrowItemAction.cs b/src/MagusEngine/Actions/ThrowItemAction.cs
new file mode 100644
index 00000000..a2e80c82
--- /dev/null
+++ b/src/MagusEngine/Actions/ThrowItemAction.cs
@@ -0,0 +1,41 @@
+using Arquimedes.Enumerators;
+using MagusEngine;
+using MagusEngine.Actions.Interfaces;
+using MagusEngine.Bus.UiBus;
+using MagusEngine.Core.Entities;
+using MagusEngine.Services;
+using MagusEngine.Systems;
+
+namespace MagusEngine.Actions
+{
+ public class ThrowItemAction : IExecuteAction
+ {
+ private Target? _targetCursor;
+ private readonly MessageBusService _bus;
+
+ public ThrowItemAction()
+ {
+ _bus = Locator.GetService();
+ }
+
+ public bool Execute(Universe world)
+ {
+ Actor? controlledActor = (Actor?)world?.CurrentMap?.ControlledEntitiy;
+ if (controlledActor is null)
+ return false;
+ _bus.SendMessage(new(controlledActor, item =>
+ {
+ _targetCursor ??= new Target(controlledActor.Position);
+ if (item is null)
+ {
+ _bus.SendMessage(new("No item selected!"));
+ return;
+ }
+ _targetCursor.OnSelectItem(item, controlledActor);
+ _bus.SendMessage(new(WindowTag.Inv));
+ controlledActor.Inventory.Remove(item);
+ }));
+ return true;
+ }
+ }
+}
diff --git a/src/MagusEngine/Actions/UpDownMovementAction.cs b/src/MagusEngine/Actions/UpDownMovementAction.cs
new file mode 100644
index 00000000..cbe01229
--- /dev/null
+++ b/src/MagusEngine/Actions/UpDownMovementAction.cs
@@ -0,0 +1,127 @@
+using MagusEngine.Actions.Interfaces;
+using MagusEngine.Bus;
+using MagusEngine.Bus.UiBus;
+using MagusEngine.Components.TilesComponents;
+using MagusEngine.Core.Entities;
+using MagusEngine.Core.MapStuff;
+using MagusEngine.Services;
+using MagusEngine.Systems;
+
+namespace MagusEngine.Actions
+{
+ public class UpDownMovementAction : IExecuteAction
+ {
+ private readonly int _zDelta;
+ private readonly MessageBusService _bus;
+
+ public UpDownMovementAction(int zDelta)
+ {
+ _zDelta = zDelta;
+ _bus = Locator.GetService();
+ }
+
+ public bool Execute(Universe world)
+ {
+ if (_zDelta > 0)
+ return UpMovement();
+ else
+ return DownMovement();
+ }
+
+ private bool UpMovement()
+ {
+ var point = Find.CurrentMap!.ControlledEntitiy!.Position;
+ bool possibleChangeMap = Find.Universe.PossibleChangeMap;
+ Furniture? possibleStairs = Find.CurrentMap?.GetEntityAt(point);
+ MagiMap? currentMap = Find.CurrentMap;
+
+ if (possibleChangeMap)
+ {
+ if (possibleStairs is not null && !Find.Universe.MapIsWorld()
+ && possibleStairs.MapIdConnection is not null)
+ {
+ MagiMap map = Universe.GetMapById(possibleStairs.MapIdConnection.Value)!;
+ _bus.SendMessage(new(map, map.GetRandomWalkableTile(), currentMap));
+
+ return true;
+ }
+ else if (!Find.Universe.MapIsWorld())
+ {
+ MagiMap map = Find.Universe.WorldMap.AssocietatedMap;
+ Point playerLastPos = Find.Universe.WorldMap.AssocietatedMap.LastPlayerPosition;
+ _bus.SendMessage(new(map, playerLastPos, currentMap));
+ Locator.GetService().SaveChunkInPos(Find.Universe.CurrentChunk,
+ Find.Universe.CurrentChunk.ToIndex(map.Width));
+ Find.Universe.CurrentChunk = null!;
+ return true;
+ }
+ else if (Find.Universe.MapIsWorld())
+ {
+ _bus.SendMessage(new("Can't go to the overworld since you are there!"));
+ return false;
+ }
+ else if (possibleStairs is null && !Find.Universe.MapIsWorld())
+ {
+ _bus.SendMessage(new("Can't go up here!"));
+ return false;
+ }
+ else
+ {
+ _bus.SendMessage(new("Can't exit the map!"));
+ return false;
+ }
+ }
+ else
+ {
+ _bus.SendMessage(new("You can't change the map right now!"));
+ return false;
+ }
+ }
+
+ private bool DownMovement()
+ {
+ var point = Find.CurrentMap!.ControlledEntitiy!.Position;
+ Furniture? possibleStairs = Find.CurrentMap?.GetEntityAt(point);
+ var possibleWorldTileHere = Find.CurrentMap?.GetComponentInTileAt(point);
+ MagiMap currentMap = Find.CurrentMap!;
+ if (possibleStairs?.MapIdConnection.HasValue == true)
+ {
+ MagiMap map = Universe.GetMapById(possibleStairs.MapIdConnection.Value)!;
+ _bus.SendMessage(new(map, map.GetRandomWalkableTile(), currentMap));
+ return true;
+ }
+ else if (possibleStairs is null && possibleWorldTileHere is null)
+ {
+ _bus.SendMessage(new("There is no way to go down from here!"));
+ return false;
+ }
+
+ if (possibleWorldTileHere?.Visited == false)
+ {
+ possibleWorldTileHere.Visited = true;
+
+ RegionChunk chunk = Find.Universe.GenerateChunck(point);
+ Find.Universe.CurrentChunk = chunk;
+ Locator.GetService().SendMessage(new(chunk.LocalMaps[0],
+ chunk.LocalMaps[0].GetRandomWalkableTile(), currentMap));
+ return true;
+ }
+ else if (possibleWorldTileHere?.Visited == true)
+ {
+ RegionChunk chunk = Find.Universe.GetChunckByPos(point)!;
+ Find.Universe.CurrentChunk = chunk;
+ // if entering the map again, set to update
+ chunk.SetMapsToUpdate();
+ Locator.GetService().SendMessage(new(chunk.LocalMaps[0],
+ chunk.LocalMaps[0].LastPlayerPosition, currentMap));
+
+ return true;
+ }
+ else
+ {
+ Locator.GetService().SendMessage(new("There is nowhere to go!"));
+ return false;
+ }
+ }
+ }
+}
diff --git a/src/MagusEngine/Actions/WaitAction.cs b/src/MagusEngine/Actions/WaitAction.cs
new file mode 100644
index 00000000..d4160679
--- /dev/null
+++ b/src/MagusEngine/Actions/WaitAction.cs
@@ -0,0 +1,26 @@
+using MagusEngine.Actions.Interfaces;
+using MagusEngine.Bus.MapBus;
+using MagusEngine.Services;
+using MagusEngine.Systems;
+
+namespace MagusEngine.Actions
+{
+ public class WaitAction : IExecuteAction
+ {
+ private readonly int _time;
+ private readonly MessageBusService _bus;
+
+ public WaitAction(int time)
+ {
+ _bus = Locator.GetService();
+ _time = time;
+ }
+
+ public bool Execute(Universe world)
+ {
+ Locator.GetService().SendMessage(new(_time, true));
+
+ return true;
+ }
+ }
+}
diff --git a/src/MagusEngine/Bus/StartGameMessage.cs b/src/MagusEngine/Bus/StartGameMessage.cs
index 6f02a1ad..7bb25825 100644
--- a/src/MagusEngine/Bus/StartGameMessage.cs
+++ b/src/MagusEngine/Bus/StartGameMessage.cs
@@ -9,7 +9,7 @@ public class StartGameMessage
public Universe? Universe { get; set; }
public bool TestGame { get; set; }
- public StartGameMessage(Player player, Universe universe = null)
+ public StartGameMessage(Player player, Universe? universe = null)
{
Player = player;
Universe = universe;
diff --git a/src/MagusEngine/Bus/UiBus/CloseWindowMessage.cs b/src/MagusEngine/Bus/UiBus/CloseWindowMessage.cs
new file mode 100644
index 00000000..3ed11858
--- /dev/null
+++ b/src/MagusEngine/Bus/UiBus/CloseWindowMessage.cs
@@ -0,0 +1,14 @@
+using Arquimedes.Enumerators;
+
+namespace MagusEngine.Bus.UiBus
+{
+ public class CloseWindowMessage
+ {
+ public WindowTag Tag { get; set; }
+
+ public CloseWindowMessage(WindowTag tag)
+ {
+ Tag = tag;
+ }
+ }
+}
diff --git a/src/MagusEngine/Bus/UiBus/InventoryActionBus.cs b/src/MagusEngine/Bus/UiBus/InventoryActionBus.cs
new file mode 100644
index 00000000..ee7d5782
--- /dev/null
+++ b/src/MagusEngine/Bus/UiBus/InventoryActionBus.cs
@@ -0,0 +1,17 @@
+using System;
+using MagusEngine.Core.Entities;
+
+namespace MagusEngine.Bus.UiBus
+{
+ public class InventoryActionBus
+ {
+ public Actor ActorInventory { get; }
+ public Action
- ? Action { get; }
+
+ public InventoryActionBus(Actor actorInventory, Action
- ? action)
+ {
+ ActorInventory = actorInventory;
+ Action = action;
+ }
+ }
+}
diff --git a/src/MagusEngine/Bus/UiBus/OpenSpellCastingWindowMessage.cs b/src/MagusEngine/Bus/UiBus/OpenSpellCastingWindowMessage.cs
new file mode 100644
index 00000000..60d14dc1
--- /dev/null
+++ b/src/MagusEngine/Bus/UiBus/OpenSpellCastingWindowMessage.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using MagusEngine.Core.Magic;
+
+namespace MagusEngine.Bus.UiBus
+{
+ public class OpenSpellCastingWindowMessage
+ {
+ public List Spells { get; set; } = null!;
+ public double CurrentMana { get; set; }
+ public Action? OnCast { get; set; }
+
+ public OpenSpellCastingWindowMessage(List spells, double currentMana, Action? onCast)
+ {
+ Spells = spells;
+ CurrentMana = currentMana;
+ OnCast = onCast;
+ }
+ }
+}
diff --git a/src/MagusEngine/Bus/UiBus/OpenWindowEvent.cs b/src/MagusEngine/Bus/UiBus/OpenWindowEvent.cs
new file mode 100644
index 00000000..f60e26cd
--- /dev/null
+++ b/src/MagusEngine/Bus/UiBus/OpenWindowEvent.cs
@@ -0,0 +1,14 @@
+using Arquimedes.Enumerators;
+
+namespace MagusEngine.Bus.UiBus
+{
+ public class OpenWindowEvent
+ {
+ public WindowTag Window { get; }
+
+ public OpenWindowEvent(WindowTag window)
+ {
+ Window = window;
+ }
+ }
+}
diff --git a/src/MagusEngine/Bus/UiBus/ScrollConsoleMessage.cs b/src/MagusEngine/Bus/UiBus/ScrollConsoleMessage.cs
new file mode 100644
index 00000000..10b5084b
--- /dev/null
+++ b/src/MagusEngine/Bus/UiBus/ScrollConsoleMessage.cs
@@ -0,0 +1,16 @@
+using Arquimedes.Enumerators;
+
+namespace MagusEngine.Bus.UiBus
+{
+ public class ScrollConsoleMessage
+ {
+ public Point Delta { get; }
+ public WindowTag Tag { get; }
+
+ public ScrollConsoleMessage(Point delta, WindowTag tag)
+ {
+ Delta = delta;
+ Tag = tag;
+ }
+ }
+}
diff --git a/src/MagusEngine/Components/EntityComponents/Ai/BasicAi.cs b/src/MagusEngine/Components/EntityComponents/Ai/BasicAi.cs
index dfdefdf4..d17b6a80 100644
--- a/src/MagusEngine/Components/EntityComponents/Ai/BasicAi.cs
+++ b/src/MagusEngine/Components/EntityComponents/Ai/BasicAi.cs
@@ -23,7 +23,7 @@ public virtual (bool sucess, long ticks) RunAi(MagiMap? map)
if (rng)
{
Locator.GetService().SendMessage(new($"The {_entity.Name} waits doing nothing..."));
- return (true, TimeHelper.Wait);
+ return (true, TimeHelper.OneSecond);
}
else
{
diff --git a/src/MagusEngine/Components/EntityComponents/Ai/MoveAndAttackAI.cs b/src/MagusEngine/Components/EntityComponents/Ai/MoveAndAttackAI.cs
index 28eaa498..69fd9b39 100644
--- a/src/MagusEngine/Components/EntityComponents/Ai/MoveAndAttackAI.cs
+++ b/src/MagusEngine/Components/EntityComponents/Ai/MoveAndAttackAI.cs
@@ -38,7 +38,7 @@ public MoveAndAttackAI(int perception)
}
else
{
- return (true, TimeHelper.Wait);
+ return (true, TimeHelper.OneSecond);
}
}
diff --git a/src/MagusEngine/Core/MapStuff/MagiMap.cs b/src/MagusEngine/Core/MapStuff/MagiMap.cs
index 52e308c2..38c46545 100644
--- a/src/MagusEngine/Core/MapStuff/MagiMap.cs
+++ b/src/MagusEngine/Core/MapStuff/MagiMap.cs
@@ -82,6 +82,7 @@ public MagiEntity? ControlledEntitiy
public List? Rooms { get; set; }
public EntityManager EntityRender { get; private set; } = [];
+ public Target? TargetCursor { get; set; }
#endregion Properties
diff --git a/src/MagusEngine/MagusEngine.csproj b/src/MagusEngine/MagusEngine.csproj
index 71b988ba..df3a4302 100644
--- a/src/MagusEngine/MagusEngine.csproj
+++ b/src/MagusEngine/MagusEngine.csproj
@@ -1,14 +1,13 @@
- net9.0
+ net10.0
enable
True
-
diff --git a/src/MagusEngine/Services/Factory/AnimationFactory.cs b/src/MagusEngine/Services/Factory/AnimationFactory.cs
index 0e43542c..bf45afc8 100644
--- a/src/MagusEngine/Services/Factory/AnimationFactory.cs
+++ b/src/MagusEngine/Services/Factory/AnimationFactory.cs
@@ -6,7 +6,7 @@
namespace MagusEngine.Services.Factory
{
- public sealed class AnimationFactory : GenericFactory
+ public sealed class AnimationFactory : GenericJsonFactory
{
public AnimationFactory()
{
diff --git a/src/MagusEngine/Services/Factory/Base/GenericFactory.cs b/src/MagusEngine/Services/Factory/Base/GenericJsonFactory.cs
similarity index 74%
rename from src/MagusEngine/Services/Factory/Base/GenericFactory.cs
rename to src/MagusEngine/Services/Factory/Base/GenericJsonFactory.cs
index 3874833f..ddd6413f 100644
--- a/src/MagusEngine/Services/Factory/Base/GenericFactory.cs
+++ b/src/MagusEngine/Services/Factory/Base/GenericJsonFactory.cs
@@ -5,7 +5,7 @@
namespace MagusEngine.Services.Factory.Base
{
- public abstract class GenericFactory
+ public abstract class GenericJsonFactory
{
protected Dictionary> Factories { get; } = [];
@@ -20,6 +20,18 @@ public virtual bool Register(string key, Func factory)
return Factories.TryAdd(key, factory);
}
+ public virtual bool Register(Enum key, Func factory)
+ {
+ var str = key.ToString();
+ if (string.IsNullOrWhiteSpace(str))
+ {
+ throw new ArgumentException("Key cannot be null or empty.", nameof(key));
+ }
+ ArgumentNullException.ThrowIfNull(factory);
+
+ return Factories.TryAdd(str, factory);
+ }
+
public virtual T GetValueFromKey(string key, JToken token)
{
return Factories.TryGetValue(key, out var factory)
diff --git a/src/MagusEngine/Services/Factory/SpellEffectFactory.cs b/src/MagusEngine/Services/Factory/SpellEffectFactory.cs
index 0d23a5a2..27996460 100644
--- a/src/MagusEngine/Services/Factory/SpellEffectFactory.cs
+++ b/src/MagusEngine/Services/Factory/SpellEffectFactory.cs
@@ -7,7 +7,7 @@
namespace MagusEngine.Services.Factory
{
- public sealed class SpellEffectFactory : GenericFactory
+ public sealed class SpellEffectFactory : GenericJsonFactory
{
public SpellEffectFactory()
{
diff --git a/src/MagusEngine/Services/MessageBusService.cs b/src/MagusEngine/Services/MessageBusService.cs
index bf8a62d7..778a1890 100644
--- a/src/MagusEngine/Services/MessageBusService.cs
+++ b/src/MagusEngine/Services/MessageBusService.cs
@@ -28,8 +28,8 @@ public void SendMessage(T obj) where T : notnull
[DebuggerStepThrough]
public void SendMessage() where T : notnull, new()
{
- var instance = Activator.CreateInstance(typeof(T));
- _messageBus?.Send((T)instance!);
+ var instance = Activator.CreateInstance();
+ _messageBus?.Send(instance);
}
///
diff --git a/src/MagusEngine/Systems/Find.cs b/src/MagusEngine/Systems/Find.cs
index 78a302e9..dbeef778 100644
--- a/src/MagusEngine/Systems/Find.cs
+++ b/src/MagusEngine/Systems/Find.cs
@@ -2,6 +2,7 @@
using Arquimedes.Enumerators;
using MagusEngine.Components.TilesComponents;
using MagusEngine.Core.Civ;
+using MagusEngine.Core.Entities;
using MagusEngine.Core.Entities.Base;
using MagusEngine.Core.MapStuff;
using MagusEngine.Core.WorldStuff.History;
@@ -33,7 +34,7 @@ public static void PopulateValues(AccumulatedHistory h, WorldTile[,] tiles)
{
history = h;
Tiles = tiles;
- Rules ??= new(DataManager.ListOfRules.GetEnumerableCollection());
+ Rules ??= [.. DataManager.ListOfRules.GetEnumerableCollection()];
}
public static Site? GetFigureStayingSiteIfAny(HistoricalFigure hf)
diff --git a/src/MagusEngine/Systems/Time/TimeHelper.cs b/src/MagusEngine/Systems/Time/TimeHelper.cs
index ab030ec3..6ed3d9b2 100644
--- a/src/MagusEngine/Systems/Time/TimeHelper.cs
+++ b/src/MagusEngine/Systems/Time/TimeHelper.cs
@@ -1,4 +1,5 @@
-using MagusEngine.Core.Entities;
+using System;
+using MagusEngine.Core.Entities;
using MagusEngine.Core.Entities.Base;
using MagusEngine.Core.Magic;
using MagusEngine.Core.MapStuff;
@@ -7,10 +8,10 @@ namespace MagusEngine.Systems.Time
{
public static class TimeHelper
{
- public const int Wait = 100;
+ public const int OneMoment = 10;
+ public const int OneSecond = 100;
public const int Interact = 50;
- public const int Wear = 200;
- public const int MagicalThings = 650;
+ public const int MagicalThingsTimeModifer = 650;
public const int AiFailed = -1;
public static long GetWalkTime(Actor actor, Tile tileToMove)
@@ -39,17 +40,33 @@ public static long GetWorldWalkTime(Actor actor, Tile tile)
public static long GetAttackTime(Actor actor, Attack attack)
{
- return (long)actor.GetAttackVelocity(attack) / ((int)attack.RecoverVelocity + 1);
+ // Improved attack time calculation with realistic physics
+ double baseTime = attack.PrepareVelocity + attack.RecoverVelocity;
+ double actorSpeed = actor.GetActorSpeed();
+ double skillBonus = Math.Max(0.5, 1.0 - (actor.GetRelevantAttackAbility(actor.WieldedItem()) * 0.01));
+
+ return (long)(baseTime * skillBonus / Math.Max(actorSpeed, 0.1));
+ }
+
+ public static long GetAttackTimeWithWeapon(Actor actor, Attack attack, Item weapon)
+ {
+ double baseTime = attack.PrepareVelocity + attack.RecoverVelocity;
+ double weaponWeight = weapon?.Mass ?? 1.0;
+ double actorSpeed = actor.GetActorSpeed();
+ double skillBonus = Math.Max(0.5, 1.0 - (actor.GetRelevantAttackAbility(weapon) * 0.01));
+ double strengthFactor = Math.Max(0.5, 1.0 + (actor.GetStrenght() - weaponWeight) * 0.01);
+
+ return (long)(baseTime * weaponWeight * skillBonus * strengthFactor / Math.Max(actorSpeed, 0.1));
}
public static long GetCastingTime(Actor actor, Spell spellCasted)
{
- return (long)(MagicalThings * (spellCasted.SpellLevel + (spellCasted.MagicCost * 5)) / actor.GetActorBaseCastingSpeed(spellCasted.ShapingAbility));
+ return (long)(MagicalThingsTimeModifer * (spellCasted.SpellLevel + (spellCasted.MagicCost * 5)) / actor.GetActorBaseCastingSpeed(spellCasted.ShapingAbility));
}
- public static long GetShootingTime(Player getPlayer, double mass)
+ public static long GetShootingTime(Actor getPlayer, double mass)
{
- return (long)(Wait + (mass * 10 / (getPlayer.GetActorSpeed())));
+ return (long)(OneSecond + (mass * 10 / getPlayer.GetActorSpeed()));
}
}
}
diff --git a/src/MagusEngine/Systems/Universe.cs b/src/MagusEngine/Systems/Universe.cs
index fa64a72b..df6757d6 100644
--- a/src/MagusEngine/Systems/Universe.cs
+++ b/src/MagusEngine/Systems/Universe.cs
@@ -398,7 +398,7 @@ private void ProcessAiTurn(uint entityId)
if (sucesses >= 0 && totalTicks <= 0)
{
- totalTicks = TimeHelper.Wait;
+ totalTicks = TimeHelper.OneSecond;
MagiLog.Log($"The {entity.Name} with id {entityId} has reported no success on AI");
}