Browse Source

feature(BuildCalc) Added reset button, can change micro delay, and can alter timing interval again

main
Jonathan McCaffrey 4 years ago
parent
commit
04c1718259
  1. 6
      .github/workflows/development.yml
  2. 6
      .github/workflows/production.yml
  3. 18
      .vscode/launch.json
  4. 78
      .vscode/tasks.json
  5. 14
      Components/Components.csproj
  6. 6
      Components/Display/DevOnlyComponent.razor
  7. 21
      Components/Display/PanelComponent.razor
  8. 9
      Components/Feedback/AlertComponent.razor
  9. 6
      Components/Form/FormCheckboxComponent.razor
  10. 6
      Components/Form/FormDisplayComponent.razor
  11. 3
      Components/Form/FormEscapeCodeComponent.razor
  12. 45
      Components/Form/FormGuessComponent.razor
  13. 6
      Components/Form/FormNumberComponent.razor
  14. 6
      Components/Form/FormSelectComponent.razor
  15. 9
      Components/Form/FormTextAreaComponent.razor
  16. 9
      Components/Form/FormTextComponent.razor
  17. 6
      Components/Info/InfoBodyComponent.razor
  18. 3
      Components/Inputs/ButtonComponent.razor
  19. 25
      Components/Inputs/ButtonGroupComponent.razor
  20. 3
      Components/Inputs/ButtonType.cs
  21. 1
      Components/Inputs/CodeLinkComponent.razor
  22. 1
      Components/Inputs/EditLinkComponent.razor
  23. 12
      Components/Inputs/EntityLabelComponent.razor
  24. 2
      Components/Inputs/EntityLabelComponent.razor.css
  25. 9
      Components/Layout/LayoutWithSidebarComponent.razor
  26. 10
      Components/MarkdownContent/MarkdownContent.razor
  27. 15
      Components/Navigation/DesktopNavLinkComponent.razor
  28. 10
      Components/Navigation/DesktopNavSectionComponent.razor
  29. 32
      Components/Navigation/MobileNavComponent.razor
  30. 18
      Components/Navigation/TabletNavComponent.razor
  31. 10
      Components/Shared/DisplayableContent.razor
  32. 10
      Components/Shared/DisplayableRoute.razor
  33. 6
      Contexts/Contexts.csproj
  34. 9
      Contexts/DatabaseContext.cs
  35. BIN
      IGP/Database.db
  36. 14
      IGP/IGP.csproj
  37. 16
      IGP/Index.razor
  38. 6
      IGP/Localizations.Designer.cs
  39. 6
      IGP/Localizations.resx
  40. 6
      IGP/Pages/Agile/AgilePage.razor
  41. 2
      IGP/Pages/Agile/Parts/SprintComponent.razor
  42. 141
      IGP/Pages/BuildCalculator/BuildCalculatorPage.razor
  43. 25
      IGP/Pages/BuildCalculator/Parts/ArmyComponent.razor
  44. 2
      IGP/Pages/BuildCalculator/Parts/BankComponent.razor
  45. 4
      IGP/Pages/BuildCalculator/Parts/BuildOrderComponent.razor
  46. 24
      IGP/Pages/BuildCalculator/Parts/ChartComponent.razor
  47. 9
      IGP/Pages/BuildCalculator/Parts/EntityClickViewComponent.razor
  48. 15
      IGP/Pages/BuildCalculator/Parts/FilterComponent.razor
  49. 25
      IGP/Pages/BuildCalculator/Parts/HighlightsComponent.razor
  50. 40
      IGP/Pages/BuildCalculator/Parts/HotkeyViewerComponent.razor
  51. 8
      IGP/Pages/BuildCalculator/Parts/InputPanelComponent.razor
  52. 41
      IGP/Pages/BuildCalculator/Parts/OptionsComponent.razor
  53. 43
      IGP/Pages/BuildCalculator/Parts/TimelineComponent.razor
  54. 17
      IGP/Pages/BuildCalculator/Parts/TimingComponent.razor
  55. 4
      IGP/Pages/Comparision/ComparisionPage.razor
  56. 31
      IGP/Pages/Database/Entity/Parts/EntityPassivesComponent.razor
  57. 2
      IGP/Pages/Database/Entity/Parts/EntityProductionComponent.razor
  58. 33
      IGP/Pages/Documentation/Parts/DocumentComponent.razor
  59. 20
      IGP/Pages/MakingOf/Parts/MakingOfColours.razor
  60. 10
      IGP/Pages/MakingOf/Parts/MakingOfNavigation.razor
  61. 26
      IGP/Pages/Notes/Parts/NoteComponent.razor
  62. 15
      IGP/Portals/ToastPortal.razor
  63. 3
      IGP/Program.cs
  64. 6
      IGP/Utils/Interval.cs
  65. 27
      IGP/Utils/Markdown.cs
  66. 7
      IGP/Utils/Project.cs
  67. 16
      IGP/_Imports.razor
  68. 6
      IGP/wwwroot/content/docs/cheat-sheet.md
  69. 15
      IGP/wwwroot/content/docs/project-data.md
  70. 29
      IGP/wwwroot/content/docs/setup.md
  71. 36
      IGP/wwwroot/content/notes/coop/holdout.md
  72. 177
      IGP/wwwroot/content/notes/settings/hotkeys.md
  73. 36
      IGP/wwwroot/content/notes/the-basics/armor-types.md
  74. 6
      IGP/wwwroot/content/notes/the-basics/economy-overview.md
  75. 6
      IGP/wwwroot/content/notes/the-basics/families-factions-and-immortal-vanguards.md
  76. 6
      IGP/wwwroot/content/notes/the-basics/immortal-spells-and-pyre.md
  77. 5
      IGP/wwwroot/content/notes/the-basics/timing-and-scouting.md
  78. 2
      IGP/wwwroot/css/app.css
  79. 2
      IGP/wwwroot/generated/AgileTaskModels.json
  80. 6
      IGP/wwwroot/service-worker.published.js
  81. 7
      IGP_Convert/Program.cs
  82. 2
      Model/Agile/AgileSprintModel.cs
  83. 6
      Model/Agile/AgileTaskModel.cs
  84. 75
      Model/BuildOrders/BuildOrderModel.cs
  85. 7
      Model/Doc/DocContentModel.cs
  86. 27
      Model/Economy/EconomyOverTimeModel.cs
  87. 310
      Model/Entity/Data/DATA.cs
  88. 34
      Model/Entity/Data/Ids_Entity.cs
  89. 18
      Model/Entity/EntityModel.cs
  90. 2
      Model/Entity/Parts/EntityProductionModel.cs
  91. 2
      Model/Entity/Parts/EntityVitalityModel.cs
  92. 2
      Model/Entity/Types/DescriptiveType.cs
  93. 4
      Model/Git/GitChangeModel.cs
  94. 12
      Model/Model.csproj
  95. 21
      Model/Notes/NoteContentModel.cs
  96. 2
      Model/Website/WebSectionModel.cs
  97. 17
      Services/Development/DocumentationService.cs
  98. 43
      Services/Development/GitService.cs
  99. 89
      Services/Development/NoteService.cs
  100. 78
      Services/IServices.cs
  101. Some files were not shown because too many files have changed in this diff Show More

6
.github/workflows/development.yml

@ -5,7 +5,7 @@ on:
branches: branches:
- develop - develop
pull_request: pull_request:
types: [opened, synchronize, reopened, closed] types: [ opened, synchronize, reopened, closed ]
branches: branches:
- develop - develop
@ -27,8 +27,8 @@ jobs:
action: "upload" action: "upload"
app_location: "IGP" app_location: "IGP"
api_location: "" api_location: ""
output_location: "./wwwroot" output_location: "./wwwroot"
close_pull_request_job: close_pull_request_job:
if: github.event_name == 'pull_request' && github.event.action == 'closed' if: github.event_name == 'pull_request' && github.event.action == 'closed'
runs-on: ubuntu-latest runs-on: ubuntu-latest

6
.github/workflows/production.yml

@ -5,7 +5,7 @@ on:
branches: branches:
- main - main
pull_request: pull_request:
types: [opened, synchronize, reopened, closed] types: [ opened, synchronize, reopened, closed ]
branches: branches:
- main - main
@ -27,8 +27,8 @@ jobs:
action: "upload" action: "upload"
app_location: "IGP" app_location: "IGP"
api_location: "" api_location: ""
output_location: "./wwwroot" output_location: "./wwwroot"
close_pull_request_job: close_pull_request_job:
if: github.event_name == 'pull_request' && github.event.action == 'closed' if: github.event_name == 'pull_request' && github.event.action == 'closed'
runs-on: ubuntu-latest runs-on: ubuntu-latest

18
.vscode/launch.json vendored

@ -1,11 +1,11 @@
{ {
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "Launch and Debug Standalone Blazor WebAssembly App", "name": "Launch and Debug Standalone Blazor WebAssembly App",
"type": "blazorwasm", "type": "blazorwasm",
"request": "launch", "request": "launch",
"cwd": "${workspaceFolder}/IGP" "cwd": "${workspaceFolder}/IGP"
} }
] ]
} }

78
.vscode/tasks.json vendored

@ -1,41 +1,41 @@
{ {
"version": "2.0.0", "version": "2.0.0",
"tasks": [ "tasks": [
{ {
"label": "build", "label": "build",
"command": "dotnet", "command": "dotnet",
"type": "process", "type": "process",
"args": [ "args": [
"build", "build",
"${workspaceFolder}/IGP/IGP.csproj", "${workspaceFolder}/IGP/IGP.csproj",
"/property:GenerateFullPaths=true", "/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary" "/consoleloggerparameters:NoSummary"
], ],
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "publish", "label": "publish",
"command": "dotnet", "command": "dotnet",
"type": "process", "type": "process",
"args": [ "args": [
"publish", "publish",
"${workspaceFolder}/IGP/IGP.csproj", "${workspaceFolder}/IGP/IGP.csproj",
"/property:GenerateFullPaths=true", "/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary" "/consoleloggerparameters:NoSummary"
], ],
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "watch", "label": "watch",
"command": "dotnet", "command": "dotnet",
"type": "process", "type": "process",
"args": [ "args": [
"watch", "watch",
"run", "run",
"--project", "--project",
"${workspaceFolder}/IGP/IGP.csproj" "${workspaceFolder}/IGP/IGP.csproj"
], ],
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
} }
] ]
} }

14
Components/Components.csproj

@ -7,15 +7,15 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DefineConstants>TRACE;NO_SQL</DefineConstants> <DefineConstants>TRACE;NO_SQL</DefineConstants>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' "> <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DefineConstants>TRACE;NO_SQL</DefineConstants> <DefineConstants>TRACE;NO_SQL</DefineConstants>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<SupportedPlatform Include="browser" /> <SupportedPlatform Include="browser"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -25,14 +25,14 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Inputs\" /> <Folder Include="Inputs\"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Model\Model.csproj" /> <ProjectReference Include="..\Model\Model.csproj"/>
<ProjectReference Include="..\Services\Services.csproj" /> <ProjectReference Include="..\Services\Services.csproj"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Remove="Inputs\" /> <None Remove="Inputs\"/>
</ItemGroup> </ItemGroup>
</Project> </Project>

6
Components/Display/DevOnlyComponent.razor

@ -1,4 +1,5 @@
@if (isOnDev) { @if (isOnDev)
{
<div class="devOnlyContainer"> <div class="devOnlyContainer">
<div class="devOnlyTitleContainer"> <div class="devOnlyTitleContainer">
<div class="devOnlyTitle"> <div class="devOnlyTitle">
@ -65,7 +66,8 @@
bool isOnDev; bool isOnDev;
protected override void OnInitialized() { protected override void OnInitialized()
{
isOnDev = NavigationManager.BaseUri.Contains("https://localhost"); isOnDev = NavigationManager.BaseUri.Contains("https://localhost");
} }

21
Components/Display/PanelComponent.razor

@ -0,0 +1,21 @@
<div class="panelDisplay">
@ChildContent
</div>
<style>
.panelDisplay {
border: 2px solid var(--paper-border);
padding: 20px;
background-color: var(--paper);
display: flex;
flex-direction: column;
flex-grow: 1;
}
</style>
@code {
[Parameter]
public RenderFragment ChildContent { get; set; } = default!;
}

9
Components/Feedback/AlertComponent.razor

@ -1,11 +1,12 @@
@using Model.Feedback <div class="alertContainer @Type.ToLower()">
<div class="alertContainer @Type.ToLower()"> @if (Title != null)
@if (Title != null) { {
<div class="alertTitle"> <div class="alertTitle">
@Title @Title
</div> </div>
} }
@if (Message != null) { @if (Message != null)
{
<div> <div>
@Message @Message
</div> </div>

6
Components/Form/FormCheckboxComponent.razor

@ -10,7 +10,8 @@
checked="@Value checked="@Value
"@onchange="OnChange"/> "@onchange="OnChange"/>
</div> </div>
@if (Info != "") { @if (Info != "")
{
<div class="formInfo"> <div class="formInfo">
@Info @Info
</div> </div>
@ -66,7 +67,8 @@
private string labelId = ""; private string labelId = "";
protected override void OnInitialized() { protected override void OnInitialized()
{
labelId = Label.ToLower().Replace(" ", "_"); labelId = Label.ToLower().Replace(" ", "_");
} }

6
Components/Form/FormDisplayComponent.razor

@ -1,5 +1,6 @@
<div class="displayContainer"> <div class="displayContainer">
@if (Label != "") { @if (Label != "")
{
<div class="formLabel"> <div class="formLabel">
@Label @Label
</div> </div>
@ -7,7 +8,8 @@
<div class="displayContent"> <div class="displayContent">
@Display @Display
</div> </div>
@if (Info != "") { @if (Info != "")
{
<div class="formInfo"> <div class="formInfo">
@Info @Info
</div> </div>

3
Components/Form/FormEscapeCodeComponent.razor

@ -20,7 +20,8 @@
@code { @code {
string Output = ""; string Output = "";
public void OnChange(ChangeEventArgs changeEventArgs) { public void OnChange(ChangeEventArgs changeEventArgs)
{
var encoded = HttpUtility.HtmlEncode(changeEventArgs.Value!.ToString()); var encoded = HttpUtility.HtmlEncode(changeEventArgs.Value!.ToString());
Output = encoded?.Replace("@", "@@")!; Output = encoded?.Replace("@", "@@")!;
Output = Output.Replace("\n", "<br />"); Output = Output.Replace("\n", "<br />");

45
Components/Form/FormGuessComponent.razor

@ -1,12 +1,12 @@
@using Services @using Model.MemoryTester
@using Services.Immortal @using Services.Immortal
@using Model.MemoryTester
@implements IDisposable @implements IDisposable
@inject IMemoryTesterService MemoryTesterService @inject IMemoryTesterService MemoryTesterService
<div class="formGuessContainer"> <div class="formGuessContainer">
@if (MemoryQuestion.Name != "") { @if (MemoryQuestion.Name != "")
{
<div class="formLabel"> <div class="formLabel">
@MemoryQuestion.Name @MemoryQuestion.Name
</div> </div>
@ -94,46 +94,57 @@
private string labelId = ""; private string labelId = "";
protected override void OnInitialized() { protected override void OnInitialized()
{
labelId = Label.ToLower().Replace(" ", "_") + MemoryQuestion.Id; labelId = Label.ToLower().Replace(" ", "_") + MemoryQuestion.Id;
MemoryTesterService.Subscribe(OnMemoryEvent); MemoryTesterService.Subscribe(OnMemoryEvent);
if (MemoryQuestion.IsRevealed) { if (MemoryQuestion.IsRevealed)
{
guess = MemoryQuestion.Answer.ToString(); guess = MemoryQuestion.Answer.ToString();
} }
OnRefresh(); OnRefresh();
} }
void IDisposable.Dispose() { void IDisposable.Dispose()
{
MemoryTesterService.Unsubscribe(OnMemoryEvent); MemoryTesterService.Unsubscribe(OnMemoryEvent);
} }
void OnMemoryEvent(MemoryTesterEvent memoryTesterEvent) { void OnMemoryEvent(MemoryTesterEvent memoryTesterEvent)
if (memoryTesterEvent == MemoryTesterEvent.OnVerify) { {
if (memoryTesterEvent == MemoryTesterEvent.OnVerify)
{
OnVerify(); OnVerify();
} }
if (memoryTesterEvent == MemoryTesterEvent.OnRefresh) { if (memoryTesterEvent == MemoryTesterEvent.OnRefresh)
{
OnRefresh(); OnRefresh();
} }
} }
protected override void OnAfterRender(bool firstRender) { protected override void OnAfterRender(bool firstRender)
if (MemoryQuestion.IsRevealed) { {
if (MemoryQuestion.IsRevealed)
{
guess = MemoryQuestion.Answer.ToString(); guess = MemoryQuestion.Answer.ToString();
} }
} }
void OnVerify() { void OnVerify()
{
IsSubmitted = true; IsSubmitted = true;
} }
void OnRefresh() { void OnRefresh()
{
guess = ""; guess = "";
if (MemoryQuestion.IsRevealed) { if (MemoryQuestion.IsRevealed)
{
guess = MemoryQuestion.Answer.ToString(); guess = MemoryQuestion.Answer.ToString();
} }
@ -141,10 +152,12 @@
IsSubmitted = false; IsSubmitted = false;
} }
void OnGuessChanged(ChangeEventArgs changeEventArgs) { void OnGuessChanged(ChangeEventArgs changeEventArgs)
{
guess = changeEventArgs.Value!.ToString()!; guess = changeEventArgs.Value!.ToString()!;
OnChange.InvokeAsync(new AnswerEventArgs { OnChange.InvokeAsync(new AnswerEventArgs
{
Name = MemoryQuestion.Name, Name = MemoryQuestion.Name,
IsCorrect = int.Parse(guess) == MemoryQuestion.Answer, IsCorrect = int.Parse(guess) == MemoryQuestion.Answer,
Guess = int.Parse(guess) Guess = int.Parse(guess)

6
Components/Form/FormNumberComponent.razor

@ -1,5 +1,6 @@
<div class="formNumberContainer"> <div class="formNumberContainer">
@if (FormLabelComponent != null) { @if (FormLabelComponent != null)
{
<FormLabelComponent>@FormLabelComponent</FormLabelComponent> <FormLabelComponent>@FormLabelComponent</FormLabelComponent>
} }
<div> <div>
@ -11,7 +12,8 @@
value="@Value" value="@Value"
@onchange="OnChange"/> @onchange="OnChange"/>
</div> </div>
@if (FormInfoComponent != null) { @if (FormInfoComponent != null)
{
<FormInfoComponent>@FormInfoComponent</FormInfoComponent> <FormInfoComponent>@FormInfoComponent</FormInfoComponent>
} }
</div> </div>

6
Components/Form/FormSelectComponent.razor

@ -1,5 +1,6 @@
<div style="display: flex; width: 100%; flex-direction: column; gap:6px;"> <div style="display: flex; width: 100%; flex-direction: column; gap:6px;">
@if (FormLabelComponent != null) { @if (FormLabelComponent != null)
{
<FormLabelComponent>@FormLabelComponent</FormLabelComponent> <FormLabelComponent>@FormLabelComponent</FormLabelComponent>
} }
<select style="background-color: #2C2E33; width: 100%; border:3px solid #A8ADB9; border-radius:1px; padding: 8px;" <select style="background-color: #2C2E33; width: 100%; border:3px solid #A8ADB9; border-radius:1px; padding: 8px;"
@ -7,7 +8,8 @@
@ChildContent @ChildContent
</select> </select>
@if (FormInfoComponent != null) { @if (FormInfoComponent != null)
{
<FormInfoComponent>@FormInfoComponent</FormInfoComponent> <FormInfoComponent>@FormInfoComponent</FormInfoComponent>
} }
</div> </div>

9
Components/Form/FormTextAreaComponent.razor

@ -1,5 +1,6 @@
<div class="form-text-container"> <div class="form-text-container">
@if (Label != "") { @if (Label != "")
{
<div class="form-label"> <div class="form-label">
@Label @Label
</div> </div>
@ -12,7 +13,8 @@
value="@Value" value="@Value"
@onchange="OnChange" /> @onchange="OnChange" />
</div> </div>
@if (Info != "") { @if (Info != "")
{
<div class="form-info"> <div class="form-info">
@Info @Info
</div> </div>
@ -83,7 +85,8 @@
private string labelId = ""; private string labelId = "";
protected override void OnInitialized() { protected override void OnInitialized()
{
labelId = Label.ToLower().Replace(" ", "_"); labelId = Label.ToLower().Replace(" ", "_");
} }

9
Components/Form/FormTextComponent.razor

@ -1,5 +1,6 @@
<div class="formContainer"> <div class="formContainer">
@if (Label != "") { @if (Label != "")
{
<div class="formLabel"> <div class="formLabel">
@Label @Label
</div> </div>
@ -13,7 +14,8 @@
id="@labelId" id="@labelId"
@onchange="OnChange"/> @onchange="OnChange"/>
</div> </div>
@if (Info != "") { @if (Info != "")
{
<div class="formInfo"> <div class="formInfo">
@Info @Info
</div> </div>
@ -68,7 +70,8 @@
private string labelId = ""; private string labelId = "";
protected override void OnInitialized() { protected override void OnInitialized()
{
labelId = Label.ToLower().Replace(" ", "_"); labelId = Label.ToLower().Replace(" ", "_");
} }

6
Components/Info/InfoBodyComponent.razor

@ -1,8 +1,10 @@
<div class="infoContainer"> <div class="infoContainer">
@if (InfoQuestionComponent != null) { @if (InfoQuestionComponent != null)
{
<div class="infoTitle">@InfoQuestionComponent</div> <div class="infoTitle">@InfoQuestionComponent</div>
} }
@if (InfoAnswerComponent != null) { @if (InfoAnswerComponent != null)
{
<div>@InfoAnswerComponent</div> <div>@InfoAnswerComponent</div>
} }
</div> </div>

3
Components/Inputs/ButtonComponent.razor

@ -45,7 +45,8 @@
[Parameter] [Parameter]
public ButtonType ButtonType { get; set; } = default!; public ButtonType ButtonType { get; set; } = default!;
private void ButtonClicked(EventArgs eventArgs) { private void ButtonClicked(EventArgs eventArgs)
{
OnClick.InvokeAsync(eventArgs); OnClick.InvokeAsync(eventArgs);
} }

25
Components/Inputs/ButtonGroupComponent.razor

@ -1,13 +1,15 @@
<div class="groupButtonContainerContainer"> <div class="groupButtonContainerContainer">
<div class="groupButtonContainer"> <div class="groupButtonContainer">
@foreach (var choice in Choices) { @foreach (var choice in Choices)
var styleClass = ""; {
if (choice.Equals(Choice)) { var styleClass = "";
styleClass = "selected"; if (choice.Equals(Choice))
{
styleClass = "selected";
}
<button @onclick="@(e => OnChangeChoice(choice))" class="groupChoiceButton @styleClass">@choice</button>
} }
<button @onclick="@(e => OnChangeChoice(choice))" class="groupChoiceButton @styleClass">@choice</button> </div>
}
</div>
</div> </div>
<style> <style>
@ -76,12 +78,15 @@
[Parameter] [Parameter]
public EventCallback<string> OnClick { get; set; } public EventCallback<string> OnClick { get; set; }
protected override void OnInitialized() { } protected override void OnInitialized()
{
}
void OnChangeChoice(string choice) void OnChangeChoice(string choice)
{ {
Choice = choice; Choice = choice;
OnClick.InvokeAsync(choice); OnClick.InvokeAsync(choice);
} }
} }

3
Components/Inputs/ButtonType.cs

@ -1,6 +1,7 @@
namespace Components.Inputs; namespace Components.Inputs;
public enum ButtonType { public enum ButtonType
{
Primary, // Positive Actions Primary, // Positive Actions
Secondary // Destruction Action Secondary // Destruction Action
} }

1
Components/Inputs/CodeLinkComponent.razor

@ -25,4 +25,5 @@
[Parameter] [Parameter]
public string Href { get; set; } = ""; public string Href { get; set; } = "";
} }

1
Components/Inputs/EditLinkComponent.razor

@ -25,4 +25,5 @@
[Parameter] [Parameter]
public string Href { get; set; } = ""; public string Href { get; set; } = "";
} }

12
Components/Inputs/EntityLabelComponent.razor

@ -1,10 +1,6 @@
@using Model.Entity @using Model.Entity
@using Services.Website
@using System.ComponentModel.DataAnnotations
@using Model.Entity.Data @using Model.Entity.Data
@using Services @inject IEntityDialogService entityDialogService
@inject IEntityDialogService entityDialogService
@if (EntityId == null) @if (EntityId == null)
@ -17,8 +13,9 @@ else
} }
@code { @code {
[Parameter] public string EntityId { get; set; } = default!; [Parameter]
public string EntityId { get; set; } = default!;
private EntityModel Entity => DATA.Get()[EntityId]; private EntityModel Entity => DATA.Get()[EntityId];
@ -26,4 +23,5 @@ else
{ {
entityDialogService.AddDialog(EntityId); entityDialogService.AddDialog(EntityId);
} }
} }

2
Components/Inputs/EntityLabelComponent.razor.css

@ -1,7 +1,7 @@
 
.entityLabel { .entityLabel {
font-weight: bolder; font-weight: bolder;
box-shadow: 1px 1px 0 0 rgba(0,0,0,0.2); box-shadow: 1px 1px 0 0 rgba(0, 0, 0, 0.2);
padding-right: 4px; padding-right: 4px;
} }

9
Components/Layout/LayoutWithSidebarComponent.razor

@ -1,5 +1,4 @@
 <div class="layoutWithSidebar">
<div class="layoutWithSidebar">
<div class="layoutSidebar"> <div class="layoutSidebar">
@Sidebar @Sidebar
</div> </div>
@ -49,10 +48,12 @@
</style> </style>
@code { @code {
[Parameter] [Parameter]
public RenderFragment Sidebar { get; set; } = default!; public RenderFragment Sidebar { get; set; } = default!;
[Parameter] [Parameter]
public RenderFragment Content { get; set; } = default!; public RenderFragment Content { get; set; } = default!;
} }

10
Components/MarkdownContent/MarkdownContent.razor

@ -1,6 +1,8 @@
@((MarkupString)MarkdownText) @using Markdig
@((MarkupString)MarkdownText)
@code { @code {
[Inject] [Inject]
protected HttpClient Http { get; set; } = default!; protected HttpClient Http { get; set; } = default!;
@ -9,7 +11,9 @@
private string MarkdownText { get; set; } = ""; private string MarkdownText { get; set; } = "";
protected override async Task OnInitializedAsync() { protected override async Task OnInitializedAsync()
MarkdownText = Markdig.Markdown.ToHtml(await Http.GetStringAsync($"markdown/{MarkdownFileName}.md")); {
MarkdownText = Markdown.ToHtml(await Http.GetStringAsync($"markdown/{MarkdownFileName}.md"));
} }
} }

15
Components/Navigation/DesktopNavLinkComponent.razor

@ -1,14 +1,16 @@
@inject INavigationService navigationService; @inject INavigationService navigationService;
@inject NavigationManager navigationManager; @inject NavigationManager navigationManager;
@if (isOnPage) { @if (isOnPage)
{
<NavLink href="@Page.Href" class="desktopNavLink navSelected"> <NavLink href="@Page.Href" class="desktopNavLink navSelected">
<div class="navName"> <div class="navName">
@Page.Name @Page.Name
</div> </div>
</NavLink> </NavLink>
} }
else { else
{
<NavLink @onclick="() => navigationService.ChangeNavigationState(NavigationStateType.Default)" href="@Page.Href" class="desktopNavLink"> <NavLink @onclick="() => navigationService.ChangeNavigationState(NavigationStateType.Default)" href="@Page.Href" class="desktopNavLink">
<div class="navName"> <div class="navName">
@Page.Name @Page.Name
@ -67,7 +69,8 @@ else {
bool isOnPage = false; bool isOnPage = false;
protected override Task OnParametersSetAsync() { protected override Task OnParametersSetAsync()
{
var uri = navigationManager.Uri.Remove(0, navigationManager.BaseUri.Count()).ToLower(); var uri = navigationManager.Uri.Remove(0, navigationManager.BaseUri.Count()).ToLower();
isOnPage = Page.Href.ToLower().Equals(uri); isOnPage = Page.Href.ToLower().Equals(uri);
@ -75,11 +78,13 @@ else {
} }
void OnNavigationChanged() { void OnNavigationChanged()
{
StateHasChanged(); StateHasChanged();
} }
void OnBack() { void OnBack()
{
navigationService.Back(); navigationService.Back();
} }

10
Components/Navigation/DesktopNavSectionComponent.razor

@ -1,8 +1,8 @@
@using Model.Website <div class="sectionContainer">
@foreach (var childPage in Section.WebPageModels)
<div class="sectionContainer"> {
@foreach (var childPage in Section.WebPageModels) { if (childPage.IsPrivate.Equals("True"))
if (childPage.IsPrivate.Equals("True")) { {
continue; continue;
} }
<DesktopNavLinkComponent Page=childPage></DesktopNavLinkComponent> <DesktopNavLinkComponent Page=childPage></DesktopNavLinkComponent>

32
Components/Navigation/MobileNavComponent.razor

@ -1,9 +1,7 @@
@using Model.Website <div class="mobileFooter">
@using Microsoft.EntityFrameworkCore
<div class="mobileFooter">
<div class="mobileNavSectionsContainer"> <div class="mobileNavSectionsContainer">
@foreach (var webSection in WebSections) { @foreach (var webSection in WebSections)
{
<div class="mobileNavSectionButton" @onclick="() => OnSectionClicked(webSection)" @onclick:preventDefault="true" @onclick:stopPropagation="true"> <div class="mobileNavSectionButton" @onclick="() => OnSectionClicked(webSection)" @onclick:preventDefault="true" @onclick:stopPropagation="true">
<div class="mobileNavSectionButtonText"> <div class="mobileNavSectionButtonText">
@webSection?.Name @webSection?.Name
@ -15,14 +13,17 @@
<div class="fullPageButton @(selectedSection != null)" @onclick="OnPageClicked" @onclick:stopPropagation="false" @onclick:preventDefault="false"> <div class="fullPageButton @(selectedSection != null)" @onclick="OnPageClicked" @onclick:stopPropagation="false" @onclick:preventDefault="false">
</div> </div>
@if (selectedSection != null) { @if (selectedSection != null)
{
List<WebPageModel?> webPages = (from page in WebPages List<WebPageModel?> webPages = (from page in WebPages
where page.WebSectionModelId == selectedSection.Id where page.WebSectionModelId == selectedSection.Id
select page).ToList()!; select page).ToList()!;
<div class="mobileNavPagesContainer"> <div class="mobileNavPagesContainer">
@foreach (var webPage in webPages) { @foreach (var webPage in webPages)
if (webPage!.IsPrivate.Equals("True")) { {
if (webPage!.IsPrivate.Equals("True"))
{
continue; continue;
} }
<div class="mobileNavPageButton" @onclick="() => OnPageLinkClicked(webPage)" @onclick:preventDefault="true" @onclick:stopPropagation="true"> <div class="mobileNavPageButton" @onclick="() => OnPageLinkClicked(webPage)" @onclick:preventDefault="true" @onclick:stopPropagation="true">
@ -143,7 +144,7 @@
[Parameter] [Parameter]
public List<WebPageModel> WebPages { get; set; } = default!; public List<WebPageModel> WebPages { get; set; } = default!;
#else #else
[Parameter] [Parameter]
public DbSet<WebSectionModel> WebSections { get; set; } public DbSet<WebSectionModel> WebSections { get; set; }
@ -151,27 +152,30 @@
[Parameter] [Parameter]
public DbSet<WebPageModel> WebPages { get; set; } public DbSet<WebPageModel> WebPages { get; set; }
#endif #endif
[Inject] [Inject]
public NavigationManager NavigationManager { get; set; } = default!; public NavigationManager NavigationManager { get; set; } = default!;
private WebSectionModel? selectedSection; private WebSectionModel? selectedSection;
private WebPageModel? selectedPage; private WebPageModel? selectedPage;
void OnSectionClicked(WebSectionModel? webSection) { void OnSectionClicked(WebSectionModel? webSection)
{
selectedSection = webSection; selectedSection = webSection;
} }
void OnPageLinkClicked(WebPageModel? webPage) { void OnPageLinkClicked(WebPageModel? webPage)
{
selectedPage = webPage; selectedPage = webPage;
selectedSection = null; selectedSection = null;
NavigationManager.NavigateTo(webPage?.Href!); NavigationManager.NavigateTo(webPage?.Href!);
} }
void OnPageClicked(EventArgs eventArgs) { void OnPageClicked(EventArgs eventArgs)
{
selectedPage = null; selectedPage = null;
selectedSection = null; selectedSection = null;
} }

18
Components/Navigation/TabletNavComponent.razor

@ -19,7 +19,8 @@
<div class="tabletNav @navOpen"> <div class="tabletNav @navOpen">
@foreach (var webSection in WebSections) { @foreach (var webSection in WebSections)
{
var pages = (from page in WebPages var pages = (from page in WebPages
where page.WebSectionModelId == webSection.Id where page.WebSectionModelId == webSection.Id
select page).ToList(); select page).ToList();
@ -30,8 +31,10 @@
</div> </div>
<div class="tabletNavItems"> <div class="tabletNavItems">
@foreach (var webPage in pages) { @foreach (var webPage in pages)
if (webPage.IsPrivate.Equals("True")) { {
if (webPage.IsPrivate.Equals("True"))
{
continue; continue;
} }
<NavLink href="@webPage.Href" class="tabletNavItem" @onclick="OnPageClicked"> <NavLink href="@webPage.Href" class="tabletNavItem" @onclick="OnPageClicked">
@ -139,7 +142,7 @@
</style> </style>
@code { @code {
#if NO_SQL #if NO_SQL
[Parameter] [Parameter]
public List<WebSectionModel> WebSections { get; set; } = default!; public List<WebSectionModel> WebSections { get; set; } = default!;
@ -156,15 +159,16 @@
#endif #endif
bool navOpen = true; bool navOpen = true;
void OnNavClicked(EventArgs eventArgs) { void OnNavClicked(EventArgs eventArgs)
{
navOpen = !navOpen; navOpen = !navOpen;
} }
void OnPageClicked(EventArgs eventArgs) { void OnPageClicked(EventArgs eventArgs)
{
navOpen = false; navOpen = false;
} }

10
Components/Shared/DisplayableContent.razor

@ -1,6 +1,5 @@
@using Model.Website.Enums @if (isDisplayable)
@using Model.Website {
@if (isDisplayable) {
@ChildContent @ChildContent
} }
@ -10,14 +9,15 @@
public RenderFragment ChildContent { get; set; } = default!; public RenderFragment ChildContent { get; set; } = default!;
[Parameter] [Parameter]
public WebDeploymentType DeploymentType { get; set; } = default!; public WebDeploymentType DeploymentType { get; set; }
[Inject] [Inject]
public NavigationManager MyNavigationManager { get; set; } = default!; public NavigationManager MyNavigationManager { get; set; } = default!;
bool isDisplayable; bool isDisplayable;
protected override void OnInitialized() { protected override void OnInitialized()
{
isDisplayable = DeploymentType == WebDeploymentModel.DeploymentType; isDisplayable = DeploymentType == WebDeploymentModel.DeploymentType;
} }

10
Components/Shared/DisplayableRoute.razor

@ -1,8 +1,9 @@
@using Model.Website @if (isDisplayable)
@if (isDisplayable) { {
@ChildContent @ChildContent
} }
else { else
{
<LayoutView Layout="@typeof(MainLayout)"> <LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p> <p>Sorry, there's nothing at this address.</p>
</LayoutView> </LayoutView>
@ -18,7 +19,8 @@ else {
bool isDisplayable; bool isDisplayable;
protected override void OnInitialized() { protected override void OnInitialized()
{
var page = MyNavigationManager.Uri.Remove(0, MyNavigationManager.BaseUri.Length); var page = MyNavigationManager.Uri.Remove(0, MyNavigationManager.BaseUri.Length);
isDisplayable = WebDeploymentModel.Get().Contains(page); isDisplayable = WebDeploymentModel.Get().Contains(page);
} }

6
Contexts/Contexts.csproj

@ -7,11 +7,11 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DefineConstants>TRACE;</DefineConstants> <DefineConstants>TRACE;</DefineConstants>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' "> <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DefineConstants>TRACE;</DefineConstants> <DefineConstants>TRACE;</DefineConstants>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@ -23,7 +23,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Model\Model.csproj" /> <ProjectReference Include="..\Model\Model.csproj"/>
</ItemGroup> </ItemGroup>
</Project> </Project>

9
Contexts/DatabaseContext.cs

@ -1,18 +1,19 @@
#if NO_SQL #if NO_SQL
#else #else
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Model.Doc; using Model.Doc;
using Model.Git;
using Model.Notes; using Model.Notes;
using Model.Website; using Model.Website;
using Model.Git;
using Model.Work.Tasks; using Model.Work.Tasks;
namespace Contexts; namespace Contexts;
public class DatabaseContext : DbContext { public class DatabaseContext : DbContext
public DatabaseContext(DbContextOptions<DatabaseContext> options) : base(options) { {
public DatabaseContext(DbContextOptions<DatabaseContext> options) : base(options)
{
Database.EnsureCreated(); Database.EnsureCreated();
} }

BIN
IGP/Database.db

Binary file not shown.

14
IGP/IGP.csproj

@ -62,13 +62,13 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<_ContentIncludedByDefault Remove="wwwroot\content\notes\coop\image\notes\map-lostprovince\Map_LostProvince.png" /> <_ContentIncludedByDefault Remove="wwwroot\content\notes\coop\image\notes\map-lostprovince\Map_LostProvince.png" />
<_ContentIncludedByDefault Remove="wwwroot\image\notes\coop-holdout\CoopBaseLarge.png" /> <_ContentIncludedByDefault Remove="wwwroot\image\notes\coop-holdout\CoopBaseLarge.png" />
<_ContentIncludedByDefault Remove="wwwroot\image\notes\coop-holdout\DefendPoints.png" /> <_ContentIncludedByDefault Remove="wwwroot\image\notes\coop-holdout\DefendPoints.png" />
<_ContentIncludedByDefault Remove="wwwroot\image\notes\coop-holdout\EnemySpawns.png" /> <_ContentIncludedByDefault Remove="wwwroot\image\notes\coop-holdout\EnemySpawns.png" />
<_ContentIncludedByDefault Remove="wwwroot\image\notes\coop-holdout\Multipliers.png" /> <_ContentIncludedByDefault Remove="wwwroot\image\notes\coop-holdout\Multipliers.png" />
<_ContentIncludedByDefault Remove="wwwroot\image\notes\coop-holdout\OpenBases.png" /> <_ContentIncludedByDefault Remove="wwwroot\image\notes\coop-holdout\OpenBases.png" />
<_ContentIncludedByDefault Remove="wwwroot\image\notes\coop-holdout\Pyre.png" /> <_ContentIncludedByDefault Remove="wwwroot\image\notes\coop-holdout\Pyre.png" />
</ItemGroup> </ItemGroup>
</Project> </Project>

16
IGP/Index.razor

@ -1,19 +1,5 @@
@page "/" @page "/"
@using Microsoft.Extensions.Localization
@layout PageLayout @layout PageLayout
<HomePage/>
@inject IStringLocalizer<Localizations> locale
<DevOnlyComponent>
<DocumentationIndexPage></DocumentationIndexPage>
@locale["Greeting"].Value
@locale["Greeting"]
@locale["Greeting"].Name
@locale["Greeting"].ResourceNotFound
</DevOnlyComponent>
<HomePage></HomePage>

6
IGP/Localizations.Designer.cs generated

@ -104,5 +104,11 @@ namespace IGP {
return ResourceManager.GetString("Tooltip Hotkey Info", resourceCulture); return ResourceManager.GetString("Tooltip Hotkey Info", resourceCulture);
} }
} }
internal static string Tooltip_Options_Info {
get {
return ResourceManager.GetString("Tooltip Options Info", resourceCulture);
}
}
} }
} }

6
IGP/Localizations.resx

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<root> <root>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root" <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"
id="root"
xmlns=""> xmlns="">
<xsd:element name="root" msdata:IsDataSet="true"> <xsd:element name="root" msdata:IsDataSet="true">
@ -66,4 +67,7 @@ You can also use the default Immortal hotkeys, but the above hotkey UI must have
Additionally, more entities will appear as you build the required technology. You can click or press ` to remove the last made entity. &lt;i&gt;But you cannot remove the starting entities at interval 0.&lt;/i&gt;</value> Additionally, more entities will appear as you build the required technology. You can click or press ` to remove the last made entity. &lt;i&gt;But you cannot remove the starting entities at interval 0.&lt;/i&gt;</value>
</data> </data>
<data name="Tooltip Options Info" xml:space="preserve">
<value>Misc calculator controls.</value>
</data>
</root> </root>

6
IGP/Pages/Agile/AgilePage.razor

@ -17,7 +17,7 @@ else
@foreach (var sprint in agileService.AgileSprintModels! @foreach (var sprint in agileService.AgileSprintModels!
.OrderBy(e => e.EndDate).Reverse()) .OrderBy(e => e.EndDate).Reverse())
{ {
<details class="sprintDisplayContainer @sprint.GetSprintType().ToLower()" <details class="sprintDisplayContainer @sprint.GetSprintType().ToLower()"
open="@(sprint.GetSprintType() == SprintType.Current)"> open="@(sprint.GetSprintType() == SprintType.Current)">
<summary class="sprintSummary"> <summary class="sprintSummary">
<div class="sprintTitle">@sprint.Name</div> <div class="sprintTitle">@sprint.Name</div>
@ -91,8 +91,8 @@ else
void HasChanged() void HasChanged()
{ {
if(!agileService.IsLoaded()) return; if (!agileService.IsLoaded()) return;
backlog.Clear(); backlog.Clear();
foreach (var task in agileService.AgileTaskModels!) foreach (var task in agileService.AgileTaskModels!)

2
IGP/Pages/Agile/Parts/SprintComponent.razor

@ -11,7 +11,7 @@
<div class="tasksContainer"> <div class="tasksContainer">
@if (AgileSprint.AgileTaskModels.Count > 0) @if (AgileSprint.AgileTaskModels.Count > 0)
{ {
@foreach (var task in AgileSprint.AgileTaskModels.OrderBy(x=>x.OrderPriority)) @foreach (var task in AgileSprint.AgileTaskModels.OrderBy(x => x.OrderPriority))
{ {
<div class="taskContainer @task.Status.ToLower() @task.Task.ToLower()"> <div class="taskContainer @task.Status.ToLower() @task.Task.ToLower()">
<div class="taskName">@task.Name</div> <div class="taskName">@task.Name</div>

141
IGP/Pages/BuildCalculator/BuildCalculatorPage.razor

@ -10,7 +10,6 @@
@inject ITimingService timingService @inject ITimingService timingService
@page "/build-calculator" @page "/build-calculator"
@using Microsoft.Extensions.Localization
@implements IDisposable @implements IDisposable
@ -20,89 +19,93 @@
<AlertComponent Type="@SeverityType.Warning"> <AlertComponent Type="@SeverityType.Warning">
<Title>Work In Progress and Not Fully Tested</Title> <Title>Work In Progress and Not Fully Tested</Title>
<Message> <Message>
Currently not considering training queue times. Lacking error toasts for invalid actions. Performance needs to be optimized. Calculations haven't been thoroughly compared against real gameplay. Added a 2 second delay to actions to account for casual micro (will probably tweak later). Currently not considering training queue times.
</Message> </Message>
</AlertComponent> </AlertComponent>
<ContentDividerComponent></ContentDividerComponent> <ContentDividerComponent></ContentDividerComponent>
<div class="calculatorGrid"> <div class="calculatorGrid">
<div class="gridItem" style="grid-area: timing;">
<div style="grid-area: timing;" class="gridItem"> <ButtonComponent OnClick="OnResetClicked">Clear Build Order</ButtonComponent>
<InfoTooltipComponent InfoText="@locale["Tooltip Timing Info"]"> <PanelComponent>
<InfoTooltipComponent InfoText="@locale["Tooltip Timing Info"]">
<TimingComponent></TimingComponent> <TimingComponent></TimingComponent>
</InfoTooltipComponent> </InfoTooltipComponent>
</PanelComponent>
</div> </div>
@if (true) <div class="gridItem" style="grid-area: chart;">
{ <PanelComponent>
<div style="grid-area: chart;" class="gridItem">
<InfoTooltipComponent InfoText="@locale["Tooltip Chart Info"]"> <InfoTooltipComponent InfoText="@locale["Tooltip Chart Info"]">
<ChartComponent></ChartComponent> <ChartComponent></ChartComponent>
</InfoTooltipComponent> </InfoTooltipComponent>
</div> </PanelComponent>
} </div>
<div style="grid-area: filter;" class="gridItem"> <div class="gridItem" style="grid-area: filter;">
<InfoTooltipComponent InfoText="@locale["Tooltip Filter Info"]"> <PanelComponent>
<FilterComponent></FilterComponent> <InfoTooltipComponent InfoText="@locale["Tooltip Filter Info"]">
</InfoTooltipComponent> <FilterComponent></FilterComponent>
</InfoTooltipComponent>
</PanelComponent>
<PanelComponent>
<InfoTooltipComponent InfoText="@locale["Tooltip Options Info"]">
<OptionsComponent></OptionsComponent>
</InfoTooltipComponent>
</PanelComponent>
</div> </div>
@if (true) <div class="gridItem" style="grid-area: view;">
{ <PanelComponent>
<div style="grid-area: view;" class="gridItem">
<InfoTooltipComponent InfoText="@locale["Tooltip Entity Info"]"> <InfoTooltipComponent InfoText="@locale["Tooltip Entity Info"]">
<EntityClickViewComponent/> <EntityClickViewComponent/>
</InfoTooltipComponent> </InfoTooltipComponent>
</div>
}
@if (true) </PanelComponent>
{ </div>
<div style="grid-area: bank;" class="gridItem">
<div class="gridItem" style="grid-area: bank;">
<PanelComponent>
<InfoTooltipComponent InfoText="@locale["Tooltip Bank Info"]"> <InfoTooltipComponent InfoText="@locale["Tooltip Bank Info"]">
<BankComponent></BankComponent> <BankComponent></BankComponent>
</InfoTooltipComponent> </InfoTooltipComponent>
</div> </PanelComponent>
} </div>
@if (true) <div class="gridItem" style="grid-area: army;">
{ <PanelComponent>
<div style="grid-area: army;" class="gridItem">
<InfoTooltipComponent InfoText="@locale["Tooltip Army Info"]"> <InfoTooltipComponent InfoText="@locale["Tooltip Army Info"]">
<ArmyComponent></ArmyComponent> <ArmyComponent></ArmyComponent>
</InfoTooltipComponent> </InfoTooltipComponent>
</div> </PanelComponent>
} </div>
<div class="gridItem gridKeys"> <div class="gridItem gridKeys">
<PanelComponent>
<InfoTooltipComponent InfoText="@locale["Tooltip Hotkey Info"]"> <InfoTooltipComponent InfoText="@locale["Tooltip Hotkey Info"]">
<HotkeyViewerComponent Size="80"></HotkeyViewerComponent>
<HotkeyViewerComponent Size="80"></HotkeyViewerComponent> </InfoTooltipComponent>
</InfoTooltipComponent> </PanelComponent>
</div> </div>
@if (true) <div class="gridItem" style="grid-area: highlights;">
{ <PanelComponent>
<div style="grid-area: highlights;" class="gridItem">
<InfoTooltipComponent InfoText="@locale["Tooltip Highlights Info"]"> <InfoTooltipComponent InfoText="@locale["Tooltip Highlights Info"]">
<HighlightsComponent></HighlightsComponent> <HighlightsComponent></HighlightsComponent>
</InfoTooltipComponent> </InfoTooltipComponent>
</div> </PanelComponent>
} </div>
@if (true)
{ <div class="gridItem" style="grid-area: buildorder;">
<div style="grid-area: buildorder;" class="gridItem"> <PanelComponent>
<InfoTooltipComponent InfoText="@locale["Tooltip BuildOrder Info"]"> <InfoTooltipComponent InfoText="@locale["Tooltip BuildOrder Info"]">
<BuildOrderComponent></BuildOrderComponent> <BuildOrderComponent></BuildOrderComponent>
</InfoTooltipComponent> </InfoTooltipComponent>
</div> </PanelComponent>
} </div>
</div> </div>
<ContentDividerComponent></ContentDividerComponent> <ContentDividerComponent></ContentDividerComponent>
@ -135,7 +138,7 @@
<InfoBodyComponent> <InfoBodyComponent>
<InfoQuestionComponent> <InfoQuestionComponent>
What is CONTROl key for? What is CONTROL key for?
</InfoQuestionComponent> </InfoQuestionComponent>
<InfoAnswerComponent> <InfoAnswerComponent>
Economy and tech related upgrades for townhalls. Economy and tech related upgrades for townhalls.
@ -165,6 +168,12 @@
<style> <style>
.gridItem {
display: flex;
flex-direction: column;
gap: 8px;
}
.calculatorGrid { .calculatorGrid {
display: grid; display: grid;
gap: 8px; gap: 8px;
@ -178,12 +187,6 @@
'chart chart chart chart'; 'chart chart chart chart';
} }
.gridItem {
border: 2px solid var(--paper-border);
padding: 20px;
background-color: var(--paper);
}
.gridKeys { .gridKeys {
grid-area: keys; grid-area: keys;
} }
@ -209,30 +212,35 @@
padding-left: 2px; padding-left: 2px;
padding-right: 2px; padding-right: 2px;
} }
.gridItem {
padding: 0px;
border: 0px;
width: 100%;
}
} }
</style> </style>
@code { @code {
protected override void OnInitialized() protected override void OnInitialized()
{ {
economyService.Calculate(buildOrderService, timingService, 0); economyService.Calculate(buildOrderService, timingService, 0);
keyService.Subscribe(HandleClick); keyService.Subscribe(HandleClick);
} }
void IDisposable.Dispose() void IDisposable.Dispose()
{ {
keyService.Unsubscribe(HandleClick); keyService.Unsubscribe(HandleClick);
} }
private void OnResetClicked()
{
toastService.AddToast(new ToastModel(){
SeverityType = SeverityType.Success,
Message = "Build order has been cleared.",
Title = "Reset"});
buildOrderService.Reset();
}
private void HandleClick() private void HandleClick()
{ {
var hotkey = keyService.GetHotkey(); var hotkey = keyService.GetHotkey();
@ -254,16 +262,17 @@
var faction = filterService.GetFactionType(); var faction = filterService.GetFactionType();
var immortal = filterService.GetImmortalType(); var immortal = filterService.GetImmortalType();
EntityModel? entity = EntityModel.GetFrom(hotkey!, hotkeyGroup, isHoldSpace, faction, immortal); var entity = EntityModel.GetFrom(hotkey!, hotkeyGroup, isHoldSpace, faction, immortal);
if (entity == null) if (entity == null)
{ {
return; return;
} }
if (buildOrderService.Add(entity, economyService, toastService)) if (buildOrderService.Add(entity, economyService, toastService))
{ {
economyService.Calculate(buildOrderService, timingService, buildOrderService.GetLastRequestInterval()); economyService.Calculate(buildOrderService, timingService, buildOrderService.GetLastRequestInterval());
} }
} }
} }

25
IGP/Pages/BuildCalculator/Parts/ArmyComponent.razor

@ -1,6 +1,6 @@
@inject IJSRuntime jsRuntime; @inject IJSRuntime jsRuntime
@inject IBuildOrderService BuildOrder @inject IBuildOrderService buildOrder
@implements IDisposable @implements IDisposable
@ -35,12 +35,12 @@
protected override void OnInitialized() protected override void OnInitialized()
{ {
BuildOrder.Subscribe(OnBuildOrderChanged); buildOrder.Subscribe(OnBuildOrderChanged);
} }
void IDisposable.Dispose() void IDisposable.Dispose()
{ {
BuildOrder.Unsubscribe(OnBuildOrderChanged); buildOrder.Unsubscribe(OnBuildOrderChanged);
} }
protected override bool ShouldRender() protected override bool ShouldRender()
@ -57,20 +57,20 @@
jsRuntime.InvokeVoidAsync("console.timeEnd", "ArmyComponent"); jsRuntime.InvokeVoidAsync("console.timeEnd", "ArmyComponent");
#endif #endif
} }
void OnBuildOrderChanged() void OnBuildOrderChanged()
{ {
int armyCountWas = 0; var armyCountWas = 0;
foreach (var army in armyCount) foreach (var army in armyCount)
{ {
armyCountWas += army.Value; armyCountWas += army.Value;
} }
armyCount.Clear(); armyCount.Clear();
lastInterval = 0; lastInterval = 0;
var entitiesOverTime = BuildOrder.GetOrders(); var entitiesOverTime = buildOrder.GetOrders();
foreach (var entitiesAtTime in entitiesOverTime) foreach (var entitiesAtTime in entitiesOverTime)
{ {
@ -91,19 +91,18 @@
} }
} }
//TODO Better //TODO Better
int armyCountIs = 0; var armyCountIs = 0;
foreach (var army in armyCount) foreach (var army in armyCount)
{ {
armyCountIs += army.Value; armyCountIs += army.Value;
} }
if (armyCountWas != armyCountIs) if (armyCountWas != armyCountIs)
{ {
StateHasChanged(); StateHasChanged();
} }
} }
} }

2
IGP/Pages/BuildCalculator/Parts/BankComponent.razor

@ -43,7 +43,7 @@
#if DEBUG #if DEBUG
jsRuntime.InvokeVoidAsync("console.time", "BankComponent"); jsRuntime.InvokeVoidAsync("console.time", "BankComponent");
#endif #endif
return true; return true;
} }

4
IGP/Pages/BuildCalculator/Parts/BuildOrderComponent.razor

@ -1,6 +1,5 @@
@inject IJSRuntime jsRuntime; @inject IJSRuntime jsRuntime;
@inject IBuildOrderService buildOrderService @inject IBuildOrderService buildOrderService
@implements IDisposable @implements IDisposable
@ -29,7 +28,7 @@
#if DEBUG #if DEBUG
jsRuntime.InvokeVoidAsync("console.time", "BuildOrderComponent"); jsRuntime.InvokeVoidAsync("console.time", "BuildOrderComponent");
#endif #endif
return true; return true;
} }
@ -39,4 +38,5 @@
jsRuntime.InvokeVoidAsync("console.timeEnd", "BuildOrderComponent"); jsRuntime.InvokeVoidAsync("console.timeEnd", "BuildOrderComponent");
#endif #endif
} }
} }

24
IGP/Pages/BuildCalculator/Parts/ChartComponent.razor

@ -6,7 +6,6 @@
@if (lastRequestedRefreshIndex != requestedRefreshIndex) @if (lastRequestedRefreshIndex != requestedRefreshIndex)
{ {
<LoadingComponent/> <LoadingComponent/>
} }
else else
{ {
@ -30,8 +29,8 @@ else
</div> </div>
} }
</div> </div>
<style> <style>
.chartsContainer { .chartsContainer {
position: relative; position: relative;
@ -60,8 +59,6 @@ else
<Display>@highestArmyPoint</Display> <Display>@highestArmyPoint</Display>
</FormDisplayComponent> </FormDisplayComponent>
</FormLayoutComponent> </FormLayoutComponent>
} }
@code { @code {
@ -80,7 +77,7 @@ else
private Timer ageTimer = null!; private Timer ageTimer = null!;
protected override void OnInitialized() protected override void OnInitialized()
{ {
buildOrderService.Subscribe(OnBuilderOrderChanged); buildOrderService.Subscribe(OnBuilderOrderChanged);
@ -89,12 +86,13 @@ else
ageTimer.Elapsed += OnAge!; ageTimer.Elapsed += OnAge!;
ageTimer.Enabled = true; ageTimer.Enabled = true;
GenerateChart(); GenerateChart();
} }
int lastRequestedRefreshIndex = 0; int lastRequestedRefreshIndex = 0;
void OnAge(object? sender, ElapsedEventArgs elapsedEventArgs) void OnAge(object? sender, ElapsedEventArgs elapsedEventArgs)
{ {
if (requestedRefreshIndex > 0) if (requestedRefreshIndex > 0)
@ -105,14 +103,13 @@ else
requestedRefreshIndex = 0; requestedRefreshIndex = 0;
lastRequestedRefreshIndex = 0; lastRequestedRefreshIndex = 0;
} }
lastRequestedRefreshIndex = requestedRefreshIndex; lastRequestedRefreshIndex = requestedRefreshIndex;
} }
ageTimer.Enabled = true; ageTimer.Enabled = true;
} }
void IDisposable.Dispose() void IDisposable.Dispose()
{ {
@ -121,6 +118,7 @@ else
int requestedRefreshIndex = 0; int requestedRefreshIndex = 0;
void OnBuilderOrderChanged() void OnBuilderOrderChanged()
{ {
requestedRefreshIndex++; requestedRefreshIndex++;
@ -133,7 +131,7 @@ else
#if DEBUG #if DEBUG
jsRuntime.InvokeVoidAsync("console.time", "ChartComponent"); jsRuntime.InvokeVoidAsync("console.time", "ChartComponent");
#endif #endif
return true; return true;
} }
@ -143,7 +141,7 @@ else
jsRuntime.InvokeVoidAsync("console.timeEnd", "ChartComponent"); jsRuntime.InvokeVoidAsync("console.timeEnd", "ChartComponent");
#endif #endif
} }
void GenerateChart() void GenerateChart()
{ {
var economyOverTime = economyService.GetOverTime(); var economyOverTime = economyService.GetOverTime();

9
IGP/Pages/BuildCalculator/Parts/EntityClickViewComponent.razor

@ -1,9 +1,7 @@
@inject IJSRuntime jsRuntime; @inject IJSRuntime jsRuntime;
@inject IKeyService keyService
@inject IImmortalSelectionService filterService
@inject IKeyService keyService @inject IBuildOrderService buildOrderService
@inject IImmortalSelectionService filterService
@inject IBuildOrderService buildOrderService
@implements IDisposable @implements IDisposable
@ -68,4 +66,5 @@
StateHasChanged(); StateHasChanged();
} }
} }
} }

15
IGP/Pages/BuildCalculator/Parts/FilterComponent.razor

@ -1,4 +1,5 @@
@inject IJSRuntime jsRuntime; @inject IJSRuntime jsRuntime;
@inject IImmortalSelectionService filterService
<FormLayoutComponent> <FormLayoutComponent>
<FormSelectComponent OnChange="@OnFactionChanged"> <FormSelectComponent OnChange="@OnFactionChanged">
@ -12,12 +13,12 @@
<FormSelectComponent OnChange="@OnImmortalChanged"> <FormSelectComponent OnChange="@OnImmortalChanged">
<FormLabelComponent>Immortal</FormLabelComponent> <FormLabelComponent>Immortal</FormLabelComponent>
<ChildContent> <ChildContent>
@if (FilterService.GetFactionType() == FactionType.QRath) @if (filterService.GetFactionType() == FactionType.QRath)
{ {
<option value="@DataType.IMMORTAL_Orzum" selected>Orzum</option> <option value="@DataType.IMMORTAL_Orzum" selected>Orzum</option>
<option value="@DataType.IMMORTAL_Ajari">Ajari</option> <option value="@DataType.IMMORTAL_Ajari">Ajari</option>
} }
@if (FilterService.GetFactionType() == FactionType.Aru) @if (filterService.GetFactionType() == FactionType.Aru)
{ {
<option value="@DataType.IMMORTAL_Mala" selected>Mala</option> <option value="@DataType.IMMORTAL_Mala" selected>Mala</option>
<option value="@DataType.IMMORTAL_Xol">Xol</option> <option value="@DataType.IMMORTAL_Xol">Xol</option>
@ -28,17 +29,14 @@
@code { @code {
[Inject]
public IImmortalSelectionService FilterService { get; set; } = default!;
void OnFactionChanged(ChangeEventArgs e) void OnFactionChanged(ChangeEventArgs e)
{ {
FilterService.SelectFactionType(e.Value!.ToString()!); filterService.SelectFactionType(e.Value!.ToString()!);
} }
void OnImmortalChanged(ChangeEventArgs e) void OnImmortalChanged(ChangeEventArgs e)
{ {
FilterService.SelectImmortalType(e.Value!.ToString()!); filterService.SelectImmortalType(e.Value!.ToString()!);
} }
protected override bool ShouldRender() protected override bool ShouldRender()
@ -46,7 +44,7 @@
#if DEBUG #if DEBUG
jsRuntime.InvokeVoidAsync("console.time", "FilterComponent"); jsRuntime.InvokeVoidAsync("console.time", "FilterComponent");
#endif #endif
return true; return true;
} }
@ -56,4 +54,5 @@
jsRuntime.InvokeVoidAsync("console.timeEnd", "FilterComponent"); jsRuntime.InvokeVoidAsync("console.timeEnd", "FilterComponent");
#endif #endif
} }
} }

25
IGP/Pages/BuildCalculator/Parts/HighlightsComponent.razor

@ -1,5 +1,7 @@
@inject IJSRuntime jsRuntime; @inject IJSRuntime jsRuntime;
@inject IEconomyService economyService
@inject IBuildOrderService buildOrderService
@inject ITimingService timingService
@implements IDisposable @implements IDisposable
@ -7,7 +9,7 @@
<div> <div>
<div>Requested</div> <div>Requested</div>
@foreach (var ordersAtTime in BuildOrderService.StartedOrders.Reverse()) @foreach (var ordersAtTime in buildOrderService.StartedOrders.Reverse())
{ {
foreach (var order in ordersAtTime.Value) foreach (var order in ordersAtTime.Value)
{ {
@ -26,7 +28,7 @@
<div> <div>
<div>Finished</div> <div>Finished</div>
@foreach (var ordersAtTime in BuildOrderService.CompletedOrders.Reverse()) @foreach (var ordersAtTime in buildOrderService.CompletedOrders.Reverse())
{ {
foreach (var order in ordersAtTime.Value) foreach (var order in ordersAtTime.Value)
{ {
@ -57,25 +59,16 @@
@code { @code {
[Inject]
IEconomyService EconomyService { get; set; } = default!;
[Inject]
IBuildOrderService BuildOrderService { get; set; } = default!;
[Inject]
ITimingService TimingService { get; set; } = default!;
protected override void OnInitialized() protected override void OnInitialized()
{ {
EconomyService.Subscribe(StateHasChanged); economyService.Subscribe(StateHasChanged);
BuildOrderService.Subscribe(StateHasChanged); buildOrderService.Subscribe(StateHasChanged);
} }
void IDisposable.Dispose() void IDisposable.Dispose()
{ {
EconomyService.Unsubscribe(StateHasChanged); economyService.Unsubscribe(StateHasChanged);
BuildOrderService.Unsubscribe(StateHasChanged); buildOrderService.Unsubscribe(StateHasChanged);
} }
protected override bool ShouldRender() protected override bool ShouldRender()

40
IGP/Pages/BuildCalculator/Parts/HotkeyViewerComponent.razor

@ -1,8 +1,6 @@
@inject IJSRuntime jsRuntime; @inject IJSRuntime jsRuntime;
@using System.Diagnostics
@implements IDisposable @implements IDisposable
@inject IKeyService keyService @inject IKeyService keyService
@inject IBuildOrderService buildOrderService @inject IBuildOrderService buildOrderService
@inject IImmortalSelectionService filterService @inject IImmortalSelectionService filterService
@ -57,7 +55,6 @@
@hotkey.KeyText @hotkey.KeyText
@foreach (var entity in data.Values) @foreach (var entity in data.Values)
{ {
if (InvalidKey(entity, hotkey) || InvalidKeyGroup(entity, hotkey) || InvalidHoldSpace(entity)) if (InvalidKey(entity, hotkey) || InvalidKeyGroup(entity, hotkey) || InvalidHoldSpace(entity))
{ {
continue; continue;
@ -67,7 +64,7 @@
{ {
continue; continue;
} }
if (InvalidVanguard(entity) || InvalidNonVanguard(entity)) if (InvalidVanguard(entity) || InvalidNonVanguard(entity))
{ {
continue; continue;
@ -75,7 +72,7 @@
var isVanguard = entity.VanguardAdded() != null; var isVanguard = entity.VanguardAdded() != null;
var style = isVanguard ? "font-weight: bold;" : ""; var style = isVanguard ? "font-weight: bold;" : "";
if (buildOrderService.WillMeetRequirements(entity) == null) if (buildOrderService.WillMeetRequirements(entity) == null)
{ {
style += "color:gray; font-style: italic;"; style += "color:gray; font-style: italic;";
@ -138,6 +135,7 @@
} }
int completedTimeCount = 0; int completedTimeCount = 0;
void OnBuilderOrderChanged() void OnBuilderOrderChanged()
{ {
if (buildOrderService.UniqueCompletedTimes.Count != completedTimeCount) if (buildOrderService.UniqueCompletedTimes.Count != completedTimeCount)
@ -146,13 +144,13 @@
StateHasChanged(); StateHasChanged();
} }
} }
protected override bool ShouldRender() protected override bool ShouldRender()
{ {
#if DEBUG #if DEBUG
jsRuntime.InvokeVoidAsync("console.time", "HotKeyViewerComponent"); jsRuntime.InvokeVoidAsync("console.time", "HotKeyViewerComponent");
#endif #endif
return true; return true;
} }
@ -177,8 +175,8 @@
// Move to Filter Service // Move to Filter Service
bool InvalidVanguard(EntityModel entity) bool InvalidVanguard(EntityModel entity)
{ {
if (entity.VanguardAdded() != null if (entity.VanguardAdded() != null
&& entity.VanguardAdded()?.ImmortalId != filterService.GetImmortalType() && entity.VanguardAdded()?.ImmortalId != filterService.GetImmortalType()
&& filterService.GetImmortalType() != ImmortalType.Any) && filterService.GetImmortalType() != ImmortalType.Any)
{ {
return true; return true;
@ -252,11 +250,10 @@
void OnKeyPressed() void OnKeyPressed()
{ {
var controlGroupWas = controlGroup;
string controlGroupWas = controlGroup; var keyWas = key;
string keyWas = key;
if (keyService.GetAllPressedKeys().Contains("Z")) if (keyService.GetAllPressedKeys().Contains("Z"))
{ {
controlGroup = "Z"; controlGroup = "Z";
@ -299,13 +296,11 @@
if (controlGroupWas != controlGroup || keyWas != key) if (controlGroupWas != controlGroup || keyWas != key)
{ {
StateHasChanged();
StateHasChanged();
} }
} }
private void HandleClick() private void HandleClick()
{ {
var hotkey = keyService.GetHotkey(); var hotkey = keyService.GetHotkey();
@ -327,16 +322,17 @@
var faction = filterService.GetFactionType(); var faction = filterService.GetFactionType();
var immortal = filterService.GetImmortalType(); var immortal = filterService.GetImmortalType();
EntityModel? entity = EntityModel.GetFrom(hotkey!, hotkeyGroup, isHoldSpace, faction, immortal); var entity = EntityModel.GetFrom(hotkey!, hotkeyGroup, isHoldSpace, faction, immortal);
if (entity == null) if (entity == null)
{ {
return; return;
} }
if (buildOrderService.Add(entity, economyService, toastService)) if (buildOrderService.Add(entity, economyService, toastService))
{ {
economyService.Calculate(buildOrderService, timingService, buildOrderService.GetLastRequestInterval()); economyService.Calculate(buildOrderService, timingService, buildOrderService.GetLastRequestInterval());
} }
} }
} }

8
IGP/Pages/BuildCalculator/Parts/InputPanelComponent.razor

@ -1,4 +1,4 @@
@inject IKeyService keyService @inject IKeyService keyService
@inject IJSRuntime jsRuntime; @inject IJSRuntime jsRuntime;
@ -13,9 +13,10 @@
</div> </div>
@code { @code {
[Parameter] [Parameter]
public RenderFragment ChildContent { get; set; } = default!; public RenderFragment ChildContent { get; set; } = default!;
private void HandleKeyDown(KeyboardEventArgs e) private void HandleKeyDown(KeyboardEventArgs e)
{ {
keyService.AddPressedKey(e.Key); keyService.AddPressedKey(e.Key);
@ -31,7 +32,7 @@
#if DEBUG #if DEBUG
jsRuntime.InvokeVoidAsync("console.time", "InputPanelComponent"); jsRuntime.InvokeVoidAsync("console.time", "InputPanelComponent");
#endif #endif
return true; return true;
} }
@ -41,4 +42,5 @@
jsRuntime.InvokeVoidAsync("console.timeEnd", "InputPanelComponent"); jsRuntime.InvokeVoidAsync("console.timeEnd", "InputPanelComponent");
#endif #endif
} }
} }

41
IGP/Pages/BuildCalculator/Parts/OptionsComponent.razor

@ -0,0 +1,41 @@
@inject IJSRuntime jsRuntime;
@inject IBuildOrderService buildOrderService
@inject IEconomyService economyService
@inject IToastService toastService
@inject ITimingService timingService
<FormLayoutComponent>
<FormNumberComponent Max="600"
Min="0"
Value="@buildOrderService.BuildingInputDelay"
OnChange="@OnBuildingInputDelayChanged">
<FormLabelComponent>Building Input Delay</FormLabelComponent>
<FormInfoComponent>Add a input delay to constructing buildings for simulating worker movement and player micro.</FormInfoComponent>
</FormNumberComponent>
</FormLayoutComponent>
@code {
void OnBuildingInputDelayChanged(ChangeEventArgs changeEventArgs)
{
buildOrderService.BuildingInputDelay = int.Parse(changeEventArgs.Value!.ToString()!);
}
protected override bool ShouldRender()
{
#if DEBUG
jsRuntime.InvokeVoidAsync("console.time", "TimingComponent");
#endif
return true;
}
protected override void OnAfterRender(bool firstRender)
{
#if DEBUG
jsRuntime.InvokeVoidAsync("console.timeEnd", "TimingComponent");
#endif
}
}

43
IGP/Pages/BuildCalculator/Parts/TimelineComponent.razor

@ -1,9 +1,10 @@
@inject IJSRuntime jsRuntime; @inject IJSRuntime jsRuntime
@inject IEconomyService economyService
@inject IBuildOrderService buildOrderService
@implements IDisposable @implements IDisposable
<Virtualize Items="@EconomyService.GetOverTime()" Context="economyAtSecond" ItemSize="400" OverscanCount="4"> <Virtualize Items="@economyService.GetOverTime()" Context="economyAtSecond" ItemSize="400" OverscanCount="4">
<div style="display: grid; gap: 8px; grid-template-columns: 1fr 1fr;"> <div style="display: grid; gap: 8px; grid-template-columns: 1fr 1fr;">
<div> <div>
<div> <div>
@ -27,19 +28,19 @@
<br/> <br/>
</div> </div>
<div> <div>
@if (BuildOrderService.StartedOrders.TryGetValue(economyAtSecond.Interval, out var ordersAtTime)) @if (buildOrderService.StartedOrders.TryGetValue(economyAtSecond.Interval, out var ordersAtTime))
{ {
@foreach (var order in ordersAtTime) @foreach (var order in ordersAtTime)
{ {
<div> <div>
Requested: @order.Info().Name Requested: @order.Info().Name
</div> </div>
} }
} }
@if (BuildOrderService.CompletedOrders.TryGetValue(economyAtSecond.Interval, out var ordersCompletedAtTime)) @if (buildOrderService.CompletedOrders.TryGetValue(economyAtSecond.Interval, out var ordersCompletedAtTime))
{ {
@foreach (var order in ordersCompletedAtTime) @foreach (var order in ordersCompletedAtTime)
{ {
@ -55,30 +56,24 @@
@code { @code {
[Inject]
IEconomyService EconomyService { get; set; } = default!;
[Inject]
IBuildOrderService BuildOrderService { get; set; } = default!;
protected override void OnInitialized() protected override void OnInitialized()
{ {
EconomyService.Subscribe(StateHasChanged); economyService.Subscribe(StateHasChanged);
BuildOrderService.Subscribe(StateHasChanged); buildOrderService.Subscribe(StateHasChanged);
} }
void IDisposable.Dispose() void IDisposable.Dispose()
{ {
EconomyService.Unsubscribe(StateHasChanged); economyService.Unsubscribe(StateHasChanged);
BuildOrderService.Unsubscribe(StateHasChanged); buildOrderService.Unsubscribe(StateHasChanged);
} }
protected override bool ShouldRender() protected override bool ShouldRender()
{ {
#if DEBUG #if DEBUG
jsRuntime.InvokeVoidAsync("console.time", "TimelineComponent"); jsRuntime.InvokeVoidAsync("console.time", "TimelineComponent");
#endif #endif
return true; return true;
} }

17
IGP/Pages/BuildCalculator/Parts/TimingComponent.razor

@ -5,11 +5,8 @@
@inject IToastService toastService @inject IToastService toastService
@inject ITimingService timingService @inject ITimingService timingService
<FormLayoutComponent> <FormLayoutComponent>
<FormNumberComponent ReadOnly="true" <FormNumberComponent Max="2048"
Max="600"
Min="0" Min="0"
Value="@timingService.GetTiming()" Value="@timingService.GetTiming()"
OnChange="@OnTimingChanged"> OnChange="@OnTimingChanged">
@ -27,10 +24,17 @@
</FormLayoutComponent> </FormLayoutComponent>
@code { @code {
void OnTimingChanged(ChangeEventArgs changeEventArgs) void OnTimingChanged(ChangeEventArgs changeEventArgs)
{ {
timingService.SetTiming(int.Parse(changeEventArgs.Value!.ToString()!)); timingService.SetTiming(int.Parse(changeEventArgs.Value!.ToString()!));
economyService.Calculate(buildOrderService, timingService, buildOrderService.GetLastRequestInterval()); economyService.Calculate(buildOrderService, timingService, buildOrderService.GetLastRequestInterval());
toastService.AddToast(new ToastModel()
{
Title = "Timing Interval",
Message = "Timing interval has changed.",
SeverityType = SeverityType.Success
});
} }
void OnNameChanged(ChangeEventArgs changeEventArgs) void OnNameChanged(ChangeEventArgs changeEventArgs)
@ -48,13 +52,13 @@
{ {
buildOrderService.SetNotes(changeEventArgs.Value!.ToString()!); buildOrderService.SetNotes(changeEventArgs.Value!.ToString()!);
} }
protected override bool ShouldRender() protected override bool ShouldRender()
{ {
#if DEBUG #if DEBUG
jsRuntime.InvokeVoidAsync("console.time", "TimingComponent"); jsRuntime.InvokeVoidAsync("console.time", "TimingComponent");
#endif #endif
return true; return true;
} }
@ -65,5 +69,4 @@
#endif #endif
} }
} }

4
IGP/Pages/Comparision/ComparisionPage.razor

@ -21,7 +21,7 @@ grid-template-areas: 'loader sand compare compare' ;">
<div style="grid-area: compare; border: 2px solid black; padding: 20px;"> <div style="grid-area: compare; border: 2px solid black; padding: 20px;">
Comparision Charts Comparision Charts
</div> </div>
@ -40,7 +40,7 @@ grid-template-areas: 'loader sand compare compare' ;">
[Inject] [Inject]
IEconomyService EconomyService { get; set; } = default!; IEconomyService EconomyService { get; set; } = default!;
[Inject] [Inject]
ITimingService TimingService { get; set; } = default!; ITimingService TimingService { get; set; } = default!;

31
IGP/Pages/Database/Entity/Parts/EntityPassivesComponent.razor

@ -12,7 +12,7 @@
var requirements = passive.Requirements(); var requirements = passive.Requirements();
<div> <div>
<div> <div>
<b>Passive Name:</b> @info.Name <b>Passive Name:</b> @info.Name
@ -46,7 +46,7 @@
} }
</div> </div>
} }
@if (requirements.Count > 0) @if (requirements.Count > 0)
{ {
@foreach (var requirement in requirements) @foreach (var requirement in requirements)
@ -71,7 +71,7 @@
var info = passive.Info(); var info = passive.Info();
var production = passive.Production(); var production = passive.Production();
var requirements = passive.Requirements(); var requirements = passive.Requirements();
@ -89,20 +89,20 @@
<b>Notes:</b> @((MarkupString)info.Notes) <b>Notes:</b> @((MarkupString)info.Notes)
</div> </div>
} }
@if (requirements.Count > 0) @if (requirements.Count > 0)
{
@foreach (var requirement in requirements)
{ {
var requirementModel = DATA.Get()[requirement.Id]; @foreach (var requirement in requirements)
<div> {
<span> var requirementModel = DATA.Get()[requirement.Id];
<b>@requirement.Requirement.Replace("_", " "):</b> @requirementModel.Info().Name <div>
</span> <span>
</div> <b>@requirement.Requirement.Replace("_", " "):</b> @requirementModel.Info().Name
</span>
</div>
}
} }
}
</div> </div>
@if (production != null) @if (production != null)
@ -122,7 +122,6 @@
} }
</div> </div>
} }
} }
</EntityDisplayComponent> </EntityDisplayComponent>
} }

2
IGP/Pages/Database/Entity/Parts/EntityProductionComponent.razor

@ -46,7 +46,7 @@
{ {
<div> <div>
<b>Shields:</b> @Production.DefensiveLayer <b>Shields:</b> @Production.DefensiveLayer
</div> </div>
} }
@if (!Production.BuildTime.Equals(0)) @if (!Production.BuildTime.Equals(0))

33
IGP/Pages/Documentation/Parts/DocumentComponent.razor

@ -1,7 +1,3 @@
@using System.Net.Http.Json
@using Markdig.Extensions.Yaml
@using Markdig.Syntax
@using YamlDotNet.Serialization
@inject HttpClient httpClient @inject HttpClient httpClient
@if (content == null) @if (content == null)
@ -19,10 +15,10 @@ else
</div> </div>
</div> </div>
<div class="docContent">@((MarkupString)Markdown.ToHtml(content, Pipeline))</div> <div class="docContent">@((MarkupString)Markdown.ToHtml(content, Pipeline))</div>
<div class="docFooter"><EditLinkComponent Href="@GitUrl"></EditLinkComponent></div> <div class="docFooter">
<EditLinkComponent Href="@GitUrl"></EditLinkComponent>
</div>
</div> </div>
} }
<style> <style>
@ -56,22 +52,33 @@ else
</style> </style>
@code { @code {
[Parameter] public DocContentModel DocContentModel { get; set; } = default!;
[Parameter]
public DocContentModel DocContentModel { get; set; } = default!;
DocFrontMatterModel docFrontMatter = null!; DocFrontMatterModel docFrontMatter = null!;
private string? content = null; private string? content = null;
private string Filepath => $"content/docs/{DocContentModel.Content}.md"; private string Filepath => $"content/docs/{DocContentModel.Content}.md";
private string GitUrl => $"{Project.GitResourcesUrl}/{Filepath}"; private string GitUrl => $"{Project.GitResourcesUrl}/{Filepath}";
private MarkdownPipeline Pipeline => MarkdownFiles.Pipeline; private MarkdownPipeline Pipeline => MarkdownFiles.Pipeline;
private async Task<DocFrontMatterModel> LoadContent() { private async Task<DocFrontMatterModel> LoadContent()
{
content = await MarkdownFiles.LoadMarkdown(httpClient, Filepath); content = await MarkdownFiles.LoadMarkdown(httpClient, Filepath);
return docFrontMatter = return docFrontMatter =
await MarkdownFiles.LoadFrontMatter<DocFrontMatterModel>(httpClient, Filepath); await MarkdownFiles.LoadFrontMatter<DocFrontMatterModel>(httpClient, Filepath);
} }
protected override async Task OnParametersSetAsync() => await LoadContent(); protected override async Task OnParametersSetAsync()
protected override async Task OnInitializedAsync() => await LoadContent(); {
await LoadContent();
}
protected override async Task OnInitializedAsync()
{
await LoadContent();
}
} }

20
IGP/Pages/MakingOf/Parts/MakingOfColours.razor

@ -77,16 +77,16 @@
Border: <input type="color" value="@info_border" @onchange="e => info_border = e.Value!.ToString()!"/> Border: <input type="color" value="@info_border" @onchange="e => info_border = e.Value!.ToString()!"/>
</div> </div>
</div> </div>
<div class="color info_secondary"> <div class="color info_secondary">
<div>Info Secondary</div> <div>Info Secondary</div>
<div> <div>
Base: <input type="color" value="@info_secondary" @onchange="e => info_secondary = e.Value!.ToString()!"/> Base: <input type="color" value="@info_secondary" @onchange="e => info_secondary = e.Value!.ToString()!"/>
</div> </div>
<div> <div>
Border: <input type="color" value="@info_secondary_border" @onchange="e => info_secondary_border = e.Value!.ToString()!"/> Border: <input type="color" value="@info_secondary_border" @onchange="e => info_secondary_border = e.Value!.ToString()!"/>
</div>
</div> </div>
</div>
</div> </div>
<style> <style>
@ -183,6 +183,6 @@
string info_border = "#210b36"; string info_border = "#210b36";
string info_secondary = "#4c3e59"; string info_secondary = "#4c3e59";
string info_secondary_border = "#7e58a2"; string info_secondary_border = "#7e58a2";
} }

10
IGP/Pages/MakingOf/Parts/MakingOfNavigation.razor

@ -6,15 +6,15 @@
Group specfic webpages. Each webpage link is used to navigate to that specific webpage. If on the webpage, the link turns dark gray. It can be clicked again to leave the page and return to home. Group specfic webpages. Each webpage link is used to navigate to that specific webpage. If on the webpage, the link turns dark gray. It can be clicked again to leave the page and return to home.
</Description> </Description>
<Example> <Example>
<NavSectionComponent Section=@(new WebSectionModel { Name = "Example Section" }) <DesktopNavSectionComponent Section=@(new WebSectionModel { Name = "Example Section" })
Children=@(new List<WebPageModel> { new() { Name = "Example Page", Href = "immortal-makingof", IsPrivate = "False" }, new() { Name = "Database", Href = "immortal-database", IsPrivate = "False" } })> Children=@(new List<WebPageModel> { new() { Name = "Example Page", Href = "immortal-makingof", IsPrivate = "False" }, new() { Name = "Database", Href = "immortal-database", IsPrivate = "False" } })>
</NavSectionComponent> </DesktopNavSectionComponent>
</Example> </Example>
<Usage> <Usage>
<CodeComponent> <CodeComponent>
&lt;NavSectionComponent Section=@@(new WebSectionModel{Name = &quot;Example Section&quot;}) &lt;DesktopNavSectionComponent Section=@@(new WebSectionModel{Name = &quot;Example Section&quot;})
Children=@@(new List&lt;WebPageModel&gt;{new WebPageModel{Name=&quot;Example Page&quot;, Href = &quot;immortal-makingof&quot;, IsPrivate = false}, new WebPageModel{Name=&quot;Database&quot;, Href = &quot;immortal-database&quot;, IsPrivate = false}})&gt; Children=@@(new List&lt;WebPageModel&gt;{new WebPageModel{Name=&quot;Example Page&quot;, Href = &quot;immortal-makingof&quot;, IsPrivate = false}, new WebPageModel{Name=&quot;Database&quot;, Href = &quot;immortal-database&quot;, IsPrivate = false}})&gt;
&lt;/NavSectionComponent&gt; &lt;/DesktopNavSectionComponent&gt;
</CodeComponent> </CodeComponent>
</Usage> </Usage>
<Code> <Code>

26
IGP/Pages/Notes/Parts/NoteComponent.razor

@ -15,7 +15,9 @@ else
</div> </div>
</div> </div>
<div class="noteContent">@((MarkupString)Markdown.ToHtml(content, Pipeline))</div> <div class="noteContent">@((MarkupString)Markdown.ToHtml(content, Pipeline))</div>
<div class="noteFooter"><EditLinkComponent Href="@GitUrl"></EditLinkComponent></div> <div class="noteFooter">
<EditLinkComponent Href="@GitUrl"></EditLinkComponent>
</div>
</div> </div>
} }
@ -43,23 +45,33 @@ else
</style> </style>
@code { @code {
[Parameter] public NoteContentModel NoteContentModel { get; set; } = default!;
[Parameter]
public NoteContentModel NoteContentModel { get; set; } = default!;
NoteFrontMatterModel noteFrontMatter = null!; NoteFrontMatterModel noteFrontMatter = null!;
private string? content = null; private string? content = null;
private string Filepath => $"content/notes/{NoteContentModel.Content}.md"; private string Filepath => $"content/notes/{NoteContentModel.Content}.md";
private string GitUrl => $"{Project.GitResourcesUrl}/{Filepath}"; private string GitUrl => $"{Project.GitResourcesUrl}/{Filepath}";
private MarkdownPipeline Pipeline => MarkdownFiles.Pipeline; private MarkdownPipeline Pipeline => MarkdownFiles.Pipeline;
private async Task<NoteFrontMatterModel> LoadContent() { private async Task<NoteFrontMatterModel> LoadContent()
{
content = await MarkdownFiles.LoadMarkdown(httpClient, Filepath); content = await MarkdownFiles.LoadMarkdown(httpClient, Filepath);
return noteFrontMatter = return noteFrontMatter =
await MarkdownFiles.LoadFrontMatter<NoteFrontMatterModel>(httpClient, Filepath); await MarkdownFiles.LoadFrontMatter<NoteFrontMatterModel>(httpClient, Filepath);
} }
protected override async Task OnParametersSetAsync() => await LoadContent(); protected override async Task OnParametersSetAsync()
protected override async Task OnInitializedAsync() => await LoadContent(); {
await LoadContent();
}
protected override async Task OnInitializedAsync()
{
await LoadContent();
}
} }

15
IGP/Portals/ToastPortal.razor

@ -5,9 +5,8 @@
@if (toastService.HasToasts()) @if (toastService.HasToasts())
{ {
<div class="toastsContainer"> <div class="toastsContainer">
@foreach(var toast in Toasts) @foreach (var toast in Toasts)
{ {
<ToastComponent Toast="toast"/> <ToastComponent Toast="toast"/>
} }
</div> </div>
@ -27,25 +26,24 @@
@code { @code {
private List<ToastModel> Toasts => toastService.GetToasts(); private List<ToastModel> Toasts => toastService.GetToasts();
private Timer ageTimer = null!; private Timer ageTimer = null!;
protected override void OnInitialized() protected override void OnInitialized()
{ {
toastService.Subscribe(OnUpdate); toastService.Subscribe(OnUpdate);
ageTimer = new Timer(10); ageTimer = new Timer(10);
ageTimer.Elapsed += OnAge!; ageTimer.Elapsed += OnAge!;
ageTimer.Enabled = true; ageTimer.Enabled = true;
} }
public void Dispose() public void Dispose()
{ {
toastService.Unsubscribe(OnUpdate); toastService.Unsubscribe(OnUpdate);
} }
void OnAge(object? sender, ElapsedEventArgs elapsedEventArgs) void OnAge(object? sender, ElapsedEventArgs elapsedEventArgs)
{ {
toastService.AgeToasts(); toastService.AgeToasts();
@ -57,4 +55,5 @@
{ {
StateHasChanged(); StateHasChanged();
} }
} }

3
IGP/Program.cs

@ -6,7 +6,6 @@ using Services.Development;
using Services.Immortal; using Services.Immortal;
using Services.Website; using Services.Website;
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US"); CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US");
CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo("en-US"); CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo("en-US");
@ -44,7 +43,6 @@ builder.Services.AddSingleton(new HttpClient
}); });
#if NO_SQL #if NO_SQL
#else #else
@ -52,7 +50,6 @@ builder.Services.AddSingleton(new HttpClient
#endif #endif
await builder.Build().RunAsync(); await builder.Build().RunAsync();

6
IGP/Utils/Interval.cs

@ -1,7 +1,9 @@
namespace IGP.Utils; namespace IGP.Utils;
public static class Interval { public static class Interval
public static string ToTime(int interval) { {
public static string ToTime(int interval)
{
return TimeSpan.FromSeconds(interval).ToString(@"mm\:ss"); return TimeSpan.FromSeconds(interval).ToString(@"mm\:ss");
} }
} }

27
IGP/Utils/Markdown.cs

@ -1,18 +1,18 @@
using Markdig; using Markdig;
using Markdig.Extensions.Yaml; using Markdig.Extensions.Yaml;
using Markdig.Syntax; using Markdig.Syntax;
using Model.Doc;
using YamlDotNet.Serialization; using YamlDotNet.Serialization;
namespace IGP.Utils; namespace IGP.Utils;
public static class MarkdownFiles { public static class MarkdownFiles
private static readonly IDeserializer YamlDeserializer = {
private static readonly IDeserializer YamlDeserializer =
new DeserializerBuilder() new DeserializerBuilder()
.IgnoreUnmatchedProperties() .IgnoreUnmatchedProperties()
.Build(); .Build();
public static readonly MarkdownPipeline Pipeline public static readonly MarkdownPipeline Pipeline
= new MarkdownPipelineBuilder() = new MarkdownPipelineBuilder()
.UseYamlFrontMatter() .UseYamlFrontMatter()
.UseAdvancedExtensions() .UseAdvancedExtensions()
@ -22,30 +22,31 @@ public static class MarkdownFiles {
{ {
return await httpClient.GetStringAsync(filepath); return await httpClient.GetStringAsync(filepath);
} }
public static async Task<T> LoadFrontMatter<T>(HttpClient httpClient, string filepath) { public static async Task<T> LoadFrontMatter<T>(HttpClient httpClient, string filepath)
{
var markdown = await LoadMarkdown(httpClient, filepath); var markdown = await LoadMarkdown(httpClient, filepath);
var document = Markdown.Parse(markdown, Pipeline); var document = Markdown.Parse(markdown, Pipeline);
var block = document var block = document
.Descendants<YamlFrontMatterBlock>() .Descendants<YamlFrontMatterBlock>()
.FirstOrDefault(); .FirstOrDefault();
if (block == null) if (block == null)
return default!; return default!;
var yaml = var yaml =
block block
.Lines .Lines
.Lines .Lines
.OrderByDescending(x => x.Line) .OrderByDescending(x => x.Line)
.Select(x => $"{x}\n") .Select(x => $"{x}\n")
.ToList() .ToList()
.Select(x => x.Replace("---", string.Empty)) .Select(x => x.Replace("---", string.Empty))
.Where(x => !string.IsNullOrWhiteSpace(x)) .Where(x => !string.IsNullOrWhiteSpace(x))
.Aggregate((s, agg) => agg + s); .Aggregate((s, agg) => agg + s);
return YamlDeserializer.Deserialize<T>(yaml); return YamlDeserializer.Deserialize<T>(yaml);
} }
} }

7
IGP/Utils/Project.cs

@ -1,6 +1,7 @@
namespace IGP.Utils; namespace IGP.Utils;
public static class Project { public static class Project
public static string GitResourcesUrl => "https://github.com/JonathanMcCaffrey/IGP-Fan-Reference/blob/develop/IGP/wwwroot/"; {
public static string GitResourcesUrl =>
"https://github.com/JonathanMcCaffrey/IGP-Fan-Reference/blob/develop/IGP/wwwroot/";
} }

16
IGP/_Imports.razor

@ -6,11 +6,10 @@
@using Components.Layout @using Components.Layout
@using Components.Navigation @using Components.Navigation
@using Components.Shared @using Components.Shared
@using IGP.Utils
@using System.Globalization
@using IGP.Dialog @using IGP.Dialog
@using IGP.Pages @using IGP.Pages
@using IGP.Pages.Agile.Parts @using IGP.Pages.Agile.Parts
@using IGP.Pages.BuildCalculator
@using IGP.Pages.BuildCalculator.Parts @using IGP.Pages.BuildCalculator.Parts
@using IGP.Pages.Comparision @using IGP.Pages.Comparision
@using IGP.Pages.Comparision.Parts @using IGP.Pages.Comparision.Parts
@ -23,27 +22,28 @@
@using IGP.Pages.Home.Parts @using IGP.Pages.Home.Parts
@using IGP.Pages.MakingOf.Parts @using IGP.Pages.MakingOf.Parts
@using IGP.Pages.MemoryTester.Parts @using IGP.Pages.MemoryTester.Parts
@using IGP.Pages.RoadMap.Parts
@using IGP.Pages.Notes @using IGP.Pages.Notes
@using IGP.Pages.Notes.Parts @using IGP.Pages.Notes.Parts
@using System.Timers @using IGP.Pages.RoadMap.Parts
@using IGP.Portals @using IGP.Portals
@using IGP.Utils
@using Markdig @using Markdig
@using Model.Feedback
@using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.WebAssembly.Http @using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.EntityFrameworkCore @using Microsoft.EntityFrameworkCore
@using Microsoft.Extensions.Localization
@using Microsoft.JSInterop @using Microsoft.JSInterop
@using Model.Chart @using Model.Chart
@using Model.Git
@using Model.Doc @using Model.Doc
@using Model.Economy @using Model.Economy
@using Model.Entity @using Model.Entity
@using Model.Entity.Data @using Model.Entity.Data
@using Model.Entity.Parts @using Model.Entity.Parts
@using Model.Feedback
@using Model.Git
@using Model.Hotkeys @using Model.Hotkeys
@using Model.MemoryTester @using Model.MemoryTester
@using Model.Notes @using Model.Notes
@ -55,4 +55,6 @@
@using Model.Work.Tasks.Enums @using Model.Work.Tasks.Enums
@using Services @using Services
@using Services.Immortal @using Services.Immortal
@using System.Reflection @using System.Globalization
@using System.Reflection
@using System.Timers

6
IGP/wwwroot/content/docs/cheat-sheet.md

@ -1,8 +1,6 @@
--- ---
title: Cheat Sheet title: Cheat Sheet summary: Handy links or quick information on this project. created_date: 2022-04-11 updated_date:
summary: Handy links or quick information on this project. 2022-04-11
created_date: 2022-04-11
updated_date: 2022-04-11
--- ---
# Overview # Overview

15
IGP/wwwroot/content/docs/project-data.md

@ -1,8 +1,5 @@
--- ---
title: Project Data title: Project Data summary: Using data in this project. created_date: 2022-04-11 updated_date: 2022-04-11
summary: Using data in this project.
created_date: 2022-04-11
updated_date: 2022-04-11
--- ---
# Overview # Overview
@ -11,7 +8,8 @@ This document will contain general information on data in this project.
## General Note ## General Note
This project is a work in progress. As such, most of the data in the website doesn't follow the document. Ideally, this will be fixed over time. This project is a work in progress. As such, most of the data in the website doesn't follow the document. Ideally, this
will be fixed over time.
## SQL ## SQL
@ -19,7 +17,9 @@ Relational data is stored in a local SQL database.
This data is converted into JSON so it can be handled by Blazor WASM. This data is converted into JSON so it can be handled by Blazor WASM.
<i>Currently, Blazor WASM has a bug that prevents SQL from being used in production. Although, given SQL doesn't seem to provide much, aside from increased build times and load times, it might just be best to use the design principals of SQL, and it's interface, without using the actual technology in production.</i> <i>Currently, Blazor WASM has a bug that prevents SQL from being used in production. Although, given SQL doesn't seem to
provide much, aside from increased build times and load times, it might just be best to use the design principals of
SQL, and it's interface, without using the actual technology in production.</i>
The data is then loaded in by a Service, via it's load method. The data is then loaded in by a Service, via it's load method.
@ -90,7 +90,8 @@ else
Localized strings are handled in the Localizations.resx file. Localized strings are handled in the Localizations.resx file.
Most text isn't using localized strings yet. And English is the only plan of support in the short term, and probably in the long term as well. Most text isn't using localized strings yet. And English is the only plan of support in the short term, and probably in
the long term as well.
## Markdown Files ## Markdown Files

29
IGP/wwwroot/content/docs/setup.md

@ -1,18 +1,15 @@
--- ---
title: Setup title: Setup summary: Get set up on developing this web project. created_date: 3/30/2022 updated_date: 4/7/2022
summary: Get set up on developing this web project.
created_date: 3/30/2022
updated_date: 4/7/2022
--- ---
# Overview # Overview
This document will contain general setup notes for the project. This document will contain general setup notes for the project.
## Prerequisite ## Prerequisite
To understand content in this document, it is recommended to have some software development experience. Particularly using GitHub and Visual Studio. To understand content in this document, it is recommended to have some software development experience. Particularly
using GitHub and Visual Studio.
- [GitHub Documentation](https://docs.github.com/en/get-started) - [GitHub Documentation](https://docs.github.com/en/get-started)
@ -24,10 +21,13 @@ To make updates to this website, it is recommended to understand HTML/CSS and C#
- [Mozilla's HTML Documentation](https://developer.mozilla.org/en-US/docs/Learn/HTML/Introduction_to_HTML/Getting_started) - [Mozilla's HTML Documentation](https://developer.mozilla.org/en-US/docs/Learn/HTML/Introduction_to_HTML/Getting_started)
- [W3SCHOOLS' HTML Documentation](https://www.w3schools.com/html/) - [W3SCHOOLS' HTML Documentation](https://www.w3schools.com/html/)
Further, you should understand the product and clients this website is for. So it is recommended to play "Immortal: Gates of Pyre". Further, you should understand the product and clients this website is for. So it is recommended to play "Immortal:
Gates of Pyre".
- [IGP Website](https://gatesofpyre.com/) - [IGP Website](https://gatesofpyre.com/)
- **Please Note:** This product currently has restricted access with it is in a pre-alpha state. If you are not aware or interested in IGP, I recommend to wait for product release. Otherwise, check out their discord for steps of getting access. - **Please Note:** This product currently has restricted access with it is in a pre-alpha state. If you are not
aware or interested in IGP, I recommend to wait for product release. Otherwise, check out their discord for steps
of getting access.
## Installation ## Installation
@ -37,7 +37,8 @@ Download and install Visual Studio preview.
[https://visualstudio.microsoft.com/vs/preview/](https://visualstudio.microsoft.com/vs/preview/) [https://visualstudio.microsoft.com/vs/preview/](https://visualstudio.microsoft.com/vs/preview/)
When installing, ensure you have selected "Workloads | **ASP.NET and web development**" and "Individual components | **.NET WebAssembly build tools**". When installing, ensure you have selected "Workloads | **ASP.NET and web development**" and "Individual components | **
.NET WebAssembly build tools**".
## Download Project ## Download Project
@ -77,11 +78,13 @@ C:.
Code committed to the `main` branch will automatically be deployed to [production](https://www.igpfanreference.com/). Code committed to the `main` branch will automatically be deployed to [production](https://www.igpfanreference.com/).
Code committed to the `develop` branch will automatically be deployed to [development](https://calm-mud-04916b210.1.azurestaticapps.net/). Code committed to the `develop` branch will automatically be deployed
to [development](https://calm-mud-04916b210.1.azurestaticapps.net/).
_This is handle via the files in `.github/workflow`. Look into these [GitHub Actions Documents](https://docs.github.com/en/actions) if curious about how this CI system works._ _This is handle via the files in `.github/workflow`. Look into
these [GitHub Actions Documents](https://docs.github.com/en/actions) if curious about how this CI system works._
## Troubleshooting ## Troubleshooting
Nothing that some good internet searches cannot resolved. But you can also contact the project maintainer
Nothing that some good internet searches cannot resolved. But you can also contact the project maintainer on [Discord](https://discord.gg/uMq8bMGeeN). on [Discord](https://discord.gg/uMq8bMGeeN).

36
IGP/wwwroot/content/notes/coop/holdout.md

@ -1,26 +1,27 @@
--- ---
title: Holdout title: Holdout summary: First coop test map in pre-alpha. created_date: 2/18/2022 updated_date: 2/18/2022
summary: First coop test map in pre-alpha.
created_date: 2/18/2022
updated_date: 2/18/2022
--- ---
Information contained in this note is based on this <a href="https://www.youtube.com/watch?v=XkAgOCIz3DE">YouTube, Reference Video</a>. Information contained in this note is based on this <a href="https://www.youtube.com/watch?v=XkAgOCIz3DE">YouTube,
Reference Video</a>.
![Open Bases](./image/notes/coop-holdout/OpenBases.png) ![Open Bases](./image/notes/coop-holdout/OpenBases.png)
**Open Bases** **Open Bases**
On this map, you start with around 500 alloy and 100 ether. You are probably going to want to expand to the bases in the marked order, given the density of defending enemies shown on the minimap. On this map, you start with around 500 alloy and 100 ether. You are probably going to want to expand to the bases in the
marked order, given the density of defending enemies shown on the minimap.
You should know that these are all standard bases that will mine out in 10 minutes. Giving a total of 18,000 alloy and 7,200 ether. Plus an additional 6,000 alloy from the starting Bastion. In the late game, you will have zero income, aside from pyre.
You should know that these are all standard bases that will mine out in 10 minutes. Giving a total of 18,000 alloy and
7,200 ether. Plus an additional 6,000 alloy from the starting Bastion. In the late game, you will have zero income,
aside from pyre.
![Enemy Spawns](./image/notes/coop-holdout/EnemySpawns.png) ![Enemy Spawns](./image/notes/coop-holdout/EnemySpawns.png)
**Enemy Spawn Areas** **Enemy Spawn Areas**
The first enemy wave will spawn at 1 minute, and every 2 minutes after will spawn a new wave. These waves are small, and won't be a threat until the 15-minute mark. The first enemy wave will spawn at 1 minute, and every 2 minutes after will spawn a new wave. These waves are small, and
won't be a threat until the 15-minute mark.
![Defend Points](./image/notes/coop-holdout/DefendPoints.png) ![Defend Points](./image/notes/coop-holdout/DefendPoints.png)
@ -28,19 +29,26 @@ The first enemy wave will spawn at 1 minute, and every 2 minutes after will spaw
You have till then to take all 5 of your bases, and set a defensive line at the outer Pyre towers. You have till then to take all 5 of your bases, and set a defensive line at the outer Pyre towers.
The spawn size post the 15-minute mark does become rather large. You may be tempted to fall back and abandon forward bases, but the waves will stack if not dealt with. Eventually, more units than the game can handle, so ensure outer pyre towers are held. Try to take them back if you lose them. The spawn size post the 15-minute mark does become rather large. You may be tempted to fall back and abandon forward
bases, but the waves will stack if not dealt with. Eventually, more units than the game can handle, so ensure outer pyre
towers are held. Try to take them back if you lose them.
![Pyre](./image/notes/coop-holdout/Pyre.png) ![Pyre](./image/notes/coop-holdout/Pyre.png)
**Pyre Camps** **Pyre Camps**
When you have the time you are also going to need to take the 4 pyre camps spread around the map. It will probably be ideal to split your army in half, to protect your two outer towers, and just have a small force of Ichors or Dervishes to clear the camps quickly. When you have the time you are also going to need to take the 4 pyre camps spread around the map. It will probably be
ideal to split your army in half, to protect your two outer towers, and just have a small force of Ichors or Dervishes
to clear the camps quickly.
![Multipliers](./image/notes/coop-holdout/Multipliers.png) ![Multipliers](./image/notes/coop-holdout/Multipliers.png)
**Multipliers** **Multipliers**
If you have additional free time, you can take out the Altar of the Worthys on the edges of the map to double your current more multiplier: 2, 4, 8, to the max of 16. Amber Wombs will also spawn, with a pack of enemies to defend them. Killing an Amber Womb will increase your score, but also spawn random friendly and enemy units. With this spawning, it's possible to go past the supply cap. If you have additional free time, you can take out the Altar of the Worthys on the edges of the map to double your
current more multiplier: 2, 4, 8, to the max of 16. Amber Wombs will also spawn, with a pack of enemies to defend them.
Killing an Amber Womb will increase your score, but also spawn random friendly and enemy units. With this spawning, it's
possible to go past the supply cap.
But really, these optional objectives can be completely ignored, so you can just focus on surviving for as long as possible. But really, these optional objectives can be completely ignored, so you can just focus on surviving for as long as
possible.

177
IGP/wwwroot/content/notes/settings/hotkeys.md

@ -1,8 +1,6 @@
--- ---
title: Custom HotKey Setup title: Custom HotKey Setup summary: Customize your hotkeys in the pre-alpha. created_date: 4/13/2022 updated_date:
summary: Customize your hotkeys in the pre-alpha. 4/13/2022
created_date: 4/13/2022
updated_date: 4/13/2022
--- ---
In the pre-alpha, IGP comes with some Unreal default hotkey setup. In the pre-alpha, IGP comes with some Unreal default hotkey setup.
@ -15,78 +13,79 @@ This document will explain how to set up, modify, and use a new hotkey setup.
```ini ```ini
[/Script/Engine.InputSettings] [/Script/Engine.InputSettings]
ActionMappings=(ActionName="Ability1",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Q) ActionMappings = (ActionName="Ability1",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Q)
ActionMappings=(ActionName="Ability2",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=W) ActionMappings = (ActionName="Ability2",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=W)
ActionMappings=(ActionName="Ability3",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=E) ActionMappings = (ActionName="Ability3",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=E)
ActionMappings=(ActionName="Ability4",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=R) ActionMappings = (ActionName="Ability4",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=R)
ActionMappings=(ActionName="Ability5",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=F) ActionMappings = (ActionName="Ability5",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=F)
ActionMappings=(ActionName="Ability6",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=V) ActionMappings = (ActionName="Ability6",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=V)
ActionMappings=(ActionName="Ability7",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=A) ActionMappings = (ActionName="Ability7",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=A)
ActionMappings=(ActionName="Ability8",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=S) ActionMappings = (ActionName="Ability8",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=S)
ActionMappings=(ActionName="AttackMove",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=A) ActionMappings = (ActionName="AttackMove",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=A)
ActionMappings=(ActionName="CancelOrders",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Tilde) ActionMappings = (ActionName="CancelOrders",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Tilde)
ActionMappings=(ActionName="CompleteAllTraining",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=I) ActionMappings = (ActionName="CompleteAllTraining",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=I)
ActionMappings=(ActionName="CompleteConstructions",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=K) ActionMappings = (ActionName="CompleteConstructions",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=K)
ActionMappings=(ActionName="ConstructionTab",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=C) ActionMappings = (ActionName="ConstructionTab",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=C)
ActionMappings=(ActionName="ControlGroup1",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=D) ActionMappings = (ActionName="ControlGroup1",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=D)
ActionMappings=(ActionName="ControlGroup10",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Zero) ActionMappings = (ActionName="ControlGroup10",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Zero)
ActionMappings=(ActionName="ControlGroup2",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Two) ActionMappings = (ActionName="ControlGroup2",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Two)
ActionMappings=(ActionName="ControlGroup3",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Three) ActionMappings = (ActionName="ControlGroup3",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Three)
ActionMappings=(ActionName="ControlGroup4",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Four) ActionMappings = (ActionName="ControlGroup4",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Four)
ActionMappings=(ActionName="ControlGroup5",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Five) ActionMappings = (ActionName="ControlGroup5",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Five)
ActionMappings=(ActionName="ControlGroup6",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Six) ActionMappings = (ActionName="ControlGroup6",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Six)
ActionMappings=(ActionName="ControlGroup7",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Seven) ActionMappings = (ActionName="ControlGroup7",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Seven)
ActionMappings=(ActionName="ControlGroup8",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Eight) ActionMappings = (ActionName="ControlGroup8",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Eight)
ActionMappings=(ActionName="ControlGroup9",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Nine) ActionMappings = (ActionName="ControlGroup9",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Nine)
ActionMappings=(ActionName="ControlGroupAddStealKey",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=SpaceBar) ActionMappings = (ActionName="ControlGroupAddStealKey",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=SpaceBar)
ActionMappings=(ActionName="Delete",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Delete) ActionMappings = (ActionName="Delete",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Delete)
ActionMappings=(ActionName="DisableWeapons",bShift=True,bCtrl=False,bAlt=True,bCmd=False,Key=J) ActionMappings = (ActionName="DisableWeapons",bShift=True,bCtrl=False,bAlt=True,bCmd=False,Key=J)
ActionMappings=(ActionName="DownArrow",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Down) ActionMappings = (ActionName="DownArrow",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Down)
ActionMappings=(ActionName="DragPan",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=MiddleMouseButton) ActionMappings = (ActionName="DragPan",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=MiddleMouseButton)
ActionMappings=(ActionName="Enter Cinematic Camera",bShift=True,bCtrl=False,bAlt=True,bCmd=False,Key=L) ActionMappings = (ActionName="Enter Cinematic Camera",bShift=True,bCtrl=False,bAlt=True,bCmd=False,Key=L)
ActionMappings=(ActionName="FullMana",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=J) ActionMappings = (ActionName="FullMana",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=J)
ActionMappings=(ActionName="FullyDamageSelectedUnits",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=P) ActionMappings = (ActionName="FullyDamageSelectedUnits",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=P)
ActionMappings=(ActionName="GetAlloyEther",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=M) ActionMappings = (ActionName="GetAlloyEther",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=M)
ActionMappings=(ActionName="GetPyre",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=L) ActionMappings = (ActionName="GetPyre",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=L)
ActionMappings=(ActionName="Hide HUD",bShift=True,bCtrl=False,bAlt=True,bCmd=False,Key=O) ActionMappings = (ActionName="Hide HUD",bShift=True,bCtrl=False,bAlt=True,bCmd=False,Key=O)
ActionMappings=(ActionName="InclusiveSelect/QueueCommand",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=LeftShift) ActionMappings = (ActionName="InclusiveSelect/QueueCommand",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=LeftShift)
ActionMappings=(ActionName="JumpToCameraLocation1",bShift=True,bCtrl=False,bAlt=False,bCmd=False,Key=Z) ActionMappings = (ActionName="JumpToCameraLocation1",bShift=True,bCtrl=False,bAlt=False,bCmd=False,Key=Z)
ActionMappings=(ActionName="JumpToCameraLocation2",bShift=True,bCtrl=False,bAlt=False,bCmd=False,Key=X) ActionMappings = (ActionName="JumpToCameraLocation2",bShift=True,bCtrl=False,bAlt=False,bCmd=False,Key=X)
ActionMappings=(ActionName="JumpToCameraLocation3",bShift=True,bCtrl=False,bAlt=False,bCmd=False,Key=C) ActionMappings = (ActionName="JumpToCameraLocation3",bShift=True,bCtrl=False,bAlt=False,bCmd=False,Key=C)
ActionMappings=(ActionName="JumpToCameraLocation4",bShift=True,bCtrl=False,bAlt=False,bCmd=False,Key=V) ActionMappings = (ActionName="JumpToCameraLocation4",bShift=True,bCtrl=False,bAlt=False,bCmd=False,Key=V)
ActionMappings=(ActionName="JumpToCameraLocation5",bShift=True,bCtrl=False,bAlt=False,bCmd=False,Key=Two) ActionMappings = (ActionName="JumpToCameraLocation5",bShift=True,bCtrl=False,bAlt=False,bCmd=False,Key=Two)
ActionMappings=(ActionName="JumpToCameraLocation6",bShift=True,bCtrl=False,bAlt=False,bCmd=False,Key=Three) ActionMappings = (ActionName="JumpToCameraLocation6",bShift=True,bCtrl=False,bAlt=False,bCmd=False,Key=Three)
ActionMappings=(ActionName="JumpToCameraLocation7",bShift=True,bCtrl=False,bAlt=False,bCmd=False,Key=Four) ActionMappings = (ActionName="JumpToCameraLocation7",bShift=True,bCtrl=False,bAlt=False,bCmd=False,Key=Four)
ActionMappings=(ActionName="LeftArrow",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Left) ActionMappings = (ActionName="LeftArrow",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Left)
ActionMappings=(ActionName="LeftMouseClick",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=LeftMouseButton) ActionMappings = (ActionName="LeftMouseClick",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=LeftMouseButton)
ActionMappings=(ActionName="MarcoPolo",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Comma) ActionMappings = (ActionName="MarcoPolo",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Comma)
ActionMappings=(ActionName="Menu",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Escape) ActionMappings = (ActionName="Menu",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Escape)
ActionMappings=(ActionName="Menu",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=F10) ActionMappings = (ActionName="Menu",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=F10)
ActionMappings=(ActionName="MinimapJumpTo",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=LeftMouseButton) ActionMappings = (ActionName="MinimapJumpTo",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=LeftMouseButton)
ActionMappings=(ActionName="Move/ContextCommand",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=RightMouseButton) ActionMappings = (ActionName="Move/ContextCommand",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=RightMouseButton)
ActionMappings=(ActionName="PyreTab",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=One) ActionMappings = (ActionName="PyreTab",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=One)
ActionMappings=(ActionName="ResearchTab",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Tab) ActionMappings = (ActionName="ResearchTab",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Tab)
ActionMappings=(ActionName="RespawnNeutrals",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=N) ActionMappings = (ActionName="RespawnNeutrals",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=N)
ActionMappings=(ActionName="RightArrow",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Right) ActionMappings = (ActionName="RightArrow",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Right)
ActionMappings=(ActionName="RightMouseClick",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=RightMouseButton) ActionMappings = (ActionName="RightMouseClick",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=RightMouseButton)
ActionMappings=(ActionName="Select/ConfirmAbility",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=LeftMouseButton) ActionMappings = (ActionName="Select/ConfirmAbility",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=LeftMouseButton)
ActionMappings=(ActionName="SelectUnitProductionBuildings",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Z) ActionMappings = (ActionName="SelectUnitProductionBuildings",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Z)
ActionMappings=(ActionName="SetCameraLocation1",bShift=False,bCtrl=True,bAlt=False,bCmd=False,Key=Z) ActionMappings = (ActionName="SetCameraLocation1",bShift=False,bCtrl=True,bAlt=False,bCmd=False,Key=Z)
ActionMappings=(ActionName="SetCameraLocation2",bShift=False,bCtrl=True,bAlt=False,bCmd=False,Key=X) ActionMappings = (ActionName="SetCameraLocation2",bShift=False,bCtrl=True,bAlt=False,bCmd=False,Key=X)
ActionMappings=(ActionName="SetCameraLocation3",bShift=False,bCtrl=True,bAlt=False,bCmd=False,Key=C) ActionMappings = (ActionName="SetCameraLocation3",bShift=False,bCtrl=True,bAlt=False,bCmd=False,Key=C)
ActionMappings=(ActionName="SetCameraLocation4",bShift=False,bCtrl=True,bAlt=False,bCmd=False,Key=V) ActionMappings = (ActionName="SetCameraLocation4",bShift=False,bCtrl=True,bAlt=False,bCmd=False,Key=V)
ActionMappings=(ActionName="SetCameraLocation5",bShift=False,bCtrl=True,bAlt=False,bCmd=False,Key=Two) ActionMappings = (ActionName="SetCameraLocation5",bShift=False,bCtrl=True,bAlt=False,bCmd=False,Key=Two)
ActionMappings=(ActionName="SetCameraLocation6",bShift=False,bCtrl=True,bAlt=False,bCmd=False,Key=Three) ActionMappings = (ActionName="SetCameraLocation6",bShift=False,bCtrl=True,bAlt=False,bCmd=False,Key=Three)
ActionMappings=(ActionName="SetCameraLocation7",bShift=False,bCtrl=True,bAlt=False,bCmd=False,Key=Four) ActionMappings = (ActionName="SetCameraLocation7",bShift=False,bCtrl=True,bAlt=False,bCmd=False,Key=Four)
ActionMappings=(ActionName="StandGround",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=S) ActionMappings = (ActionName="StandGround",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=S)
ActionMappings=(ActionName="SwitchAbilityCommandLayer",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=SpaceBar) ActionMappings = (ActionName="SwitchAbilityCommandLayer",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=SpaceBar)
ActionMappings=(ActionName="TheCheatToRuleThemAll",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=None) ActionMappings = (ActionName="TheCheatToRuleThemAll",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=None)
ActionMappings=(ActionName="Toggle Gamepad",bShift=False,bCtrl=True,bAlt=True,bCmd=False,Key=Slash) ActionMappings = (ActionName="Toggle Gamepad",bShift=False,bCtrl=True,bAlt=True,bCmd=False,Key=Slash)
ActionMappings=(ActionName="UpArrow",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Up) ActionMappings = (ActionName="UpArrow",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Up)
ActionMappings=(ActionName="ZoomIn",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=MouseScrollUp) ActionMappings = (ActionName="ZoomIn",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=MouseScrollUp)
ActionMappings=(ActionName="ZoomOut",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=MouseScrollDown) ActionMappings = (ActionName="ZoomOut",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=MouseScrollDown)
ActionMappings=(ActionName="UnitTypeSelectionModifier",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=LeftControl) ActionMappings = (ActionName="UnitTypeSelectionModifier",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=LeftControl)
``` ```
***Copy the above content and save the file as `Input.ini`.*** ***Copy the above content and save the file as `Input.ini`.***
## Understand the Input.ini ## Understand the Input.ini
@ -94,13 +93,20 @@ ActionMappings=(ActionName="UnitTypeSelectionModifier",bShift=False,bCtrl=False,
You can notice a single line of this file can be broken down like this. You can notice a single line of this file can be broken down like this.
`ActionMappings=(ActionName="AttackMove",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=A)` `ActionMappings=(ActionName="AttackMove",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=A)`
- `ActionMappings=(***)`: Indicates content is an action mapping. i.e. a hotkey - `ActionMappings=(***)`: Indicates content is an action mapping. i.e. a hotkey
- `ActionName="AttackMove"`: Indicates the name of the selected action. Here, we are using the `AttackMove` move action, that forces your selected army to attack. - `ActionName="AttackMove"`: Indicates the name of the selected action. Here, we are using the `AttackMove` move action,
- `Key=A`: Indicates key being mapped to the action. Set to `Key=Tab` to require the Tab key to be pressed instead, to perform the `AttackMove` action. that forces your selected army to attack.
- `bShift=False`: Indicates that the Shift key is not held. Set to `bShift=True` to require a shift key held to perform the mapped action. - `Key=A`: Indicates key being mapped to the action. Set to `Key=Tab` to require the Tab key to be pressed instead, to
- `bCtrl=False`: Indicates that the Ctrl key is not held. Set to `bCtrl=True` to require a ctrl key held to perform the mapped action. perform the `AttackMove` action.
- `bAlt=False`: Indicates that the Alt key is not held. Set to `bAlt=True` to require a alt key held to perform the mapped action. - `bShift=False`: Indicates that the Shift key is not held. Set to `bShift=True` to require a shift key held to
- `bCmd=False`: Indicates that the Cmd key is not held. Set to `bCmd=True` to require a cmd key held to perform the mapped action. (Macs not supported by IGP) perform the mapped action.
- `bCtrl=False`: Indicates that the Ctrl key is not held. Set to `bCtrl=True` to require a ctrl key held to perform
the mapped action.
- `bAlt=False`: Indicates that the Alt key is not held. Set to `bAlt=True` to require a alt key held to perform the
mapped action.
- `bCmd=False`: Indicates that the Cmd key is not held. Set to `bCmd=True` to require a cmd key held to perform the
mapped action. (Macs not supported by IGP)
## Modify the Input.ini file ## Modify the Input.ini file
@ -108,9 +114,11 @@ You are now going to want to modify the file with your own hotkey setup.
To do this, replace any of the Key=`VALUE` mapped to the desired actions with any value from the list below. To do this, replace any of the Key=`VALUE` mapped to the desired actions with any value from the list below.
*For example, you can swap the Z Key value in SelectUnitProductionBuildings to C. Which would look like this: `ActionMappings=(ActionName="SelectUnitProductionBuildings",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=C)`* *For example, you can swap the Z Key value in SelectUnitProductionBuildings to C. Which would look like
this: `ActionMappings=(ActionName="SelectUnitProductionBuildings",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=C)`*
**Key Values** **Key Values**
- `AnyKey` - `AnyKey`
- `MouseX` - `MouseX`
- `MouseY` - `MouseY`
@ -242,8 +250,9 @@ To do this, replace any of the Key=`VALUE` mapped to the desired actions with an
# Transfer the Input.ini file # Transfer the Input.ini file
Drag and drop this new `Input.ini` file into `WindowsClient` folder in IGP. This folder can be found under `C:\Users\YOUR_USER\AppData\Local\Programs\CURRENT_IMMORTAL_CLIENT\Immortal\Saved\Config\WindowsClient\`. Drag and drop this new `Input.ini` file into `WindowsClient` folder in IGP. This folder can be found
Remember to use proper values for `YOUR_USER` and `CURRENT_IMMORTAL_CLIENT`. under `C:\Users\YOUR_USER\AppData\Local\Programs\CURRENT_IMMORTAL_CLIENT\Immortal\Saved\Config\WindowsClient\`. Remember
to use proper values for `YOUR_USER` and `CURRENT_IMMORTAL_CLIENT`.
There will be a blank `Input.ini` file in this folder. You can safely override it with your modified file. There will be a blank `Input.ini` file in this folder. You can safely override it with your modified file.

36
IGP/wwwroot/content/notes/the-basics/armor-types.md

@ -1,8 +1,5 @@
--- ---
title: Armor Types title: Armor Types summary: Heavy, Medium, and Light. What does it mean? created_date: 4/13/2000 updated_date: 4/13/2000
summary: Heavy, Medium, and Light. What does it mean?
created_date: 4/13/2000
updated_date: 4/13/2000
--- ---
## Armor Types ## Armor Types
@ -13,12 +10,14 @@ All units in "IMMORTAL: Gates of Pyre" have one of the three armor types.
- Medium - Medium
- Light - Light
These types mean nothing inherently. A Light armor unit will not take more damage than a Heavy armor unit, from the same damage source. These types mean nothing inherently. A Light armor unit will not take more damage than a Heavy armor unit, from the same
damage source.
Where this change is some units deal particular damage to a particular armor type. Where this change is some units deal particular damage to a particular armor type.
For example, a Dervish deals 16 damage generally, 24 to medium, and 32 damage to heavy armor types. For example, a Dervish deals 16 damage generally, 24 to medium, and 32 damage to heavy armor types. As an opposite
As an opposite example, the Zephyr will deal 20 damage generally, 24 to medium and 28 to heavy armor types. And as a different example, Sipari deals 20 damage generally, 18 damage to heavy armor. example, the Zephyr will deal 20 damage generally, 24 to medium and 28 to heavy armor types. And as a different example,
Sipari deals 20 damage generally, 18 damage to heavy armor.
Wait? There was no pattern to what general and specific damage is. Wait? There was no pattern to what general and specific damage is.
@ -32,29 +31,36 @@ They have two armies, one is a pack of Masked Hunters, and one is a pack of Xaca
Masked Hunters have the light armor type and Xacals have the heavy armor type. Masked Hunters have the light armor type and Xacals have the heavy armor type.
Well, you know Dervish deals the most damage to Light, and Zephyr deals the most damage to heavy, so you should generally have your Dervish attack the Masked Hunters and the Zephyr's attack the Xacals. Well, you know Dervish deals the most damage to Light, and Zephyr deals the most damage to heavy, so you should
generally have your Dervish attack the Masked Hunters and the Zephyr's attack the Xacals.
But wait, your opponent moved their two armies together! But wait, your opponent moved their two armies together!
Defensively, Masked Hunters deal less damage to the heavy armor type, and Xacals do less damage to Light. Defensively, Masked Hunters deal less damage to the heavy armor type, and Xacals do less damage to Light.
So while you want your Dervish to attack Masked Hunters, and the Zephyrs to attack the Xacals, you also want your Dervish to defend against the Xacals and Zephyrs to defend against the Masked Hunters. So while you want your Dervish to attack Masked Hunters, and the Zephyrs to attack the Xacals, you also want your
Dervish to defend against the Xacals and Zephyrs to defend against the Masked Hunters.
In mixed battles, you can spend some micro on your units to defend against enemy attackers they are strong against while having them attack potentially different enemies. In mixed battles, you can spend some micro on your units to defend against enemy attackers they are strong against while
having them attack potentially different enemies.
So what should you do? Build some Sipari, a Light armor unit, to help tank some Xacal shots, to give your Dervish and Zephyrs room to maneuver against their key targets.
So what should you do? Build some Sipari, a Light armor unit, to help tank some Xacal shots, to give your Dervish and
Zephyrs room to maneuver against their key targets.
## What else is there? ## What else is there?
Some units have additional tags, such as Structure and Etheric. Units can deal particular, or BONUS damage against enemies with those tags. Some units have additional tags, such as Structure and Etheric. Units can deal particular, or BONUS damage against
enemies with those tags.
**What are structures?** Structures are any building. Pretty much anything not a part of your moving army. **What are structures?** Structures are any building. Pretty much anything not a part of your moving army.
As an example of bonus damage, the Absolver deals +8 damage to structures, giving it 29 DPS to heavy structures. Conversely, it has 23 DPS against heavy structures when deployed, meaning Absolvers are better at sniping most structures when mobilized. As an example of bonus damage, the Absolver deals +8 damage to structures, giving it 29 DPS to heavy structures.
Conversely, it has 23 DPS against heavy structures when deployed, meaning Absolvers are better at sniping most
structures when mobilized.
Heads up though, that not all structures are heavy, examples include Radiant Wards generated by the Dervish. Heads up though, that not all structures are heavy, examples include Radiant Wards generated by the Dervish.
**What are etherics?** Etherics are most caster units in the game. These casters can generally win long drawn-out fights, so are good to snipe with units that deal extra damage against them. **What are etherics?** Etherics are most caster units in the game. These casters can generally win long drawn-out
fights, so are good to snipe with units that deal extra damage against them.
An etheric example would be the Bloodbounds Culling Strike ability, which deals bonus damage against etheric. An etheric example would be the Bloodbounds Culling Strike ability, which deals bonus damage against etheric.

6
IGP/wwwroot/content/notes/the-basics/economy-overview.md

@ -1,6 +1,4 @@
--- ---
title: Economy Overview title: Economy Overview summary: Alloy, Ether and Supply. Don't forget to expand!
summary: Alloy, Ether and Supply. Don't forget to expand! created_date: 1/01/2000 updated_date: 1/01/2000
created_date: 1/01/2000
updated_date: 1/01/2000
--- ---

6
IGP/wwwroot/content/notes/the-basics/families-factions-and-immortal-vanguards.md

@ -1,6 +1,4 @@
--- ---
title: Families, Factions, and Immortal Vanguards title: Families, Factions, and Immortal Vanguards summary: How IMMORTAL: Gates of Pyre handle your army selection
summary: How IMMORTAL: Gates of Pyre handle your army selection choices choices created_date: 1/01/2000 updated_date: 1/01/2000
created_date: 1/01/2000
updated_date: 1/01/2000
--- ---

6
IGP/wwwroot/content/notes/the-basics/immortal-spells-and-pyre.md

@ -1,8 +1,6 @@
--- ---
title: Immortals Spells and Pyre title: Immortals Spells and Pyre summary: Customize your hotkeys in the pre-alpha. created_date: 1/01/2000 updated_date:
summary: Customize your hotkeys in the pre-alpha. 1/01/2000
created_date: 1/01/2000
updated_date: 1/01/2000
--- ---
## What are Immortals ## What are Immortals

5
IGP/wwwroot/content/notes/the-basics/timing-and-scouting.md

@ -1,8 +1,5 @@
--- ---
title: Timing and Scouting title: Timing and Scouting summary: Knowing is half the battle. created_date: 1/01/2000 updated_date: 1/01/2000
summary: Knowing is half the battle.
created_date: 1/01/2000
updated_date: 1/01/2000
--- ---
## Timing ## Timing

2
IGP/wwwroot/css/app.css

@ -33,7 +33,7 @@
--info-secondary: #4c3e59; --info-secondary: #4c3e59;
--info-secondary-border: #7e58a2; --info-secondary-border: #7e58a2;
--info-hover: #451376; --info-hover: #451376;
--info-border-hover: #210b36; --info-border-hover: #210b36;

2
IGP/wwwroot/generated/AgileTaskModels.json

File diff suppressed because one or more lines are too long

6
IGP/wwwroot/service-worker.published.js

@ -8,8 +8,8 @@ self.addEventListener('fetch', event => event.respondWith(onFetch(event)));
const cacheNamePrefix = 'offline-cache-'; const cacheNamePrefix = 'offline-cache-';
const cacheName = `${cacheNamePrefix}${self.assetsManifest.version}`; const cacheName = `${cacheNamePrefix}${self.assetsManifest.version}`;
const offlineAssetsInclude = [ /\.dll$/, /\.pdb$/, /\.wasm/, /\.html/, /\.js$/, /\.json$/, /\.css$/, /\.woff$/, /\.png$/, /\.jpe?g$/, /\.gif$/, /\.ico$/, /\.blat$/, /\.dat$/ ]; const offlineAssetsInclude = [/\.dll$/, /\.pdb$/, /\.wasm/, /\.html/, /\.js$/, /\.json$/, /\.css$/, /\.woff$/, /\.png$/, /\.jpe?g$/, /\.gif$/, /\.ico$/, /\.blat$/, /\.dat$/];
const offlineAssetsExclude = [ /^service-worker\.js$/ ]; const offlineAssetsExclude = [/^service-worker\.js$/];
async function onInstall(event) { async function onInstall(event) {
console.info('Service worker: Install'); console.info('Service worker: Install');
@ -18,7 +18,7 @@ async function onInstall(event) {
const assetsRequests = self.assetsManifest.assets const assetsRequests = self.assetsManifest.assets
.filter(asset => offlineAssetsInclude.some(pattern => pattern.test(asset.url))) .filter(asset => offlineAssetsInclude.some(pattern => pattern.test(asset.url)))
.filter(asset => !offlineAssetsExclude.some(pattern => pattern.test(asset.url))) .filter(asset => !offlineAssetsExclude.some(pattern => pattern.test(asset.url)))
.map(asset => new Request(asset.url, { integrity: asset.hash, cache: 'no-cache' })); .map(asset => new Request(asset.url, {integrity: asset.hash, cache: 'no-cache'}));
await caches.open(cacheName).then(cache => cache.addAll(assetsRequests)); await caches.open(cacheName).then(cache => cache.addAll(assetsRequests));
} }

7
IGP_Convert/Program.cs

@ -10,7 +10,8 @@ var options = new DbContextOptionsBuilder<DatabaseContext>();
options.UseSqlite($"Filename={projectPath}/{webProjectName}/Database.db"); options.UseSqlite($"Filename={projectPath}/{webProjectName}/Database.db");
// Load our database // Load our database
using (var db = new DatabaseContext(options.Options)) { using (var db = new DatabaseContext(options.Options))
{
// And save data in format Blazor Wasm can use // And save data in format Blazor Wasm can use
File.WriteAllTextAsync($"{webPath}/GitPatchModels.json", JsonSerializer.Serialize(db.GitPatchModels)); File.WriteAllTextAsync($"{webPath}/GitPatchModels.json", JsonSerializer.Serialize(db.GitPatchModels));
File.WriteAllTextAsync($"{webPath}/GitChangeModels.json", JsonSerializer.Serialize(db.GitChangeModels)); File.WriteAllTextAsync($"{webPath}/GitChangeModels.json", JsonSerializer.Serialize(db.GitChangeModels));
@ -18,11 +19,11 @@ using (var db = new DatabaseContext(options.Options)) {
File.WriteAllTextAsync($"{webPath}/AgileTaskModels.json", JsonSerializer.Serialize(db.AgileTaskModels)); File.WriteAllTextAsync($"{webPath}/AgileTaskModels.json", JsonSerializer.Serialize(db.AgileTaskModels));
File.WriteAllTextAsync($"{webPath}/WebSectionModels.json", JsonSerializer.Serialize(db.WebSectionModels)); File.WriteAllTextAsync($"{webPath}/WebSectionModels.json", JsonSerializer.Serialize(db.WebSectionModels));
File.WriteAllTextAsync($"{webPath}/WebPageModels.json", JsonSerializer.Serialize(db.WebPageModels)); File.WriteAllTextAsync($"{webPath}/WebPageModels.json", JsonSerializer.Serialize(db.WebPageModels));
File.WriteAllTextAsync($"{webPath}/DocContentModels.json", JsonSerializer.Serialize(db.DocContentModels)); File.WriteAllTextAsync($"{webPath}/DocContentModels.json", JsonSerializer.Serialize(db.DocContentModels));
File.WriteAllTextAsync($"{webPath}/DocConnectionModels.json", JsonSerializer.Serialize(db.DocConnectionModels)); File.WriteAllTextAsync($"{webPath}/DocConnectionModels.json", JsonSerializer.Serialize(db.DocConnectionModels));
File.WriteAllTextAsync($"{webPath}/DocSectionModels.json", JsonSerializer.Serialize(db.DocSectionModels)); File.WriteAllTextAsync($"{webPath}/DocSectionModels.json", JsonSerializer.Serialize(db.DocSectionModels));
File.WriteAllTextAsync($"{webPath}/NoteContentModels.json", JsonSerializer.Serialize(db.NoteContentModels)); File.WriteAllTextAsync($"{webPath}/NoteContentModels.json", JsonSerializer.Serialize(db.NoteContentModels));
File.WriteAllTextAsync($"{webPath}/NoteConnectionModels.json", JsonSerializer.Serialize(db.NoteConnectionModels)); File.WriteAllTextAsync($"{webPath}/NoteConnectionModels.json", JsonSerializer.Serialize(db.NoteConnectionModels));
File.WriteAllTextAsync($"{webPath}/NoteSectionModels.json", JsonSerializer.Serialize(db.NoteSectionModels)); File.WriteAllTextAsync($"{webPath}/NoteSectionModels.json", JsonSerializer.Serialize(db.NoteSectionModels));

2
Model/Agile/AgileSprintModel.cs

@ -10,7 +10,7 @@ public class AgileSprintModel
public int Id { get; set; } public int Id { get; set; }
public string Name { get; set; } = "Add name..."; public string Name { get; set; } = "Add name...";
public string Description { get; set; } = "Add description..."; public string Description { get; set; } = "Add description...";
public DateTime? StartDate { get; set; } = null; public DateTime? StartDate { get; set; } = null;
public DateTime? EndDate { get; set; } = null; public DateTime? EndDate { get; set; } = null;

6
Model/Agile/AgileTaskModel.cs

@ -13,12 +13,12 @@ public class AgileTaskModel
public string Status { get; set; } = StatusType.Fun_Idea; public string Status { get; set; } = StatusType.Fun_Idea;
public string Priority { get; set; } = PriorityType.Medium; public string Priority { get; set; } = PriorityType.Medium;
public string Task { get; set; } = TaskType.Feature; public string Task { get; set; } = TaskType.Feature;
public int OrderPriority => Status == StatusType.In_Progress ? 1 public int OrderPriority => Status == StatusType.In_Progress ? 1
: Status == StatusType.Todo ? 2 : Status == StatusType.Todo ? 2
: Status == StatusType.Done ? 3 : Status == StatusType.Done ? 3
: Status == StatusType.Canceled ? 4 : Status == StatusType.Canceled ? 4
: Status == StatusType.To_Test ? 2 : Status == StatusType.To_Test ? 2
: Status == StatusType.Fun_Idea ? 5 : 6; : Status == StatusType.Fun_Idea ? 5 : 6;
public DateTime? Created { get; set; } = null; public DateTime? Created { get; set; } = null;

75
Model/BuildOrders/BuildOrderModel.cs

@ -1,7 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Model.Entity; using Model.Entity;
using Model.Entity.Data;
namespace Model.BuildOrders; namespace Model.BuildOrders;
@ -9,76 +8,16 @@ public class BuildOrderModel
{ {
public string Name { get; set; } = ""; public string Name { get; set; } = "";
public string Color { get; set; } = "red"; public string Color { get; set; } = "red";
public int CurrentSupplyUsed { get; set; } = 0;
public Dictionary<int, List<EntityModel>> StartedOrders { get; set; } = new()
{
{
0,
new List<EntityModel>
{
EntityModel.Get(DataType.STARTING_Bastion),
EntityModel.Get(DataType.STARTING_TownHall_Aru)
}
}
};
public Dictionary<int, List<EntityModel>> CompletedOrders { get; set; } = new()
{
{
0,
new List<EntityModel>
{
EntityModel.Get(DataType.STARTING_Bastion),
EntityModel.Get(DataType.STARTING_TownHall_Aru)
}
}
};
public Dictionary<string, int> UniqueCompletedTimes { get; set; } = new()
{
{
DataType.STARTING_Bastion, 0
},
{
DataType.STARTING_TownHall_Aru, 0
}
};
public Dictionary<string, int> UniqueCompletedCount { get; set; } = new()
{
{
DataType.STARTING_Bastion, 1
},
{
DataType.STARTING_TownHall_Aru, 1
}
};
public Dictionary<int, int> SupplyCountTimes { get; set; } = new()
{
{
0, 0
}
};
public string Notes { get; set; } = @""; public string Notes { get; set; } = @"";
public List<string> BuildTypes { get; set; } = new(); public List<string> BuildTypes { get; set; } = new();
public int CurrentSupplyUsed { get; set; } = 0;
public Dictionary<int, List<EntityModel>> StartedOrders { get; set; } = new();
public List<EntityModel> GetCompletedBefore(int interval) public Dictionary<int, List<EntityModel>> CompletedOrders { get; set; } = new();
{ public Dictionary<string, int> UniqueCompletedTimes { get; set; } = new();
return (from ordersAtTime in StartedOrders public Dictionary<string, int> UniqueCompletedCount { get; set; } = new();
from orders in ordersAtTime.Value public Dictionary<int, int> SupplyCountTimes { get; set; } = new();
where ordersAtTime.Key >= interval
where ordersAtTime.Key + (orders.Production() == null ? 0 : orders.Production().BuildTime) <= interval
select orders).ToList();
}
public List<EntityModel> GetHarvestersCompletedBefore(int interval) public List<EntityModel> GetHarvestersCompletedBefore(int interval)
{ {
return (from ordersAtTime in StartedOrders return (from ordersAtTime in StartedOrders

7
Model/Doc/DocContentModel.cs

@ -8,11 +8,14 @@ namespace Model.Doc;
public class DocContentModel public class DocContentModel
{ {
[Key] public int Id { get; set; } = 1; [Key] public int Id { get; set; } = 1;
public int? ParentId { get; set; } = null; public int? ParentId { get; set; } = null;
public int? DocSectionModelId { get; set; } = null; public int? DocSectionModelId { get; set; } = null;
public string Href { get; set; } public string Href { get; set; }
[NotMapped] public virtual ICollection<DocContentModel> DocumentationModels { get; set; } = new List<DocContentModel>();
[NotMapped]
public virtual ICollection<DocContentModel> DocumentationModels { get; set; } = new List<DocContentModel>();
[NotMapped] public virtual DocContentModel Parent { get; set; } [NotMapped] public virtual DocContentModel Parent { get; set; }
[NotMapped] public virtual int PageOrder { get; set; } [NotMapped] public virtual int PageOrder { get; set; }
public DateTime CreatedDate { get; set; } public DateTime CreatedDate { get; set; }

27
Model/Economy/EconomyOverTimeModel.cs

@ -100,27 +100,23 @@ public class EconomyOverTimeModel
// Remove Funds from Build Order // Remove Funds from Build Order
if (buildOrder.StartedOrders.TryGetValue(interval, out var ordersAtTime)) if (buildOrder.StartedOrders.TryGetValue(interval, out var ordersAtTime))
{ foreach (var order in ordersAtTime)
foreach (var order in ordersAtTime)
{
var foundEntity = EntityModel.GetDictionary()[order.DataType];
var production = foundEntity.Production();
if (production != null)
{ {
economyAtSecond.Alloy -= production.Alloy; var foundEntity = EntityModel.GetDictionary()[order.DataType];
economyAtSecond.Ether -= production.Ether; var production = foundEntity.Production();
var finishedAt = interval + production.BuildTime;
if (production != null)
{
economyAtSecond.Alloy -= production.Alloy;
economyAtSecond.Ether -= production.Ether;
var finishedAt = interval + production.BuildTime;
if (production.RequiresWorker) economyAtSecond.BusyWorkerCount += 1; if (production.RequiresWorker) economyAtSecond.BusyWorkerCount += 1;
}
} }
}
}
// Handle new entities // Handle new entities
if (buildOrder.StartedOrders.TryGetValue(interval, out var ordersCompletedAtTime)) if (buildOrder.StartedOrders.TryGetValue(interval, out var ordersCompletedAtTime))
{
foreach (var newEntity in ordersCompletedAtTime) foreach (var newEntity in ordersCompletedAtTime)
{ {
var harvest = newEntity; var harvest = newEntity;
@ -129,7 +125,6 @@ public class EconomyOverTimeModel
var production = newEntity.Production(); var production = newEntity.Production();
if (production != null && production.RequiresWorker) economyAtSecond.BusyWorkerCount -= 1; if (production != null && production.RequiresWorker) economyAtSecond.BusyWorkerCount -= 1;
} }
}
} }
} }
} }

310
Model/Entity/Data/DATA.cs

@ -55,7 +55,8 @@ public class DATA
DataType.TEAPOT_FlyingTeapot, new EntityModel(DataType.TEAPOT_FlyingTeapot, EntityType.Teapot) DataType.TEAPOT_FlyingTeapot, new EntityModel(DataType.TEAPOT_FlyingTeapot, EntityType.Teapot)
.AddPart(new EntityInfoModel .AddPart(new EntityInfoModel
{ {
Name = "Flying Teapot", Description = "Basic observer. Can fly and see hidden units within 1000 range.", Name = "Flying Teapot",
Description = "Basic observer. Can fly and see hidden units within 1000 range.",
Notes = @"Doesn't take up a scout slot." Notes = @"Doesn't take up a scout slot."
}) })
.AddPart(new EntityRequirementModel { Id = DataType.TEAPOT_Teapot }) .AddPart(new EntityRequirementModel { Id = DataType.TEAPOT_Teapot })
@ -236,7 +237,7 @@ public class DATA
Resource = ResourceType.Pyre, HarvestedPerInterval = 1, HarvestDelay = 3, Resource = ResourceType.Pyre, HarvestedPerInterval = 1, HarvestDelay = 3,
RequiresWorker = false, Slots = 1, TotalAmount = -1 RequiresWorker = false, Slots = 1, TotalAmount = -1
}) })
.AddPart(new EntityIdPassiveModel {Id = DataType.IPASSIVE_MothersHunger}) .AddPart(new EntityIdPassiveModel { Id = DataType.IPASSIVE_MothersHunger })
.AddPart(new EntityIdPyreSpellModel { Id = DataType.ISPELL_SummonGroveGuardian }) .AddPart(new EntityIdPyreSpellModel { Id = DataType.ISPELL_SummonGroveGuardian })
.AddPart(new EntityIdPyreSpellModel { Id = DataType.ISPELL_InfuseTroops }) .AddPart(new EntityIdPyreSpellModel { Id = DataType.ISPELL_InfuseTroops })
.AddPart(new EntityIdPyreSpellModel { Id = DataType.ISPELL_ConstructBloodWell }) .AddPart(new EntityIdPyreSpellModel { Id = DataType.ISPELL_ConstructBloodWell })
@ -255,7 +256,7 @@ public class DATA
Resource = ResourceType.Pyre, HarvestedPerInterval = 1, HarvestDelay = 3, Resource = ResourceType.Pyre, HarvestedPerInterval = 1, HarvestDelay = 3,
RequiresWorker = false, Slots = 1, TotalAmount = -1 RequiresWorker = false, Slots = 1, TotalAmount = -1
}) })
.AddPart(new EntityIdPassiveModel {Id = DataType.IPASSIVE_StalkersSense}) .AddPart(new EntityIdPassiveModel { Id = DataType.IPASSIVE_StalkersSense })
.AddPart(new EntityIdPyreSpellModel { Id = DataType.ISPELL_SummonGroveGuardian }) .AddPart(new EntityIdPyreSpellModel { Id = DataType.ISPELL_SummonGroveGuardian })
.AddPart(new EntityIdPyreSpellModel { Id = DataType.ISPELL_InfuseTroops }) .AddPart(new EntityIdPyreSpellModel { Id = DataType.ISPELL_InfuseTroops })
.AddPart(new EntityIdPyreSpellModel { Id = DataType.ISPELL_ConstructBloodWell }) .AddPart(new EntityIdPyreSpellModel { Id = DataType.ISPELL_ConstructBloodWell })
@ -276,7 +277,7 @@ public class DATA
Resource = ResourceType.Pyre, HarvestedPerInterval = 1, HarvestDelay = 3, Resource = ResourceType.Pyre, HarvestedPerInterval = 1, HarvestDelay = 3,
RequiresWorker = false, Slots = 1, TotalAmount = -1 RequiresWorker = false, Slots = 1, TotalAmount = -1
}) })
.AddPart(new EntityIdPassiveModel {Id = DataType.IPASSIVE_HealingGround}) .AddPart(new EntityIdPassiveModel { Id = DataType.IPASSIVE_HealingGround })
.AddPart(new EntityIdPyreSpellModel { Id = DataType.ISPELL_SummonCitadel }) .AddPart(new EntityIdPyreSpellModel { Id = DataType.ISPELL_SummonCitadel })
.AddPart(new EntityIdPyreSpellModel { Id = DataType.ISPELL_InfuseTroops }) .AddPart(new EntityIdPyreSpellModel { Id = DataType.ISPELL_InfuseTroops })
.AddPart(new EntityIdPyreSpellModel { Id = DataType.ISPELL_DeliverFromEvil }) .AddPart(new EntityIdPyreSpellModel { Id = DataType.ISPELL_DeliverFromEvil })
@ -294,7 +295,7 @@ public class DATA
Resource = ResourceType.Pyre, HarvestedPerInterval = 1, HarvestDelay = 3, Resource = ResourceType.Pyre, HarvestedPerInterval = 1, HarvestDelay = 3,
RequiresWorker = false, Slots = 1, TotalAmount = -1 RequiresWorker = false, Slots = 1, TotalAmount = -1
}) })
.AddPart(new EntityIdPassiveModel {Id = DataType.IPASSIVE_Expansionist}) .AddPart(new EntityIdPassiveModel { Id = DataType.IPASSIVE_Expansionist })
.AddPart(new EntityIdPyreSpellModel { Id = DataType.ISPELL_InfuseTroops }) .AddPart(new EntityIdPyreSpellModel { Id = DataType.ISPELL_InfuseTroops })
.AddPart(new EntityIdPyreSpellModel { Id = DataType.ISPELL_SummonCitadel }) .AddPart(new EntityIdPyreSpellModel { Id = DataType.ISPELL_SummonCitadel })
.AddPart(new EntityIdPyreSpellModel { Id = DataType.ISPELL_EmpireUnbroken }) .AddPart(new EntityIdPyreSpellModel { Id = DataType.ISPELL_EmpireUnbroken })
@ -320,20 +321,23 @@ public class DATA
DataType.IPASSIVE_MothersHunger, DataType.IPASSIVE_MothersHunger,
new EntityModel(DataType.IPASSIVE_MothersHunger, EntityType.Passive) new EntityModel(DataType.IPASSIVE_MothersHunger, EntityType.Passive)
.AddPart(new EntityInfoModel .AddPart(new EntityInfoModel
{ {
Name = "Mother's Hunger", Name = "Mother's Hunger",
Description = "Mala's Blood Wells grant you pyre for nearby non-quitl deaths, based on the supply.", Description =
Notes = "+1 per supply" "Mala's Blood Wells grant you pyre for nearby non-quitl deaths, based on the supply.",
Notes = "+1 per supply"
}) })
}, },
{ {
DataType.IPASSIVE_StalkersSense, DataType.IPASSIVE_StalkersSense,
new EntityModel(DataType.IPASSIVE_StalkersSense, EntityType.Passive) new EntityModel(DataType.IPASSIVE_StalkersSense, EntityType.Passive)
.AddPart(new EntityInfoModel .AddPart(new EntityInfoModel
{ Name = "Stalker's Sense", Description = "Xol's units sense nearby enemies in the fog of war.", Notes = "Not implemented."}) {
Name = "Stalker's Sense", Description = "Xol's units sense nearby enemies in the fog of war.",
Notes = "Not implemented."
})
}, },
// Keys // Keys
{ {
DataType.COMMAND_Attack, DataType.COMMAND_Attack,
@ -369,7 +373,7 @@ public class DATA
.AddPart(new EntityVitalityModel { Health = 500, Armor = ArmorType.Heavy }) .AddPart(new EntityVitalityModel { Health = 500, Armor = ArmorType.Heavy })
.AddPart(new EntityWeaponModel .AddPart(new EntityWeaponModel
{ Damage = 30, AttacksPerSecond = 1.401f, Targets = TargetType.All, Range = 700 }) { Damage = 30, AttacksPerSecond = 1.401f, Targets = TargetType.All, Range = 700 })
.AddPart(new EntityIdPassiveModel(){Id = DataType.PASSIVE_BastionPassives}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_BastionPassives })
}, },
{ {
DataType.STARTING_Tower, DataType.STARTING_Tower,
@ -389,7 +393,7 @@ public class DATA
MediumDamage = 25, HeavyDamage = 30 MediumDamage = 25, HeavyDamage = 30
}) })
.AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_Respite }) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_Respite })
.AddPart(new EntityIdPassiveModel(){Id = DataType.PASSIVE_HallowedGround}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_HallowedGround })
}, },
// Starting Structures // Starting Structures
// Aru // Aru
@ -406,7 +410,7 @@ public class DATA
HarvestedPerInterval = 1, RequiresWorker = true, Resource = ResourceType.Alloy, Slots = 6, HarvestedPerInterval = 1, RequiresWorker = true, Resource = ResourceType.Alloy, Slots = 6,
TotalAmount = 6000 TotalAmount = 6000
}) })
.AddPart(new EntityIdPassiveModel(){Id = DataType.PASSIVE_Rootway}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_Rootway })
}, },
// Starting Structures // Starting Structures
// Q'Rath // Q'Rath
@ -423,7 +427,7 @@ public class DATA
HarvestedPerInterval = 6, RequiresWorker = false, Resource = ResourceType.Alloy, Slots = 1, HarvestedPerInterval = 6, RequiresWorker = false, Resource = ResourceType.Alloy, Slots = 1,
TotalAmount = 6000 TotalAmount = 6000
}) })
.AddPart(new EntityIdPassiveModel(){Id = DataType.PASSIVE_HallowedGround}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_HallowedGround })
}, },
// Vanguard // Vanguard
@ -457,7 +461,7 @@ public class DATA
.AddPart(new EntityMovementModel { Speed = 380, Movement = MovementType.Ground }) .AddPart(new EntityMovementModel { Speed = 380, Movement = MovementType.Ground })
.AddPart(new EntityIdUpgradeModel { Id = DataType.UPGRADE_FaithCastBlades }) .AddPart(new EntityIdUpgradeModel { Id = DataType.UPGRADE_FaithCastBlades })
.AddPart(new EntityIdUpgradeModel { Id = DataType.UPGRADE_IconOfKhastEem }) .AddPart(new EntityIdUpgradeModel { Id = DataType.UPGRADE_IconOfKhastEem })
.AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_IconOfKhastEem}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_IconOfKhastEem })
.AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_FaithCastBlades }) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_FaithCastBlades })
}, },
{ {
@ -589,8 +593,6 @@ public class DATA
{ Damage = 16, Range = 700, AttacksPerSecond = 0.606f, Targets = TargetType.Ground }) { Damage = 16, Range = 700, AttacksPerSecond = 0.606f, Targets = TargetType.Ground })
.AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_ProjectileGestation }) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_ProjectileGestation })
.AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_FallenHarvest }) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_FallenHarvest })
}, },
{ {
DataType.VANGUARD_DreadSister_Mala, DataType.VANGUARD_DreadSister_Mala,
@ -647,8 +649,8 @@ public class DATA
.AddPart(new EntityMovementModel { Speed = 350, Movement = MovementType.Ground }) .AddPart(new EntityMovementModel { Speed = 350, Movement = MovementType.Ground })
.AddPart(new EntityWeaponModel .AddPart(new EntityWeaponModel
{ Damage = 11, Range = 400, AttacksPerSecond = 1.02f, Targets = TargetType.All }) { Damage = 11, Range = 400, AttacksPerSecond = 1.02f, Targets = TargetType.All })
.AddPart(new EntityIdPassiveModel(){Id = DataType.PASSIVE_Stalk}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_Stalk })
.AddPart(new EntityIdPassiveModel(){Id = DataType.PASSIVE_Ambush}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_Ambush })
}, },
{ {
DataType.VANGUARD_WhiteWoodReaper_Xol, DataType.VANGUARD_WhiteWoodReaper_Xol,
@ -726,10 +728,10 @@ public class DATA
Damage = 20, HeavyDamage = 18, Range = 180, AttacksPerSecond = 0.699f, Damage = 20, HeavyDamage = 18, Range = 180, AttacksPerSecond = 0.699f,
SecondsBetweenAttacks = 1.43f, Targets = TargetType.Ground SecondsBetweenAttacks = 1.43f, Targets = TargetType.Ground
}) })
.AddPart(new EntityIdUpgradeModel() { Id = DataType.UPGRADE_GreavesOfAhqar}) .AddPart(new EntityIdUpgradeModel { Id = DataType.UPGRADE_GreavesOfAhqar })
.AddPart(new EntityIdUpgradeModel() { Id = DataType.UPGRADE_FortifiedIcons}) .AddPart(new EntityIdUpgradeModel { Id = DataType.UPGRADE_FortifiedIcons })
.AddPart(new EntityIdPassiveModel() { Id = DataType.PASSIVE_GreavesOfAhqar}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_GreavesOfAhqar })
.AddPart(new EntityIdPassiveModel() { Id = DataType.PASSIVE_FortifiedIcons}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_FortifiedIcons })
}, },
{ {
DataType.UNIT_Magi, DataType.UNIT_Magi,
@ -832,9 +834,8 @@ public class DATA
}) })
.AddPart(new EntityIdUpgradeModel { Id = DataType.UPGRADE_SiroccoScript }) .AddPart(new EntityIdUpgradeModel { Id = DataType.UPGRADE_SiroccoScript })
.AddPart(new EntityIdUpgradeModel { Id = DataType.UPGRADE_RadiantWard }) .AddPart(new EntityIdUpgradeModel { Id = DataType.UPGRADE_RadiantWard })
.AddPart(new EntityIdAbilityModel {Id = DataType.ABILITY_RadiantWard}) .AddPart(new EntityIdAbilityModel { Id = DataType.ABILITY_RadiantWard })
.AddPart(new EntityIdPassiveModel(){Id = DataType.PASSIVE_SiroccoScript}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_SiroccoScript })
}, },
{ {
DataType.UNIT_Absolver, DataType.UNIT_Absolver,
@ -937,7 +938,6 @@ public class DATA
Damage = 60, MediumDamage = 80, HeavyDamage = 100, Range = 1300, AttacksPerSecond = 0.143f, Damage = 60, MediumDamage = 80, HeavyDamage = 100, Range = 1300, AttacksPerSecond = 0.143f,
Targets = TargetType.Ground Targets = TargetType.Ground
}) })
.AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_HallowedRuin }) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_HallowedRuin })
}, },
{ {
@ -1026,9 +1026,9 @@ public class DATA
.AddPart(new EntityMovementModel { Speed = 420, Movement = MovementType.Air }) .AddPart(new EntityMovementModel { Speed = 420, Movement = MovementType.Air })
.AddPart(new EntityWeaponModel .AddPart(new EntityWeaponModel
{ Damage = 32, Range = 600, AttacksPerSecond = 0.556f, Targets = TargetType.Ground }) { Damage = 32, Range = 600, AttacksPerSecond = 0.556f, Targets = TargetType.Ground })
.AddPart(new EntityIdUpgradeModel(){Id = DataType.UPGRADE_WingsOfTheKenLatir}) .AddPart(new EntityIdUpgradeModel { Id = DataType.UPGRADE_WingsOfTheKenLatir })
.AddPart(new EntityIdPassiveModel(){Id = DataType.PASSIVE_WingsOfTheKenLatir}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_WingsOfTheKenLatir })
.AddPart(new EntityIdPassiveModel(){Id = DataType.PASSIVE_ExecutionRites}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_ExecutionRites })
}, },
{ {
DataType.UNIT_SharU, DataType.UNIT_SharU,
@ -1167,7 +1167,6 @@ public class DATA
Targets = TargetType.Ground Targets = TargetType.Ground
}) })
.AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_QuenchingScythes }) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_QuenchingScythes })
.AddPart(new EntityIdPassiveModel { Id = DataType.ABILITY_CullingStrike }) .AddPart(new EntityIdPassiveModel { Id = DataType.ABILITY_CullingStrike })
}, },
{ {
@ -1267,7 +1266,7 @@ public class DATA
}) })
.AddPart(new EntityIdUpgradeModel { Id = DataType.UPGRADE_DenInstinct }) .AddPart(new EntityIdUpgradeModel { Id = DataType.UPGRADE_DenInstinct })
.AddPart(new EntityIdUpgradeModel { Id = DataType.UPGRADE_PursuitLigaments }) .AddPart(new EntityIdUpgradeModel { Id = DataType.UPGRADE_PursuitLigaments })
.AddPart(new EntityIdPassiveModel() { Id = DataType.PASSIVE_ExternalDigestion }) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_ExternalDigestion })
}, },
{ {
DataType.UNIT_Resinant, DataType.UNIT_Resinant,
@ -1332,8 +1331,7 @@ public class DATA
TargetType.Air TargetType.Air
}) })
.AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_AaroxBurn }) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_AaroxBurn })
.AddPart(new EntityIdAbilityModel { Id = DataType.ABILITY_DiveBomb })
.AddPart(new EntityIdAbilityModel() { Id = DataType.ABILITY_DiveBomb })
}, },
{ {
DataType.UNIT_Thrum, DataType.UNIT_Thrum,
@ -1378,7 +1376,7 @@ public class DATA
.AddPart(new EntityWeaponModel .AddPart(new EntityWeaponModel
{ Damage = 9, Range = 500, AttacksPerSecond = 0.714f, Targets = TargetType.Ground }) { Damage = 9, Range = 500, AttacksPerSecond = 0.714f, Targets = TargetType.Ground })
.AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_GuidingAmber }) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_GuidingAmber })
.AddPart(new EntityIdPassiveModel() { Id = DataType.PASSIVE_WraithBowRange }) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_WraithBowRange })
}, },
{ {
DataType.UNIT_Behemoth, DataType.UNIT_Behemoth,
@ -1409,8 +1407,6 @@ public class DATA
.AddPart(new EntityIdUpgradeModel { Id = DataType.UPGRADE_BehemothCapacity }) .AddPart(new EntityIdUpgradeModel { Id = DataType.UPGRADE_BehemothCapacity })
.AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_BehemothCapacity }) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_BehemothCapacity })
.AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_QuitlStorage2 }) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_QuitlStorage2 })
.AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_FireQuitl }) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_FireQuitl })
}, },
{ {
@ -1420,7 +1416,7 @@ public class DATA
.AddPart(new EntityFactionModel { Faction = FactionType.Aru }) .AddPart(new EntityFactionModel { Faction = FactionType.Aru })
.AddPart(new EntityVitalityModel { Health = 65, Armor = ArmorType.Light }) .AddPart(new EntityVitalityModel { Health = 65, Armor = ArmorType.Light })
.AddPart(new EntityMovementModel { Speed = 168, Movement = MovementType.Ground }) .AddPart(new EntityMovementModel { Speed = 168, Movement = MovementType.Ground })
.AddPart(new EntityIdPassiveModel() {Id = DataType.PASSIVE_Temporary}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_Temporary })
}, },
// Upgrades // Upgrades
// Q'Rath // Q'Rath
@ -1442,8 +1438,6 @@ public class DATA
}) })
.AddPart(new EntityVanguardReplacedModel .AddPart(new EntityVanguardReplacedModel
{ ImmortalId = DataType.IMMORTAL_Orzum, ReplacedById = DataType.UPGRADE_FaithCastBlades }) { ImmortalId = DataType.IMMORTAL_Orzum, ReplacedById = DataType.UPGRADE_FaithCastBlades })
}, },
{ {
DataType.UPGRADE_RadiantWard, DataType.UPGRADE_RadiantWard,
@ -1462,7 +1456,7 @@ public class DATA
Requirement = RequirementType.Production_Building Requirement = RequirementType.Production_Building
}) })
}, },
{ {
DataType.UPGRADE_FortifiedIcons, DataType.UPGRADE_FortifiedIcons,
new EntityModel(DataType.UPGRADE_FortifiedIcons, EntityType.Tech) new EntityModel(DataType.UPGRADE_FortifiedIcons, EntityType.Tech)
@ -1471,7 +1465,7 @@ public class DATA
Name = "Fortified Icons", Descriptive = DescriptiveType.Upgrade, Name = "Fortified Icons", Descriptive = DescriptiveType.Upgrade,
Description = "Sipari gain +20 shields, and Hallowed Ground grants an additional +20 shields." Description = "Sipari gain +20 shields, and Hallowed Ground grants an additional +20 shields."
}) })
.AddPart(new EntityHotkeyModel { Hotkey = "Q", HotkeyGroup = "TAB", HoldSpace = true}) .AddPart(new EntityHotkeyModel { Hotkey = "Q", HotkeyGroup = "TAB", HoldSpace = true })
.AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityFactionModel { Faction = FactionType.QRath })
.AddPart(new EntityProductionModel { Alloy = 100, Ether = 100, BuildTime = 43 }) .AddPart(new EntityProductionModel { Alloy = 100, Ether = 100, BuildTime = 43 })
.AddPart(new EntityRequirementModel .AddPart(new EntityRequirementModel
@ -1481,10 +1475,8 @@ public class DATA
}) })
.AddPart(new EntityVanguardReplacedModel .AddPart(new EntityVanguardReplacedModel
{ ImmortalId = DataType.IMMORTAL_Orzum, ReplacedById = DataType.UPGRADE_IconOfKhastEem }) { ImmortalId = DataType.IMMORTAL_Orzum, ReplacedById = DataType.UPGRADE_IconOfKhastEem })
}, },
{ {
DataType.UPGRADE_FaithCastBlades, DataType.UPGRADE_FaithCastBlades,
new EntityModel(DataType.UPGRADE_FaithCastBlades, EntityType.Tech) new EntityModel(DataType.UPGRADE_FaithCastBlades, EntityType.Tech)
@ -1496,10 +1488,10 @@ public class DATA
.AddPart(new EntityHotkeyModel { Hotkey = "Q", HotkeyGroup = "TAB" }) .AddPart(new EntityHotkeyModel { Hotkey = "Q", HotkeyGroup = "TAB" })
.AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityFactionModel { Faction = FactionType.QRath })
.AddPart(new EntityProductionModel { Alloy = 50, Ether = 100, BuildTime = 60 }) .AddPart(new EntityProductionModel { Alloy = 50, Ether = 100, BuildTime = 60 })
.AddPart(new EntityRequirementModel { Id = DataType.BUILDING_Reliquary, Requirement = RequirementType.Research_Building}) .AddPart(new EntityRequirementModel
{ Id = DataType.BUILDING_Reliquary, Requirement = RequirementType.Research_Building })
.AddPart(new EntityVanguardAddedModel .AddPart(new EntityVanguardAddedModel
{ ReplaceId = DataType.UPGRADE_GreavesOfAhqar, ImmortalId = DataType.IMMORTAL_Orzum }) { ReplaceId = DataType.UPGRADE_GreavesOfAhqar, ImmortalId = DataType.IMMORTAL_Orzum })
}, },
{ {
DataType.UPGRADE_RelicOfTheWrathfulGaze, DataType.UPGRADE_RelicOfTheWrathfulGaze,
@ -1526,7 +1518,8 @@ public class DATA
.AddPart(new EntityHotkeyModel { Hotkey = "W", HotkeyGroup = "TAB" }) .AddPart(new EntityHotkeyModel { Hotkey = "W", HotkeyGroup = "TAB" })
.AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityFactionModel { Faction = FactionType.QRath })
.AddPart(new EntityProductionModel { Alloy = 50, Ether = 75, BuildTime = 55 }) .AddPart(new EntityProductionModel { Alloy = 50, Ether = 75, BuildTime = 55 })
.AddPart(new EntityRequirementModel { Id = DataType.BUILDING_Reliquary, Requirement = RequirementType.Production_Building }) .AddPart(new EntityRequirementModel
{ Id = DataType.BUILDING_Reliquary, Requirement = RequirementType.Production_Building })
}, },
{ {
DataType.UPGRADE_ZephyrRange, DataType.UPGRADE_ZephyrRange,
@ -1539,7 +1532,8 @@ public class DATA
.AddPart(new EntityHotkeyModel { Hotkey = "E", HotkeyGroup = "TAB" }) .AddPart(new EntityHotkeyModel { Hotkey = "E", HotkeyGroup = "TAB" })
.AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityFactionModel { Faction = FactionType.QRath })
.AddPart(new EntityProductionModel { Alloy = 150, Ether = 100, BuildTime = 43 }) .AddPart(new EntityProductionModel { Alloy = 150, Ether = 100, BuildTime = 43 })
.AddPart(new EntityRequirementModel { Id = DataType.UPGRADE_ZephyrRange, Requirement = RequirementType.Production_Building }) .AddPart(new EntityRequirementModel
{ Id = DataType.UPGRADE_ZephyrRange, Requirement = RequirementType.Production_Building })
.AddPart(new EntityIdUpgradeModel { Id = DataType.UPGRADE_WindStep }) .AddPart(new EntityIdUpgradeModel { Id = DataType.UPGRADE_WindStep })
.AddPart(new EntityIdUpgradeModel { Id = DataType.UPGRADE_ZephyrRange }) .AddPart(new EntityIdUpgradeModel { Id = DataType.UPGRADE_ZephyrRange })
}, },
@ -1578,8 +1572,6 @@ public class DATA
}) })
.AddPart(new EntityVanguardAddedModel .AddPart(new EntityVanguardAddedModel
{ ReplaceId = DataType.UPGRADE_FortifiedIcons, ImmortalId = DataType.IMMORTAL_Orzum }) { ReplaceId = DataType.UPGRADE_FortifiedIcons, ImmortalId = DataType.IMMORTAL_Orzum })
}, },
{ {
DataType.UPGRADE_BladesOfTheGodhead, DataType.UPGRADE_BladesOfTheGodhead,
@ -1619,15 +1611,15 @@ public class DATA
DataType.UPGRADE_Offering, DataType.UPGRADE_Offering,
new EntityModel(DataType.UPGRADE_Offering, EntityType.Tech) new EntityModel(DataType.UPGRADE_Offering, EntityType.Tech)
.AddPart(new EntityInfoModel .AddPart(new EntityInfoModel
{ {
Name = "Offering", Name = "Offering",
Descriptive = DescriptiveType.Upgrade, Descriptive = DescriptiveType.Upgrade,
Description = "Unlocks Offering" }) Description = "Unlocks Offering"
})
.AddPart(new EntityHotkeyModel { Hotkey = "W", HotkeyGroup = "TAB" }) .AddPart(new EntityHotkeyModel { Hotkey = "W", HotkeyGroup = "TAB" })
.AddPart(new EntityFactionModel { Faction = FactionType.Aru }) .AddPart(new EntityFactionModel { Faction = FactionType.Aru })
.AddPart(new EntityVanguardReplacedModel .AddPart(new EntityVanguardReplacedModel
{ ImmortalId = DataType.IMMORTAL_Xol, ReplacedById = DataType.UPGRADE_Stalk }) { ImmortalId = DataType.IMMORTAL_Xol, ReplacedById = DataType.UPGRADE_Stalk })
.AddPart(new EntityRequirementModel .AddPart(new EntityRequirementModel
{ {
Id = DataType.BUILDING_AltarOfTheWorthy, Id = DataType.BUILDING_AltarOfTheWorthy,
@ -1649,7 +1641,6 @@ public class DATA
.AddPart(new EntityFactionModel { Faction = FactionType.Aru }) .AddPart(new EntityFactionModel { Faction = FactionType.Aru })
.AddPart(new EntityVanguardReplacedModel .AddPart(new EntityVanguardReplacedModel
{ ImmortalId = DataType.IMMORTAL_Xol, ReplacedById = DataType.UPGRADE_Ambush }) { ImmortalId = DataType.IMMORTAL_Xol, ReplacedById = DataType.UPGRADE_Ambush })
.AddPart(new EntityRequirementModel .AddPart(new EntityRequirementModel
{ {
Id = DataType.BUILDING_AmberWomb, Id = DataType.BUILDING_AmberWomb,
@ -1750,7 +1741,7 @@ public class DATA
}) })
.AddPart(new EntityProductionModel { Alloy = 50, Ether = 75, BuildTime = 29 }) .AddPart(new EntityProductionModel { Alloy = 50, Ether = 75, BuildTime = 29 })
}, },
{ {
DataType.UPGRADE_Stalk, DataType.UPGRADE_Stalk,
new EntityModel(DataType.UPGRADE_Stalk, EntityType.Tech) new EntityModel(DataType.UPGRADE_Stalk, EntityType.Tech)
@ -1770,9 +1761,8 @@ public class DATA
.AddPart(new EntityProductionModel { Alloy = 100, Ether = 80, BuildTime = 60 }) .AddPart(new EntityProductionModel { Alloy = 100, Ether = 80, BuildTime = 60 })
.AddPart(new EntityVanguardAddedModel .AddPart(new EntityVanguardAddedModel
{ ReplaceId = DataType.UPGRADE_Offering, ImmortalId = DataType.IMMORTAL_Xol }) { ReplaceId = DataType.UPGRADE_Offering, ImmortalId = DataType.IMMORTAL_Xol })
}, },
{ {
DataType.UPGRADE_Ambush, DataType.UPGRADE_Ambush,
new EntityModel(DataType.UPGRADE_Ambush, EntityType.Tech) new EntityModel(DataType.UPGRADE_Ambush, EntityType.Tech)
@ -1793,8 +1783,8 @@ public class DATA
.AddPart(new EntityVanguardAddedModel .AddPart(new EntityVanguardAddedModel
{ ReplaceId = DataType.UPGRADE_BloodMothersFevor, ImmortalId = DataType.IMMORTAL_Xol }) { ReplaceId = DataType.UPGRADE_BloodMothersFevor, ImmortalId = DataType.IMMORTAL_Xol })
}, },
{ {
DataType.UPGRADE_BloodPlague, DataType.UPGRADE_BloodPlague,
new EntityModel(DataType.UPGRADE_BloodPlague, EntityType.Tech) new EntityModel(DataType.UPGRADE_BloodPlague, EntityType.Tech)
@ -1854,14 +1844,14 @@ public class DATA
}) })
.AddPart(new EntityFactionModel { Faction = FactionType.Any }) .AddPart(new EntityFactionModel { Faction = FactionType.Any })
}, },
{ {
DataType.PASSIVE_HarvestAlloy, DataType.PASSIVE_HarvestAlloy,
new EntityModel(DataType.PASSIVE_HarvestAlloy, EntityType.Passive) new EntityModel(DataType.PASSIVE_HarvestAlloy, EntityType.Passive)
.AddPart(new EntityInfoModel .AddPart(new EntityInfoModel
{ {
Name = "Harvest Alloy", Descriptive = DescriptiveType.Passive, Name = "Harvest Alloy", Descriptive = DescriptiveType.Passive,
Description = "This unit can harvest alloy." Description = "This unit can harvest alloy."
}) })
.AddPart(new EntityFactionModel { Faction = FactionType.Any }) .AddPart(new EntityFactionModel { Faction = FactionType.Any })
}, },
@ -1880,7 +1870,7 @@ public class DATA
}) })
.AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityFactionModel { Faction = FactionType.QRath })
}, },
{ {
DataType.PASSIVE_GreavesOfAhqar, DataType.PASSIVE_GreavesOfAhqar,
new EntityModel(DataType.PASSIVE_GreavesOfAhqar, EntityType.Passive) new EntityModel(DataType.PASSIVE_GreavesOfAhqar, EntityType.Passive)
@ -1889,10 +1879,11 @@ public class DATA
Name = "Greaves Of Ahqar", Descriptive = DescriptiveType.Ability, Name = "Greaves Of Ahqar", Descriptive = DescriptiveType.Ability,
Description = @"+75 Sipari Speed" Description = @"+75 Sipari Speed"
}) })
.AddPart(new EntityRequirementModel(){ Id = DataType.UPGRADE_GreavesOfAhqar, Requirement = RequirementType.Research_Upgrade}) .AddPart(new EntityRequirementModel
{ Id = DataType.UPGRADE_GreavesOfAhqar, Requirement = RequirementType.Research_Upgrade })
.AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityFactionModel { Faction = FactionType.QRath })
}, },
{ {
DataType.PASSIVE_RelicOfTheWrathfulGaze, DataType.PASSIVE_RelicOfTheWrathfulGaze,
new EntityModel(DataType.PASSIVE_RelicOfTheWrathfulGaze, EntityType.Passive) new EntityModel(DataType.PASSIVE_RelicOfTheWrathfulGaze, EntityType.Passive)
@ -1901,7 +1892,10 @@ public class DATA
Name = "Relic Of The Wrathful Gaze", Descriptive = DescriptiveType.Ability, Name = "Relic Of The Wrathful Gaze", Descriptive = DescriptiveType.Ability,
Description = @"Increases Castigator range against air." Description = @"Increases Castigator range against air."
}) })
.AddPart(new EntityRequirementModel(){ Id = DataType.UPGRADE_RelicOfTheWrathfulGaze, Requirement = RequirementType.Research_Upgrade}) .AddPart(new EntityRequirementModel
{
Id = DataType.UPGRADE_RelicOfTheWrathfulGaze, Requirement = RequirementType.Research_Upgrade
})
.AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityFactionModel { Faction = FactionType.QRath })
}, },
{ {
@ -1912,10 +1906,11 @@ public class DATA
Name = "Wings of the Ken'Latir", Descriptive = DescriptiveType.Passive, Name = "Wings of the Ken'Latir", Descriptive = DescriptiveType.Passive,
Description = @"Increases the Warden's speed and shields significantly." Description = @"Increases the Warden's speed and shields significantly."
}) })
.AddPart(new EntityRequirementModel(){ Id = DataType.UPGRADE_WingsOfTheKenLatir, Requirement = RequirementType.Research_Upgrade}) .AddPart(new EntityRequirementModel
{ Id = DataType.UPGRADE_WingsOfTheKenLatir, Requirement = RequirementType.Research_Upgrade })
.AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityFactionModel { Faction = FactionType.QRath })
}, },
{ {
DataType.PASSIVE_ExecutionRites, DataType.PASSIVE_ExecutionRites,
new EntityModel(DataType.PASSIVE_ExecutionRites, EntityType.Passive) new EntityModel(DataType.PASSIVE_ExecutionRites, EntityType.Passive)
@ -1926,7 +1921,7 @@ public class DATA
}) })
.AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityFactionModel { Faction = FactionType.QRath })
}, },
{ {
DataType.PASSIVE_IconOfKhastEem, DataType.PASSIVE_IconOfKhastEem,
new EntityModel(DataType.PASSIVE_IconOfKhastEem, EntityType.Passive) new EntityModel(DataType.PASSIVE_IconOfKhastEem, EntityType.Passive)
@ -1935,10 +1930,11 @@ public class DATA
Name = "Icon Of Khast'Eem", Descriptive = DescriptiveType.Passive, Name = "Icon Of Khast'Eem", Descriptive = DescriptiveType.Passive,
Description = @"Grants the Zentari shields and flat armor reduction." Description = @"Grants the Zentari shields and flat armor reduction."
}) })
.AddPart(new EntityRequirementModel(){ Id = DataType.UPGRADE_IconOfKhastEem, Requirement = RequirementType.Research_Upgrade}) .AddPart(new EntityRequirementModel
{ Id = DataType.UPGRADE_IconOfKhastEem, Requirement = RequirementType.Research_Upgrade })
.AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityFactionModel { Faction = FactionType.QRath })
}, },
{ {
DataType.PASSIVE_FaithCastBlades, DataType.PASSIVE_FaithCastBlades,
new EntityModel(DataType.PASSIVE_FaithCastBlades, EntityType.Passive) new EntityModel(DataType.PASSIVE_FaithCastBlades, EntityType.Passive)
@ -1947,11 +1943,11 @@ public class DATA
Name = "Faith Cast Blades", Descriptive = DescriptiveType.Passive, Name = "Faith Cast Blades", Descriptive = DescriptiveType.Passive,
Description = @"Increases the range of the Zentari's ranged weapon." Description = @"Increases the range of the Zentari's ranged weapon."
}) })
.AddPart(new EntityRequirementModel(){ Id = DataType.UPGRADE_FaithCastBlades, Requirement = RequirementType.Research_Upgrade}) .AddPart(new EntityRequirementModel
{ Id = DataType.UPGRADE_FaithCastBlades, Requirement = RequirementType.Research_Upgrade })
.AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityFactionModel { Faction = FactionType.QRath })
}, },
{ {
DataType.PASSIVE_ThroneMovingShot, DataType.PASSIVE_ThroneMovingShot,
new EntityModel(DataType.PASSIVE_ThroneMovingShot, EntityType.Passive) new EntityModel(DataType.PASSIVE_ThroneMovingShot, EntityType.Passive)
@ -1962,7 +1958,7 @@ public class DATA
}) })
.AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityFactionModel { Faction = FactionType.QRath })
}, },
{ {
DataType.PASSIVE_SiroccoScript, DataType.PASSIVE_SiroccoScript,
new EntityModel(DataType.PASSIVE_SiroccoScript, EntityType.Passive) new EntityModel(DataType.PASSIVE_SiroccoScript, EntityType.Passive)
@ -1971,10 +1967,10 @@ public class DATA
Name = "Sirocco Script Rites", Descriptive = DescriptiveType.Passive, Name = "Sirocco Script Rites", Descriptive = DescriptiveType.Passive,
Description = @"Increases the derish's movement speed" Description = @"Increases the derish's movement speed"
}) })
.AddPart(new EntityRequirementModel(){ Id = DataType.UPGRADE_SiroccoScript}) .AddPart(new EntityRequirementModel { Id = DataType.UPGRADE_SiroccoScript })
.AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityFactionModel { Faction = FactionType.QRath })
}, },
{ {
DataType.PASSIVE_HallowingRites, DataType.PASSIVE_HallowingRites,
new EntityModel(DataType.PASSIVE_HallowingRites, EntityType.Passive) new EntityModel(DataType.PASSIVE_HallowingRites, EntityType.Passive)
@ -1985,7 +1981,7 @@ public class DATA
}) })
.AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityFactionModel { Faction = FactionType.QRath })
}, },
{ {
DataType.PASSIVE_HallowedRuin, DataType.PASSIVE_HallowedRuin,
new EntityModel(DataType.PASSIVE_HallowedRuin, EntityType.Passive) new EntityModel(DataType.PASSIVE_HallowedRuin, EntityType.Passive)
@ -1996,18 +1992,19 @@ public class DATA
}) })
.AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityFactionModel { Faction = FactionType.QRath })
}, },
{ {
DataType.PASSIVE_RegentsWrath, DataType.PASSIVE_RegentsWrath,
new EntityModel(DataType.PASSIVE_RegentsWrath, EntityType.Passive) new EntityModel(DataType.PASSIVE_RegentsWrath, EntityType.Passive)
.AddPart(new EntityInfoModel .AddPart(new EntityInfoModel
{ {
Name = "Regent's Wrath", Descriptive = DescriptiveType.Passive, Name = "Regent's Wrath", Descriptive = DescriptiveType.Passive,
Description = @"Scepters gain energy when stabilized. They lose energy when moving. Energy is spent to have splash on attack." Description =
@"Scepters gain energy when stabilized. They lose energy when moving. Energy is spent to have splash on attack."
}) })
.AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityFactionModel { Faction = FactionType.QRath })
}, },
{ {
DataType.PASSIVE_PsalmOfFire, DataType.PASSIVE_PsalmOfFire,
new EntityModel(DataType.PASSIVE_PsalmOfFire, EntityType.Passive) new EntityModel(DataType.PASSIVE_PsalmOfFire, EntityType.Passive)
@ -2018,7 +2015,7 @@ public class DATA
}) })
.AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityFactionModel { Faction = FactionType.QRath })
}, },
{ {
DataType.PASSIVE_Zeal, DataType.PASSIVE_Zeal,
new EntityModel(DataType.PASSIVE_Zeal, EntityType.Passive) new EntityModel(DataType.PASSIVE_Zeal, EntityType.Passive)
@ -2029,7 +2026,7 @@ public class DATA
}) })
.AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityFactionModel { Faction = FactionType.QRath })
}, },
{ {
DataType.PASSIVE_HallowedGround, DataType.PASSIVE_HallowedGround,
new EntityModel(DataType.PASSIVE_HallowedGround, EntityType.Passive) new EntityModel(DataType.PASSIVE_HallowedGround, EntityType.Passive)
@ -2040,7 +2037,7 @@ public class DATA
}) })
.AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityFactionModel { Faction = FactionType.QRath })
}, },
{ {
DataType.PASSIVE_CastFromLife, DataType.PASSIVE_CastFromLife,
new EntityModel(DataType.PASSIVE_HallowedGround, EntityType.Passive) new EntityModel(DataType.PASSIVE_HallowedGround, EntityType.Passive)
@ -2052,7 +2049,7 @@ public class DATA
}) })
.AddPart(new EntityFactionModel { Faction = FactionType.Aru }) .AddPart(new EntityFactionModel { Faction = FactionType.Aru })
}, },
{ {
DataType.PASSIVE_WraithBowRange, DataType.PASSIVE_WraithBowRange,
new EntityModel(DataType.PASSIVE_WraithBowRange, EntityType.Passive) new EntityModel(DataType.PASSIVE_WraithBowRange, EntityType.Passive)
@ -2061,44 +2058,46 @@ public class DATA
Name = "Wraith Bow Range", Descriptive = DescriptiveType.Ability, Name = "Wraith Bow Range", Descriptive = DescriptiveType.Ability,
Description = @"Increases Wraith Bow range against air." Description = @"Increases Wraith Bow range against air."
}) })
.AddPart(new EntityRequirementModel(){ Id = DataType.UPGRADE_WraithBowRange, Requirement = RequirementType.Research_Upgrade}) .AddPart(new EntityRequirementModel
{ Id = DataType.UPGRADE_WraithBowRange, Requirement = RequirementType.Research_Upgrade })
.AddPart(new EntityFactionModel { Faction = FactionType.Aru }) .AddPart(new EntityFactionModel { Faction = FactionType.Aru })
}, },
{ {
DataType.PASSIVE_Rootway, DataType.PASSIVE_Rootway,
new EntityModel(DataType.PASSIVE_Rootway, EntityType.Passive) new EntityModel(DataType.PASSIVE_Rootway, EntityType.Passive)
.AddPart(new EntityInfoModel .AddPart(new EntityInfoModel
{ {
Name = "Rootway", Descriptive = DescriptiveType.Passive, Name = "Rootway", Descriptive = DescriptiveType.Passive,
Description = @"Building generates Rootway.", Description = @"Building generates Rootway."
}) })
.AddPart(new EntityFactionModel { Faction = FactionType.Aru }) .AddPart(new EntityFactionModel { Faction = FactionType.Aru })
}, },
{ {
DataType.PASSIVE_BehemothCapacity, DataType.PASSIVE_BehemothCapacity,
new EntityModel(DataType.PASSIVE_BehemothCapacity, EntityType.Passive) new EntityModel(DataType.PASSIVE_BehemothCapacity, EntityType.Passive)
.AddPart(new EntityInfoModel .AddPart(new EntityInfoModel
{ {
Name = "Quitl Storage", Descriptive = DescriptiveType.Passive, Name = "Quitl Storage", Descriptive = DescriptiveType.Passive,
Description = @"Unit stores quitl for attacks.", Description = @"Unit stores quitl for attacks."
}) })
.AddPart(new EntityFactionModel { Faction = FactionType.Aru }) .AddPart(new EntityFactionModel { Faction = FactionType.Aru })
}, },
{ {
DataType.PASSIVE_QuitlStorage2, DataType.PASSIVE_QuitlStorage2,
new EntityModel(DataType.PASSIVE_QuitlStorage2, EntityType.Passive) new EntityModel(DataType.PASSIVE_QuitlStorage2, EntityType.Passive)
.AddPart(new EntityInfoModel .AddPart(new EntityInfoModel
{ {
Name = "Quitl Storage", Descriptive = DescriptiveType.Passive, Name = "Quitl Storage", Descriptive = DescriptiveType.Passive,
Description = @"Unit stores more quitl for attacks.", Description = @"Unit stores more quitl for attacks."
}) })
.AddPart(new EntityFactionModel { Faction = FactionType.Aru }) .AddPart(new EntityFactionModel { Faction = FactionType.Aru })
.AddPart(new EntityRequirementModel { Id = DataType.UPGRADE_BehemothCapacity, Requirement = RequirementType.Research_Upgrade} ) .AddPart(new EntityRequirementModel
{ Id = DataType.UPGRADE_BehemothCapacity, Requirement = RequirementType.Research_Upgrade })
}, },
{ {
DataType.PASSIVE_ExternalDigestion, DataType.PASSIVE_ExternalDigestion,
new EntityModel(DataType.PASSIVE_ExternalDigestion, EntityType.Passive) new EntityModel(DataType.PASSIVE_ExternalDigestion, EntityType.Passive)
@ -2109,56 +2108,56 @@ public class DATA
}) })
.AddPart(new EntityFactionModel { Faction = FactionType.Aru }) .AddPart(new EntityFactionModel { Faction = FactionType.Aru })
}, },
{ {
DataType.PASSIVE_Temporary, DataType.PASSIVE_Temporary,
new EntityModel(DataType.PASSIVE_Temporary, EntityType.Passive) new EntityModel(DataType.PASSIVE_Temporary, EntityType.Passive)
.AddPart(new EntityInfoModel .AddPart(new EntityInfoModel
{ {
Name = "Temporary", Descriptive = DescriptiveType.Passive, Name = "Temporary", Descriptive = DescriptiveType.Passive,
Description = @"This unit has a limited duration before it dies.", Description = @"This unit has a limited duration before it dies."
}) })
.AddPart(new EntityFactionModel { Faction = FactionType.Aru }) .AddPart(new EntityFactionModel { Faction = FactionType.Aru })
}, },
{ {
DataType.PASSIVE_Stalk, DataType.PASSIVE_Stalk,
new EntityModel(DataType.PASSIVE_Stalk, EntityType.Passive) new EntityModel(DataType.PASSIVE_Stalk, EntityType.Passive)
.AddPart(new EntityInfoModel .AddPart(new EntityInfoModel
{ {
Name = "Stalk", Descriptive = DescriptiveType.Passive, Name = "Stalk", Descriptive = DescriptiveType.Passive,
Description = @"After remaining stationary for several seconds, gain Hidden 3 and a movement speed boost.", Description =
@"After remaining stationary for several seconds, gain Hidden 3 and a movement speed boost.",
Notes = "Lose hidden on attacking" Notes = "Lose hidden on attacking"
}) })
.AddPart(new EntityFactionModel { Faction = FactionType.Aru }) .AddPart(new EntityFactionModel { Faction = FactionType.Aru })
.AddPart(new EntityRequirementModel{Id=DataType.UPGRADE_Stalk}) .AddPart(new EntityRequirementModel { Id = DataType.UPGRADE_Stalk })
}, },
{ {
DataType.PASSIVE_Ambush, DataType.PASSIVE_Ambush,
new EntityModel(DataType.PASSIVE_Stalk, EntityType.Passive) new EntityModel(DataType.PASSIVE_Stalk, EntityType.Passive)
.AddPart(new EntityInfoModel .AddPart(new EntityInfoModel
{ {
Name = "Ambush", Descriptive = DescriptiveType.Passive, Name = "Ambush", Descriptive = DescriptiveType.Passive,
Description = @"This unit deals double damage when attacking from hidden.", Description = @"This unit deals double damage when attacking from hidden."
}) })
.AddPart(new EntityFactionModel { Faction = FactionType.Aru }) .AddPart(new EntityFactionModel { Faction = FactionType.Aru })
.AddPart(new EntityRequirementModel(){Id=DataType.UPGRADE_Ambush}) .AddPart(new EntityRequirementModel { Id = DataType.UPGRADE_Ambush })
}, },
{ {
DataType.PASSIVE_HiddenX, DataType.PASSIVE_HiddenX,
new EntityModel(DataType.PASSIVE_HiddenX, EntityType.Passive) new EntityModel(DataType.PASSIVE_HiddenX, EntityType.Passive)
.AddPart(new EntityInfoModel .AddPart(new EntityInfoModel
{ {
Name = "Hidden X", Descriptive = DescriptiveType.Passive, Name = "Hidden X", Descriptive = DescriptiveType.Passive,
Description = @"This unit cannot be seen unless enemies units are within X.", Description = @"This unit cannot be seen unless enemies units are within X."
}) })
.AddPart(new EntityFactionModel { Faction = FactionType.Aru }) .AddPart(new EntityFactionModel { Faction = FactionType.Aru })
}, },
{ {
DataType.PASSIVE_FallenHarvest, DataType.PASSIVE_FallenHarvest,
new EntityModel(DataType.PASSIVE_FallenHarvest, EntityType.Passive) new EntityModel(DataType.PASSIVE_FallenHarvest, EntityType.Passive)
@ -2169,7 +2168,7 @@ public class DATA
}) })
.AddPart(new EntityFactionModel { Faction = FactionType.Aru }) .AddPart(new EntityFactionModel { Faction = FactionType.Aru })
}, },
{ {
DataType.PASSIVE_RestoreLifeblood, DataType.PASSIVE_RestoreLifeblood,
new EntityModel(DataType.PASSIVE_RestoreLifeblood, EntityType.Passive) new EntityModel(DataType.PASSIVE_RestoreLifeblood, EntityType.Passive)
@ -2181,7 +2180,7 @@ public class DATA
.AddPart(new EntityFactionModel { Faction = FactionType.Aru }) .AddPart(new EntityFactionModel { Faction = FactionType.Aru })
}, },
{ {
DataType.PASSIVE_Transfusion, DataType.PASSIVE_Transfusion,
new EntityModel(DataType.PASSIVE_Transfusion, EntityType.Passive) new EntityModel(DataType.PASSIVE_Transfusion, EntityType.Passive)
@ -2192,10 +2191,8 @@ public class DATA
}) })
.AddPart(new EntityFactionModel { Faction = FactionType.Aru }) .AddPart(new EntityFactionModel { Faction = FactionType.Aru })
}, },
{ {
DataType.PASSIVE_FortifiedIcons, DataType.PASSIVE_FortifiedIcons,
new EntityModel(DataType.PASSIVE_FortifiedIcons, EntityType.Passive) new EntityModel(DataType.PASSIVE_FortifiedIcons, EntityType.Passive)
@ -2205,7 +2202,8 @@ public class DATA
Description = @"Increases Sipari shields and increases the bonus while in Hallowed Ground", Description = @"Increases Sipari shields and increases the bonus while in Hallowed Ground",
Notes = "+20 Shields, and +20 Shields on Hallowed Ground." Notes = "+20 Shields, and +20 Shields on Hallowed Ground."
}) })
.AddPart(new EntityRequirementModel(){ Id = DataType.UPGRADE_FortifiedIcons, Requirement = RequirementType.Research_Upgrade}) .AddPart(new EntityRequirementModel
{ Id = DataType.UPGRADE_FortifiedIcons, Requirement = RequirementType.Research_Upgrade })
.AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityFactionModel { Faction = FactionType.QRath })
}, },
{ {
@ -2265,7 +2263,8 @@ public class DATA
Description = Description =
@"Xacal builds up charges for double damage overtime. These charges can be spent on attacking." @"Xacal builds up charges for double damage overtime. These charges can be spent on attacking."
}) })
.AddPart(new EntityRequirementModel(){ Id = DataType.UPGRADE_XacalDamage, Requirement = RequirementType.Research_Upgrade}) .AddPart(new EntityRequirementModel
{ Id = DataType.UPGRADE_XacalDamage, Requirement = RequirementType.Research_Upgrade })
.AddPart(new EntityFactionModel { Faction = FactionType.Aru }) .AddPart(new EntityFactionModel { Faction = FactionType.Aru })
}, },
{ {
@ -2362,19 +2361,21 @@ public class DATA
.AddPart(new EntityInfoModel .AddPart(new EntityInfoModel
{ {
Name = "Radiant Ward", Descriptive = DescriptiveType.Ability, Name = "Radiant Ward", Descriptive = DescriptiveType.Ability,
Description = @"Spawns a mine that reveals enemy units, slows them, and makes them take increased damage for a duration.", Description =
@"Spawns a mine that reveals enemy units, slows them, and makes them take increased damage for a duration."
}) })
.AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityFactionModel { Faction = FactionType.QRath })
.AddPart(new EntityProductionModel { DefensiveLayer = 30, Cooldown = 40} ) .AddPart(new EntityProductionModel { DefensiveLayer = 30, Cooldown = 40 })
.AddPart(new EntityRequirementModel { Id = DataType.UPGRADE_RadiantWard }) .AddPart(new EntityRequirementModel { Id = DataType.UPGRADE_RadiantWard })
.AddPart(new EntityVitalityModel {Health = 30, DefenseLayer = 30, Lasts = 30, Armor = ArmorType.Light, IsStructure = true}) .AddPart(new EntityVitalityModel
{ Health = 30, DefenseLayer = 30, Lasts = 30, Armor = ArmorType.Light, IsStructure = true })
.AddPart(new EntityRequirementModel .AddPart(new EntityRequirementModel
{ {
Id = DataType.BUILDING_HouseOfFadingSaints, Id = DataType.BUILDING_HouseOfFadingSaints,
Requirement = RequirementType.Production_Building Requirement = RequirementType.Production_Building
}) })
}, },
{ {
DataType.ABILITY_Maledictions, DataType.ABILITY_Maledictions,
new EntityModel(DataType.ABILITY_Maledictions, EntityType.Ability) new EntityModel(DataType.ABILITY_Maledictions, EntityType.Ability)
@ -2513,8 +2514,7 @@ public class DATA
}) })
.AddPart(new EntityHotkeyModel { Hotkey = "E", HotkeyGroup = "D" }) .AddPart(new EntityHotkeyModel { Hotkey = "E", HotkeyGroup = "D" })
.AddPart(new EntityFactionModel { Faction = FactionType.Aru }) .AddPart(new EntityFactionModel { Faction = FactionType.Aru })
.AddPart(new EntityRequirementModel(){ Id= DataType.UPGRADE_Offering}) .AddPart(new EntityRequirementModel { Id = DataType.UPGRADE_Offering })
}, },
{ {
DataType.ABILITY_DiveBomb, DataType.ABILITY_DiveBomb,
@ -2668,12 +2668,13 @@ public class DATA
.AddPart(new EntityFactionModel { Faction = FactionType.Aru }) .AddPart(new EntityFactionModel { Faction = FactionType.Aru })
.AddPart(new EntityProductionModel { Alloy = 100, BuildTime = 25 }) .AddPart(new EntityProductionModel { Alloy = 100, BuildTime = 25 })
.AddPart(new EntitySupplyModel { Takes = 6 }) .AddPart(new EntitySupplyModel { Takes = 6 })
.AddPart(new EntityRequirementModel { Id = DataType.UNIT_RedSeer, Requirement = RequirementType.Morph }) .AddPart(new EntityRequirementModel
{ Id = DataType.UNIT_RedSeer, Requirement = RequirementType.Morph })
.AddPart(new EntityVitalityModel { Health = 200, DefenseLayer = 60, Armor = ArmorType.Heavy }) .AddPart(new EntityVitalityModel { Health = 200, DefenseLayer = 60, Armor = ArmorType.Heavy })
.AddPart(new EntityMovementModel { Speed = 210, Movement = MovementType.Ground }) .AddPart(new EntityMovementModel { Speed = 210, Movement = MovementType.Ground })
.AddPart(new EntityWeaponModel .AddPart(new EntityWeaponModel
{ Damage = 125, Range = 1500, AttacksPerSecond = 0.175f, Targets = TargetType.Ground }) { Damage = 125, Range = 1500, AttacksPerSecond = 0.175f, Targets = TargetType.Ground })
.AddPart(new EntityIdPassiveModel(){Id = DataType.PASSIVE_HiddenX}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_HiddenX })
}, },
// Pyre Spells // Pyre Spells
// Q'Rath // Q'Rath
@ -2696,7 +2697,7 @@ public class DATA
MediumDamage = 25, HeavyDamage = 30 MediumDamage = 25, HeavyDamage = 30
}) })
.AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_Respite }) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_Respite })
.AddPart(new EntityIdPassiveModel(){Id = DataType.PASSIVE_HallowedGround}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_HallowedGround })
}, },
{ {
DataType.ISPELL_PillarOfHeaven, DataType.ISPELL_PillarOfHeaven,
@ -2711,7 +2712,8 @@ public class DATA
.AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityFactionModel { Faction = FactionType.QRath })
.AddPart(new EntityVanguardAddedModel { ImmortalId = DataType.IMMORTAL_Orzum }) .AddPart(new EntityVanguardAddedModel { ImmortalId = DataType.IMMORTAL_Orzum })
.AddPart(new EntityProductionModel { Pyre = 100, Cooldown = 15 }) .AddPart(new EntityProductionModel { Pyre = 100, Cooldown = 15 })
.AddPart(new EntityVitalityModel { Health = 300, DefenseLayer = 200, Armor = ArmorType.Heavy, IsStructure = true}) .AddPart(new EntityVitalityModel
{ Health = 300, DefenseLayer = 200, Armor = ArmorType.Heavy, IsStructure = true })
.AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_Zeal }) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_Zeal })
}, },
{ {
@ -2787,7 +2789,7 @@ public class DATA
.AddPart(new EntityWeaponModel .AddPart(new EntityWeaponModel
{ Damage = 15, Range = 800, AttacksPerSecond = 1.887f, Targets = TargetType.All }) { Damage = 15, Range = 800, AttacksPerSecond = 1.887f, Targets = TargetType.All })
.AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_Respite }) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_Respite })
.AddPart(new EntityIdPassiveModel(){Id = DataType.PASSIVE_Rootway}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_Rootway })
}, },
{ {
DataType.ISPELL_ConstructBloodWell, DataType.ISPELL_ConstructBloodWell,
@ -2801,10 +2803,11 @@ public class DATA
.AddPart(new EntityHotkeyModel { Hotkey = "F", HotkeyGroup = "1" }) .AddPart(new EntityHotkeyModel { Hotkey = "F", HotkeyGroup = "1" })
.AddPart(new EntityFactionModel { Faction = FactionType.Aru }) .AddPart(new EntityFactionModel { Faction = FactionType.Aru })
.AddPart(new EntityProductionModel { Pyre = 50, Cooldown = 21 }) .AddPart(new EntityProductionModel { Pyre = 50, Cooldown = 21 })
.AddPart(new EntityVitalityModel {Health = 400, Energy = 100, DefenseLayer = 50, Armor = ArmorType.Heavy, IsStructure = true}) .AddPart(new EntityVitalityModel
.AddPart(new EntityIdPassiveModel {Id = DataType.PASSIVE_RestoreLifeblood}) { Health = 400, Energy = 100, DefenseLayer = 50, Armor = ArmorType.Heavy, IsStructure = true })
.AddPart(new EntityIdPassiveModel {Id = DataType.PASSIVE_Transfusion}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_RestoreLifeblood })
.AddPart(new EntityIdPassiveModel(){Id = DataType.PASSIVE_Rootway}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_Transfusion })
.AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_Rootway })
}, },
{ {
DataType.ISPELL_RedTithe, DataType.ISPELL_RedTithe,
@ -2835,19 +2838,26 @@ public class DATA
{ {
DataType.ISPELL_MarkPrey, DataType.ISPELL_MarkPrey,
new EntityModel(DataType.ISPELL_MarkPrey, EntityType.Pyre_Spell) new EntityModel(DataType.ISPELL_MarkPrey, EntityType.Pyre_Spell)
.AddPart(new EntityInfoModel { Name = "Mark Prey", .AddPart(new EntityInfoModel
Description = @"Enemy units in the target area are <b>Revealed</b> through fog of war. Units still in the area after a short delay are marked for 10 seconds to take bonus damage and provide Pyre when killed.", {
Name = "Mark Prey",
Description =
@"Enemy units in the target area are <b>Revealed</b> through fog of war. Units still in the area after a short delay are marked for 10 seconds to take bonus damage and provide Pyre when killed.",
Notes = "+3 pyre for kills" Notes = "+3 pyre for kills"
}) })
.AddPart(new EntityHotkeyModel { Hotkey = "E", HotkeyGroup = "1" }) .AddPart(new EntityHotkeyModel { Hotkey = "E", HotkeyGroup = "1" })
.AddPart(new EntityFactionModel { Faction = FactionType.Aru }) .AddPart(new EntityFactionModel { Faction = FactionType.Aru })
.AddPart(new EntityVanguardAddedModel { ImmortalId = DataType.IMMORTAL_Xol }) .AddPart(new EntityVanguardAddedModel { ImmortalId = DataType.IMMORTAL_Xol })
.AddPart(new EntityProductionModel { Cooldown = 15, Pyre = 25}) .AddPart(new EntityProductionModel { Cooldown = 15, Pyre = 25 })
}, },
{ {
DataType.ISPELL_TheGreatHunt, DataType.ISPELL_TheGreatHunt,
new EntityModel(DataType.ISPELL_TheGreatHunt, EntityType.Pyre_Spell) new EntityModel(DataType.ISPELL_TheGreatHunt, EntityType.Pyre_Spell)
.AddPart(new EntityInfoModel { Name = "The Great Hunt", Description = "Enemy unit and structures have their vision reduce to 3 for a short time."}) .AddPart(new EntityInfoModel
{
Name = "The Great Hunt",
Description = "Enemy unit and structures have their vision reduce to 3 for a short time."
})
.AddPart(new EntityHotkeyModel { Hotkey = "R", HotkeyGroup = "1" }) .AddPart(new EntityHotkeyModel { Hotkey = "R", HotkeyGroup = "1" })
.AddPart(new EntityFactionModel { Faction = FactionType.Aru }) .AddPart(new EntityFactionModel { Faction = FactionType.Aru })
.AddPart(new EntityVanguardAddedModel { ImmortalId = DataType.IMMORTAL_Xol }) .AddPart(new EntityVanguardAddedModel { ImmortalId = DataType.IMMORTAL_Xol })
@ -2875,7 +2885,7 @@ public class DATA
HarvestedPerInterval = 1, RequiresWorker = true, Resource = ResourceType.Alloy, Slots = 2, HarvestedPerInterval = 1, RequiresWorker = true, Resource = ResourceType.Alloy, Slots = 2,
TotalAmount = 3600 TotalAmount = 3600
}) })
.AddPart(new EntityIdPassiveModel(){Id = DataType.PASSIVE_HallowedGround}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_HallowedGround })
}, },
{ {
DataType.BUPGRADE_MiningLevel2_QRath, DataType.BUPGRADE_MiningLevel2_QRath,
@ -2954,7 +2964,7 @@ public class DATA
.AddPart(new EntityProductionModel { Alloy = 250, BuildTime = 38, RequiresWorker = true }) .AddPart(new EntityProductionModel { Alloy = 250, BuildTime = 38, RequiresWorker = true })
.AddPart(new EntityVitalityModel .AddPart(new EntityVitalityModel
{ Health = 500, DefenseLayer = 500, Armor = ArmorType.Heavy, IsStructure = true }) { Health = 500, DefenseLayer = 500, Armor = ArmorType.Heavy, IsStructure = true })
.AddPart(new EntityIdPassiveModel(){Id = DataType.PASSIVE_HallowedGround}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_HallowedGround })
}, },
{ {
DataType.DEFENSE_FireSinger, DataType.DEFENSE_FireSinger,
@ -3032,7 +3042,7 @@ public class DATA
}) })
.AddPart(new EntityVitalityModel .AddPart(new EntityVitalityModel
{ Health = 450, DefenseLayer = 450, Armor = ArmorType.Heavy, IsStructure = true }) { Health = 450, DefenseLayer = 450, Armor = ArmorType.Heavy, IsStructure = true })
.AddPart(new EntityIdPassiveModel(){Id = DataType.PASSIVE_HallowedGround}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_HallowedGround })
}, },
{ {
DataType.BUILDING_HouseOfFadingSaints, DataType.BUILDING_HouseOfFadingSaints,
@ -3074,7 +3084,7 @@ public class DATA
}) })
.AddPart(new EntityVitalityModel .AddPart(new EntityVitalityModel
{ Health = 600, DefenseLayer = 600, Armor = ArmorType.Heavy, IsStructure = true }) { Health = 600, DefenseLayer = 600, Armor = ArmorType.Heavy, IsStructure = true })
.AddPart(new EntityIdPassiveModel(){Id = DataType.PASSIVE_HallowedGround}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_HallowedGround })
}, },
{ {
DataType.BUILDING_EyeOfAros, DataType.BUILDING_EyeOfAros,
@ -3139,7 +3149,7 @@ public class DATA
HarvestedPerInterval = 1, RequiresWorker = true, Resource = ResourceType.Alloy, Slots = 2, HarvestedPerInterval = 1, RequiresWorker = true, Resource = ResourceType.Alloy, Slots = 2,
TotalAmount = 3600 TotalAmount = 3600
}) })
.AddPart(new EntityIdPassiveModel(){Id = DataType.PASSIVE_Rootway}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_Rootway })
}, },
{ {
DataType.BUPGRADE_GodHeart, DataType.BUPGRADE_GodHeart,
@ -3161,7 +3171,7 @@ public class DATA
}) })
.AddPart(new EntityProductionModel .AddPart(new EntityProductionModel
{ Alloy = 100, Ether = 75, BuildTime = 36, RequiresWorker = false }) { Alloy = 100, Ether = 75, BuildTime = 36, RequiresWorker = false })
.AddPart(new EntityIdPassiveModel(){Id = DataType.PASSIVE_Rootway}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_Rootway })
}, },
{ {
DataType.BUPGRADE_MiningLevel2_Aru, DataType.BUPGRADE_MiningLevel2_Aru,
@ -3240,7 +3250,7 @@ public class DATA
.AddPart(new EntityProductionModel { Alloy = 250, BuildTime = 36, RequiresWorker = true }) .AddPart(new EntityProductionModel { Alloy = 250, BuildTime = 36, RequiresWorker = true })
.AddPart(new EntityVitalityModel .AddPart(new EntityVitalityModel
{ Health = 900, DefenseLayer = 100, Armor = ArmorType.Heavy, IsStructure = true }) { Health = 900, DefenseLayer = 100, Armor = ArmorType.Heavy, IsStructure = true })
.AddPart(new EntityIdPassiveModel(){Id = DataType.PASSIVE_Rootway}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_Rootway })
}, },
{ {
DataType.BUILDING_Neurocyte, DataType.BUILDING_Neurocyte,
@ -3282,9 +3292,11 @@ public class DATA
.AddPart(new EntityInfoModel { Name = "Omnivore", Descriptive = DescriptiveType.Upgrade }) .AddPart(new EntityInfoModel { Name = "Omnivore", Descriptive = DescriptiveType.Upgrade })
.AddPart(new EntityHotkeyModel { Hotkey = "Q", HotkeyGroup = "SHIFT" }) .AddPart(new EntityHotkeyModel { Hotkey = "Q", HotkeyGroup = "SHIFT" })
.AddPart(new EntityFactionModel { Faction = FactionType.Aru }) .AddPart(new EntityFactionModel { Faction = FactionType.Aru })
.AddPart(new EntityRequirementModel { .AddPart(new EntityRequirementModel
{
Id = DataType.DEFENSE_Aerovore, Id = DataType.DEFENSE_Aerovore,
Requirement = RequirementType.Morph }) Requirement = RequirementType.Morph
})
.AddPart(new EntityProductionModel { Alloy = 50, BuildTime = 18, RequiresWorker = false }) .AddPart(new EntityProductionModel { Alloy = 50, BuildTime = 18, RequiresWorker = false })
.AddPart(new EntityVitalityModel .AddPart(new EntityVitalityModel
{ Health = 400, DefenseLayer = 50, Armor = ArmorType.Heavy, IsStructure = true }) { Health = 400, DefenseLayer = 50, Armor = ArmorType.Heavy, IsStructure = true })
@ -3314,7 +3326,7 @@ public class DATA
}) })
.AddPart(new EntityVitalityModel .AddPart(new EntityVitalityModel
{ Health = 1000, DefenseLayer = 250, Armor = ArmorType.Heavy, IsStructure = true }) { Health = 1000, DefenseLayer = 250, Armor = ArmorType.Heavy, IsStructure = true })
.AddPart(new EntityIdPassiveModel(){Id = DataType.PASSIVE_Rootway}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_Rootway })
}, },
{ {
DataType.BUILDING_BoneCanopy, DataType.BUILDING_BoneCanopy,
@ -3336,7 +3348,7 @@ public class DATA
}) })
.AddPart(new EntityVitalityModel .AddPart(new EntityVitalityModel
{ Health = 1000, DefenseLayer = 300, Armor = ArmorType.Heavy, IsStructure = true }) { Health = 1000, DefenseLayer = 300, Armor = ArmorType.Heavy, IsStructure = true })
.AddPart(new EntityIdPassiveModel(){Id = DataType.PASSIVE_Rootway}) .AddPart(new EntityIdPassiveModel { Id = DataType.PASSIVE_Rootway })
}, },
{ {
DataType.BUILDING_RedVale, DataType.BUILDING_RedVale,

34
Model/Entity/Data/Ids_Entity.cs

@ -49,14 +49,14 @@ public static class DataType
public static string ISPELL_ConstructBloodWell = "07aee142-02dd-4804-878a-2d5c6881e8c8"; public static string ISPELL_ConstructBloodWell = "07aee142-02dd-4804-878a-2d5c6881e8c8";
public static string ISPELL_RedTithe = "57008163-5e3a-4b95-98f3-d00b54e18684"; public static string ISPELL_RedTithe = "57008163-5e3a-4b95-98f3-d00b54e18684";
public static string ISPELL_RainOfBlood = "792df385-c66a-4710-9f75-97731897a565"; public static string ISPELL_RainOfBlood = "792df385-c66a-4710-9f75-97731897a565";
public static string IPASSIVE_HealingGround = "3ec17526-8dc5-4592-9c15-ef1d9b1ca2f6"; public static string IPASSIVE_HealingGround = "3ec17526-8dc5-4592-9c15-ef1d9b1ca2f6";
public static string IPASSIVE_Expansionist = "b6cd4335-2165-44c3-b3dc-4500c0111870"; public static string IPASSIVE_Expansionist = "b6cd4335-2165-44c3-b3dc-4500c0111870";
public static string IPASSIVE_MothersHunger = "382dc614-9228-4494-9a80-d1a72604a1ee"; public static string IPASSIVE_MothersHunger = "382dc614-9228-4494-9a80-d1a72604a1ee";
public static string IPASSIVE_StalkersSense = "a3d255aa-94f2-4aed-bb44-e9becb736fca"; public static string IPASSIVE_StalkersSense = "a3d255aa-94f2-4aed-bb44-e9becb736fca";
public static string ISPELL_MarkPrey = "8505419c-bb42-41fa-9c5b-fc0db280d7c0"; public static string ISPELL_MarkPrey = "8505419c-bb42-41fa-9c5b-fc0db280d7c0";
public static string ISPELL_TheGreatHunt = "efa14586-33f0-487f-b691-1ed3bcd5b0e6"; public static string ISPELL_TheGreatHunt = "efa14586-33f0-487f-b691-1ed3bcd5b0e6";
@ -92,7 +92,7 @@ public static class DataType
public static string DEFENSE_Aerovore = "b68307b7-4759-43a3-8679-d844ac3aa73f"; public static string DEFENSE_Aerovore = "b68307b7-4759-43a3-8679-d844ac3aa73f";
public static string UPGRADE_GreavesOfAhqar = "eac602b3-e3ae-4e36-aa14-28532e3485a7"; public static string UPGRADE_GreavesOfAhqar = "eac602b3-e3ae-4e36-aa14-28532e3485a7";
public static string UPGRADE_FortifiedIcons = "b16bdb3a-6c61-44da-89c5-5be37c7e9d66"; public static string UPGRADE_FortifiedIcons = "b16bdb3a-6c61-44da-89c5-5be37c7e9d66";
@ -114,18 +114,18 @@ public static class DataType
public static string UPGRADE_BehemothCapacity = "d0390dd2-d9a5-4b20-9d8b-f554f4c52143"; public static string UPGRADE_BehemothCapacity = "d0390dd2-d9a5-4b20-9d8b-f554f4c52143";
public static string UPGRADE_BloodPlague = "9c207e21-f595-49d0-967d-f30ca8cc3745"; public static string UPGRADE_BloodPlague = "9c207e21-f595-49d0-967d-f30ca8cc3745";
public static string UPGRADE_BirthingStorm = "0cb2f1a4-03b3-491b-9db3-d2d4590ede3a"; public static string UPGRADE_BirthingStorm = "0cb2f1a4-03b3-491b-9db3-d2d4590ede3a";
public static string UPGRADE_RadiantWard = "c8acc6d0-9f26-475a-aff4-4e2b2f9657f2"; public static string UPGRADE_RadiantWard = "c8acc6d0-9f26-475a-aff4-4e2b2f9657f2";
public static string UPGRADE_Stalk = "36fbc2c0-e9e3-4f54-a79a-981db908c25c"; public static string UPGRADE_Stalk = "36fbc2c0-e9e3-4f54-a79a-981db908c25c";
public static string UPGRADE_Ambush = "6cf83dc9-717f-4fa9-b417-a3371474a1da"; public static string UPGRADE_Ambush = "6cf83dc9-717f-4fa9-b417-a3371474a1da";
public static string PASSIVE_WraithBowRange = "196dd8a6-2044-44e1-aac4-fbaa40552699"; public static string PASSIVE_WraithBowRange = "196dd8a6-2044-44e1-aac4-fbaa40552699";
public static string PASSIVE_HiddenX = "7b819996-ffc0-4e07-9c11-c91c5f9d467b"; public static string PASSIVE_HiddenX = "7b819996-ffc0-4e07-9c11-c91c5f9d467b";
public static string PASSIVE_Respite = "607c39f4-a957-4a7a-8fc6-a239f9e570ec"; public static string PASSIVE_Respite = "607c39f4-a957-4a7a-8fc6-a239f9e570ec";
public static string PASSIVE_BastionPassives = "ea42b9cb-2456-4ed2-b490-fcfde12c6153"; public static string PASSIVE_BastionPassives = "ea42b9cb-2456-4ed2-b490-fcfde12c6153";
public static string PASSIVE_HallowedWarrior = "fea43ced-33f3-4531-af7d-740c1789fec1"; public static string PASSIVE_HallowedWarrior = "fea43ced-33f3-4531-af7d-740c1789fec1";
@ -136,18 +136,18 @@ public static class DataType
public static string PASSIVE_RelicOfTheWrathfulGaze = "ccebc0c9-cfd5-465a-8a5d-2495bd745a83"; public static string PASSIVE_RelicOfTheWrathfulGaze = "ccebc0c9-cfd5-465a-8a5d-2495bd745a83";
public static string PASSIVE_WingsOfTheKenLatir = "48909ff5-63db-4c99-b62f-d290e127e0bf"; public static string PASSIVE_WingsOfTheKenLatir = "48909ff5-63db-4c99-b62f-d290e127e0bf";
public static string PASSIVE_ExecutionRites = "8d017a17-320f-4c2a-b139-d2d83bf7ecd0"; public static string PASSIVE_ExecutionRites = "8d017a17-320f-4c2a-b139-d2d83bf7ecd0";
public static string PASSIVE_IconOfKhastEem = "7a211da6-4713-40f5-a171-1e3b6e02bf09"; public static string PASSIVE_IconOfKhastEem = "7a211da6-4713-40f5-a171-1e3b6e02bf09";
public static string PASSIVE_FaithCastBlades = "da4f8c9c-1b22-4b3f-94fc-11bc12cde02d"; public static string PASSIVE_FaithCastBlades = "da4f8c9c-1b22-4b3f-94fc-11bc12cde02d";
public static string PASSIVE_ThroneMovingShot = "699423ed-7410-4daf-8b07-9dc733a8bf55"; public static string PASSIVE_ThroneMovingShot = "699423ed-7410-4daf-8b07-9dc733a8bf55";
public static string PASSIVE_SiroccoScript = "11c21afa-ff88-4e42-9f97-a1d1595b115c"; public static string PASSIVE_SiroccoScript = "11c21afa-ff88-4e42-9f97-a1d1595b115c";
public static string PASSIVE_HallowingRites = "9c8ae47b-954e-4a17-8f35-f128c9114b61"; public static string PASSIVE_HallowingRites = "9c8ae47b-954e-4a17-8f35-f128c9114b61";
public static string PASSIVE_RegentsWrath = "f111f004-6548-4430-9d13-ef44ab108ae7"; public static string PASSIVE_RegentsWrath = "f111f004-6548-4430-9d13-ef44ab108ae7";
public static string PASSIVE_PsalmOfFire = "d28f6b7c-d319-4fb8-bdd4-92ede40a0751"; public static string PASSIVE_PsalmOfFire = "d28f6b7c-d319-4fb8-bdd4-92ede40a0751";
@ -164,11 +164,11 @@ public static class DataType
public static string PASSIVE_FallenHarvest = "d209e13f-d631-40d7-90e1-d9845b51b8d4"; public static string PASSIVE_FallenHarvest = "d209e13f-d631-40d7-90e1-d9845b51b8d4";
public static string PASSIVE_RestoreLifeblood = "fa213bc6-336c-4510-8a4b-db9ccfc54d62"; public static string PASSIVE_RestoreLifeblood = "fa213bc6-336c-4510-8a4b-db9ccfc54d62";
public static string PASSIVE_Transfusion = "e67a3d6d-f2bb-4622-9e4d-ea2a26af2f39"; public static string PASSIVE_Transfusion = "e67a3d6d-f2bb-4622-9e4d-ea2a26af2f39";
public static string PASSIVE_HallowedRuin = "402b555a-eb8a-4065-bd25-465d190b30c7"; public static string PASSIVE_HallowedRuin = "402b555a-eb8a-4065-bd25-465d190b30c7";
public static string PASSIVE_ExternalDigestion = "2563723b-4a75-4a17-a104-1f5ac3b79a06"; public static string PASSIVE_ExternalDigestion = "2563723b-4a75-4a17-a104-1f5ac3b79a06";
public static string PASSIVE_OssifyingSwarm = "b8897247-8393-416e-b246-409a6b3263c2"; public static string PASSIVE_OssifyingSwarm = "b8897247-8393-416e-b246-409a6b3263c2";
public static string PASSIVE_QuenchingScythes = "dbf07db4-e7b6-4f81-9f8e-e5391850eead"; public static string PASSIVE_QuenchingScythes = "dbf07db4-e7b6-4f81-9f8e-e5391850eead";
@ -188,7 +188,7 @@ public static class DataType
public static string ABILITY_RadiantWard = "db1fc8bd-d86a-4eda-b83c-16e8d0ce4f81"; public static string ABILITY_RadiantWard = "db1fc8bd-d86a-4eda-b83c-16e8d0ce4f81";
public static string ABILITY_Maledictions = "6cdc109c-157d-433a-b225-192e39c0b613"; public static string ABILITY_Maledictions = "6cdc109c-157d-433a-b225-192e39c0b613";
public static string ABILITY_BladesOfTheGodhead = "000154ac-faf5-483d-b0bd-e84335891a27"; public static string ABILITY_BladesOfTheGodhead = "000154ac-faf5-483d-b0bd-e84335891a27";
public static string ABILITY_Windstep = "a410b296-39f7-42e0-87c8-6cef11eb967c"; public static string ABILITY_Windstep = "a410b296-39f7-42e0-87c8-6cef11eb967c";
public static string ABILITY_Leap = "aa155b88-125a-4d25-b63f-77987ea6e519"; public static string ABILITY_Leap = "aa155b88-125a-4d25-b63f-77987ea6e519";

18
Model/Entity/EntityModel.cs

@ -13,14 +13,14 @@ namespace Model.Entity;
public class EntityModel public class EntityModel
{ {
public static readonly string GameVersion = "0.0.6.9121a"; public static readonly string GameVersion = "0.0.6.9121a";
private static Dictionary<string, EntityModel> _database= null!;
private static List<EntityModel> _entityModels= null!; private static Dictionary<string, EntityModel> _database = null!;
private static List<EntityModel> _entityModels = null!;
private static List<EntityModel> _entityModelsOnlyHotkey = null!; private static List<EntityModel> _entityModelsOnlyHotkey = null!;
private static Dictionary<string, List<EntityModel>>? _entityModelsByHotkey= null!; private static Dictionary<string, List<EntityModel>>? _entityModelsByHotkey;
public EntityModel(string data, string entity, bool isSpeculative = false) public EntityModel(string data, string entity, bool isSpeculative = false)
@ -139,8 +139,8 @@ public class EntityModel
if (string.IsNullOrEmpty(hotkey)) return null; if (string.IsNullOrEmpty(hotkey)) return null;
if (!GetEntitiesByHotkey().ContainsKey(hotkey)) return null; if (!GetEntitiesByHotkey().ContainsKey(hotkey)) return null;
var foundList = from entity in GetEntitiesByHotkey()[hotkey] var foundList = from entity in GetEntitiesByHotkey()[hotkey]
where entity.Hotkey()?.HotkeyGroup == hotkeyGroup where entity.Hotkey()?.HotkeyGroup == hotkeyGroup
&& entity.Hotkey()?.HoldSpace == holdSpace && entity.Hotkey()?.HoldSpace == holdSpace
@ -224,19 +224,19 @@ public class EntityModel
public EntityHotkeyModel Hotkey() public EntityHotkeyModel Hotkey()
{ {
return ((EntityHotkeyModel)EntityParts.Find(x => x.GetType() == typeof(EntityHotkeyModel))!); return (EntityHotkeyModel)EntityParts.Find(x => x.GetType() == typeof(EntityHotkeyModel))!;
} }
public EntityFactionModel Faction() public EntityFactionModel Faction()
{ {
return ((EntityFactionModel)EntityParts.Find(x => x.GetType() == typeof(EntityFactionModel))!); return (EntityFactionModel)EntityParts.Find(x => x.GetType() == typeof(EntityFactionModel))!;
} }
public EntityHarvestModel Harvest() public EntityHarvestModel Harvest()
{ {
return ((EntityHarvestModel)EntityParts.Find(x => x.GetType() == typeof(EntityHarvestModel))!); return (EntityHarvestModel)EntityParts.Find(x => x.GetType() == typeof(EntityHarvestModel))!;
} }

2
Model/Entity/Parts/EntityProductionModel.cs

@ -10,7 +10,7 @@ public class EntityProductionModel : IEntityPartInterface
public int Pyre { get; set; } = 0; public int Pyre { get; set; } = 0;
public int Energy { get; set; } = 0; public int Energy { get; set; } = 0;
public int DefensiveLayer { get; set; } = 0; public int DefensiveLayer { get; set; } = 0;
public int BuildTime { get; set; } = 0; public int BuildTime { get; set; } = 0;

2
Model/Entity/Parts/EntityVitalityModel.cs

@ -7,7 +7,7 @@ public class EntityVitalityModel : IEntityPartInterface
public string Type { get; set; } = "EntityVitalityModel"; public string Type { get; set; } = "EntityVitalityModel";
public int Health { get; set; } = 0; public int Health { get; set; } = 0;
public int DefenseLayer { get; set; } = 0; public int DefenseLayer { get; set; } = 0;
public int Lasts { get; set; } = 0; public int Lasts { get; set; } = 0;
public string Defense { get; set; } = DefenseType.None; public string Defense { get; set; } = DefenseType.None;
public string Armor { get; set; } = ArmorType.Light; public string Armor { get; set; } = ArmorType.Light;

2
Model/Entity/Types/DescriptiveType.cs

@ -26,7 +26,7 @@ public static class DescriptiveType
public static string Summon = "Summon"; public static string Summon = "Summon";
public static string Upgrade = "Upgrade"; public static string Upgrade = "Upgrade";
public static string Ability = "Ability"; public static string Ability = "Ability";
public static string Passive = "Passive"; public static string Passive = "Passive";
public static string Applies_Debuff = "Applies_Debuff"; public static string Applies_Debuff = "Applies_Debuff";
} }

4
Model/Git/GitChangeModel.cs

@ -1,6 +1,4 @@
using System; namespace Model.Git;
namespace Model.Git;
public class GitChangeModel public class GitChangeModel
{ {

12
Model/Model.csproj

@ -5,14 +5,14 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Remove="_PaperWork\**" /> <Compile Remove="_PaperWork\**"/>
<EmbeddedResource Remove="_PaperWork\**" /> <EmbeddedResource Remove="_PaperWork\**"/>
<None Remove="_PaperWork\**" /> <None Remove="_PaperWork\**"/>
<None Remove="Immortal\MemoryTester\" /> <None Remove="Immortal\MemoryTester\"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1"/>
<PackageReference Include="YamlDotNet" Version="11.2.1" /> <PackageReference Include="YamlDotNet" Version="11.2.1"/>
</ItemGroup> </ItemGroup>
</Project> </Project>

21
Model/Notes/NoteContentModel.cs

@ -1,35 +1,37 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using Model.Doc;
namespace Model.Notes; namespace Model.Notes;
public class NoteContentModel public class NoteContentModel
{ {
public int Id { get; set; } public int Id { get; set; }
public int? ParentId { get; set; } = null; public int? ParentId { get; set; } = null;
public int? NoteSectionModelId { get; set; } = null; public int? NoteSectionModelId { get; set; } = null;
public string Href { get; set; } public string Href { get; set; }
//public DateTime LastUpdated { get; set; } //public DateTime LastUpdated { get; set; }
public DateTime CreatedDate { get; set; } public DateTime CreatedDate { get; set; }
public DateTime UpdatedDate { get; set; } public DateTime UpdatedDate { get; set; }
public string Name { get; set; } public string Name { get; set; }
public string Description { get; set; } public string Description { get; set; }
public string Content { get; set; } public string Content { get; set; }
public string IsHidden { get; set; } = "False"; public string IsHidden { get; set; } = "False";
public string IsPreAlpha { get; set; } = "True"; public string IsPreAlpha { get; set; } = "True";
[NotMapped] public virtual ICollection<NoteContentModel> NoteContentModels { get; set; } = new List<NoteContentModel>(); [NotMapped]
public virtual ICollection<NoteContentModel> NoteContentModels { get; set; } = new List<NoteContentModel>();
[NotMapped] public virtual NoteContentModel Parent { get; set; } [NotMapped] public virtual NoteContentModel Parent { get; set; }
[NotMapped] public virtual int PageOrder { get; set; } [NotMapped] public virtual int PageOrder { get; set; }
private string GetLink() private string GetLink()
{ {
var link = Href; var link = Href;
@ -43,5 +45,4 @@ public class NoteContentModel
{ {
return $"notes/{GetLink()}"; return $"notes/{GetLink()}";
} }
} }

2
Model/Website/WebSectionModel.cs

@ -12,5 +12,5 @@ public class WebSectionModel
public int Order { get; set; } = 0; public int Order { get; set; } = 0;
public string IsPrivate { get; set; } = "True"; public string IsPrivate { get; set; } = "True";
[NotMapped] public List<WebPageModel> WebPageModels { get; set; } = new List<WebPageModel>(); [NotMapped] public List<WebPageModel> WebPageModels { get; set; } = new();
} }

17
Services/Development/DocumentationService.cs

@ -22,7 +22,6 @@ public class DocumentationService : IDocumentationService
public List<DocConnectionModel> DocConnectionModels { get; set; } = new(); public List<DocConnectionModel> DocConnectionModels { get; set; } = new();
public void Subscribe(Action? action) public void Subscribe(Action? action)
{ {
OnChange += action; OnChange += action;
@ -54,7 +53,7 @@ public class DocumentationService : IDocumentationService
DocSectionModels = DocSectionModels =
(await httpClient.GetFromJsonAsync<DocSectionModel[]>("generated/DocSectionModels.json") ?? (await httpClient.GetFromJsonAsync<DocSectionModel[]>("generated/DocSectionModels.json") ??
Array.Empty<DocSectionModel>()).ToList(); Array.Empty<DocSectionModel>()).ToList();
SortSql(); SortSql();
isLoaded = true; isLoaded = true;
@ -88,28 +87,20 @@ public class DocumentationService : IDocumentationService
} }
foreach (var content in DocContentModels) foreach (var content in DocContentModels)
{
if (content.DocSectionModelId != null) if (content.DocSectionModelId != null)
{
foreach (var section in DocSectionModels) foreach (var section in DocSectionModels)
{
if (section.Id == content.DocSectionModelId) if (section.Id == content.DocSectionModelId)
{
section.DocumentationModels.Add(content); section.DocumentationModels.Add(content);
}
}
}
}
ByPageOrder(); ByPageOrder();
} }
private void ByPageOrder() private void ByPageOrder()
{ {
DocContentModelsByPageOrder = new List<DocContentModel>(); DocContentModelsByPageOrder = new List<DocContentModel>();
int order = 1; var order = 1;
foreach (var documentation in DocContentModels) foreach (var documentation in DocContentModels)
{ {
if (documentation.Parent != null) continue; if (documentation.Parent != null) continue;

43
Services/Development/GitService.cs

@ -10,15 +10,17 @@ using Microsoft.EntityFrameworkCore;
namespace Services.Development; namespace Services.Development;
public class GitService : IGitService { public class GitService : IGitService
{
private readonly HttpClient httpClient; private readonly HttpClient httpClient;
private bool isLoaded; private bool isLoaded;
private event Action OnChange = default!; private event Action OnChange = default!;
public GitService(HttpClient httpClient) { public GitService(HttpClient httpClient)
{
this.httpClient = httpClient; this.httpClient = httpClient;
} }
@ -32,30 +34,32 @@ public class GitService : IGitService {
#endif #endif
public void Subscribe(Action action)
public void Subscribe(Action action) { {
OnChange += action; OnChange += action;
} }
public void Unsubscribe(Action action) { public void Unsubscribe(Action action)
{
OnChange -= action; OnChange -= action;
} }
public bool IsLoaded() { public bool IsLoaded()
{
return isLoaded; return isLoaded;
} }
#if NO_SQL #if NO_SQL
public async Task Load() { public async Task Load()
{
if (isLoaded) return;
if (isLoaded) { GitChangeModels = (await httpClient.GetFromJsonAsync<GitChangeModel[]>("generated/GitChangeModels.json") ??
return; Array.Empty<GitChangeModel>()).ToList();
} GitPatchModels = (await httpClient.GetFromJsonAsync<GitPatchModel[]>("generated/GitPatchModels.json") ??
Array.Empty<GitPatchModel>()).ToList();
GitChangeModels = (await httpClient.GetFromJsonAsync<GitChangeModel[]>("generated/GitChangeModels.json") ?? Array.Empty<GitChangeModel>()).ToList();
GitPatchModels = (await httpClient.GetFromJsonAsync<GitPatchModel[]>("generated/GitPatchModels.json") ?? Array.Empty<GitPatchModel>()).ToList();
isLoaded = true; isLoaded = true;
@ -64,7 +68,6 @@ public class GitService : IGitService {
} }
#else #else
public async Task Load(DatabaseContext database) { public async Task Load(DatabaseContext database) {
Database = database; Database = database;
@ -84,12 +87,14 @@ public class GitService : IGitService {
#endif #endif
public void Update() { public void Update()
{
NotifyDataChanged(); NotifyDataChanged();
} }
private void NotifyDataChanged() { private void NotifyDataChanged()
{
OnChange?.Invoke(); OnChange?.Invoke();
} }
} }

89
Services/Development/NoteService.cs

@ -10,57 +10,73 @@ using Microsoft.EntityFrameworkCore;
namespace Services.Development; namespace Services.Development;
public class NoteService : INoteService { public class NoteService : INoteService
{
private readonly HttpClient httpClient; private readonly HttpClient httpClient;
private bool isLoaded; private bool isLoaded;
private event Action OnChange = default!;
private void NotifyDataChanged() { public NoteService(HttpClient httpClient)
OnChange?.Invoke(); {
}
public NoteService(HttpClient httpClient) {
this.httpClient = httpClient; this.httpClient = httpClient;
} }
public List<NoteContentModel> NoteContentModelsByPageOrder { get; set; } = new();
public List<NoteContentModel> NoteContentModels { get; set; } = default!; public List<NoteContentModel> NoteContentModels { get; set; } = default!;
public List<NoteConnectionModel> NoteConnectionModels { get; set; } = null!; public List<NoteConnectionModel> NoteConnectionModels { get; set; } = null!;
public List<NoteSectionModel> NoteSectionModels { get; set; } = null!; public List<NoteSectionModel> NoteSectionModels { get; set; } = null!;
public List<NoteContentModel> NoteContentModelsByPageOrder { get; set; } = new();
public void Subscribe(Action action)
public void Subscribe(Action action) { {
OnChange += action; OnChange += action;
} }
public void Unsubscribe(Action action) { public void Unsubscribe(Action action)
{
OnChange -= action; OnChange -= action;
} }
public bool IsLoaded() { public bool IsLoaded()
{
return isLoaded; return isLoaded;
} }
public async Task Load() { public async Task Load()
if (isLoaded) { {
return; if (isLoaded) return;
}
NoteContentModels =
NoteContentModels = (await httpClient.GetFromJsonAsync<NoteContentModel[]>("generated/NoteContentModels.json") ?? Array.Empty<NoteContentModel>()).ToList(); (await httpClient.GetFromJsonAsync<NoteContentModel[]>("generated/NoteContentModels.json") ??
NoteConnectionModels = (await httpClient.GetFromJsonAsync<NoteConnectionModel[]>("generated/NoteConnectionModels.json") ?? Array.Empty<NoteConnectionModel>()).ToList(); Array.Empty<NoteContentModel>()).ToList();
NoteSectionModels = (await httpClient.GetFromJsonAsync<NoteSectionModel[]>("generated/NoteSectionModels.json") ?? Array.Empty<NoteSectionModel>()).ToList(); NoteConnectionModels =
(await httpClient.GetFromJsonAsync<NoteConnectionModel[]>("generated/NoteConnectionModels.json") ??
Array.Empty<NoteConnectionModel>()).ToList();
NoteSectionModels =
(await httpClient.GetFromJsonAsync<NoteSectionModel[]>("generated/NoteSectionModels.json") ??
Array.Empty<NoteSectionModel>()).ToList();
isLoaded = true; isLoaded = true;
SortSQL(); SortSQL();
NotifyDataChanged(); NotifyDataChanged();
} }
public void Update()
{
NotifyDataChanged();
}
private event Action OnChange = default!;
private void NotifyDataChanged()
{
OnChange?.Invoke();
}
private NoteContentModel? ContentById(int id) private NoteContentModel? ContentById(int id)
{ {
foreach (var data in NoteContentModels!) foreach (var data in NoteContentModels!)
@ -69,7 +85,7 @@ public class NoteService : INoteService {
return null; return null;
} }
private void SortSQL() private void SortSQL()
{ {
foreach (var connection in NoteConnectionModels) foreach (var connection in NoteConnectionModels)
@ -79,27 +95,19 @@ public class NoteService : INoteService {
} }
foreach (var content in NoteContentModels) foreach (var content in NoteContentModels)
{
if (content.NoteSectionModelId != null) if (content.NoteSectionModelId != null)
{
foreach (var section in NoteSectionModels) foreach (var section in NoteSectionModels)
{
if (section.Id == content.NoteSectionModelId) if (section.Id == content.NoteSectionModelId)
{
section.NoteContentModels.Add(content); section.NoteContentModels.Add(content);
}
}
}
}
ByPageOrder(); ByPageOrder();
} }
private void ByPageOrder() private void ByPageOrder()
{ {
NoteContentModelsByPageOrder = new List<NoteContentModel>(); NoteContentModelsByPageOrder = new List<NoteContentModel>();
int order = 1; var order = 1;
foreach (var note in NoteContentModels) foreach (var note in NoteContentModels)
{ {
if (note.Parent != null) continue; if (note.Parent != null) continue;
@ -121,10 +129,7 @@ public class NoteService : INoteService {
GetAllChildren(note); GetAllChildren(note);
} }
NoteContentModelsByPageOrder = NoteContentModelsByPageOrder.OrderBy(noteContent => noteContent.PageOrder).ToList(); NoteContentModelsByPageOrder =
} NoteContentModelsByPageOrder.OrderBy(noteContent => noteContent.PageOrder).ToList();
public void Update() {
NotifyDataChanged();
} }
} }

78
Services/IServices.cs

@ -1,20 +1,18 @@
 using Model.BuildOrders;
using Model.Doc; using Model.Doc;
using Model.BuildOrders;
using Model.Economy; using Model.Economy;
using Model.Entity; using Model.Entity;
using Model.Feedback;
using Model.Git;
using Model.MemoryTester; using Model.MemoryTester;
using Model.Notes; using Model.Notes;
using Model.Website; using Model.Website;
using Model.Website.Enums; using Model.Website.Enums;
using Model.Git;
using Model.Feedback;
using Model.Work.Tasks; using Model.Work.Tasks;
using Services.Immortal; using Services.Immortal;
namespace Services; namespace Services;
public interface IToastService public interface IToastService
{ {
public void Subscribe(Action action); public void Subscribe(Action action);
@ -27,15 +25,14 @@ public interface IToastService
void ClearAllToasts(); void ClearAllToasts();
} }
public interface IEntityDialogService public interface IEntityDialogService
{ {
public void Subscribe(Action action); public void Subscribe(Action action);
public void Unsubscribe(Action action); public void Unsubscribe(Action action);
public void AddDialog(string entityId); public void AddDialog(string entityId);
public void CloseDialog(); public void CloseDialog();
public void BackDialog(); public void BackDialog();
public string? GetEntityId(); public string? GetEntityId();
@ -44,22 +41,23 @@ public interface IEntityDialogService
public bool HasHistory(); public bool HasHistory();
} }
public interface IWebsiteService { public interface IWebsiteService
{
public List<WebPageModel> WebPageModels { get; set; } public List<WebPageModel> WebPageModels { get; set; }
public List<WebSectionModel> WebSectionModels { get; set; } public List<WebSectionModel> WebSectionModels { get; set; }
public void Subscribe(Action action); public void Subscribe(Action action);
public void Unsubscribe(Action action); public void Unsubscribe(Action action);
public void Update(); public void Update();
public Task Load(); public Task Load();
public bool IsLoaded(); public bool IsLoaded();
} }
public interface IAgileService { public interface IAgileService
{
#if NO_SQL #if NO_SQL
public List<AgileSprintModel>? AgileSprintModels { get; set; } public List<AgileSprintModel>? AgileSprintModels { get; set; }
public List<AgileTaskModel>? AgileTaskModels { get; set; } public List<AgileTaskModel>? AgileTaskModels { get; set; }
@ -71,12 +69,13 @@ public interface IAgileService {
public void Subscribe(Action? action); public void Subscribe(Action? action);
public void Unsubscribe(Action? action); public void Unsubscribe(Action? action);
public void Update(); public void Update();
public Task Load(); public Task Load();
public bool IsLoaded(); public bool IsLoaded();
} }
public interface INoteService { public interface INoteService
{
public List<NoteContentModel> NoteContentModels { get; set; } public List<NoteContentModel> NoteContentModels { get; set; }
public List<NoteConnectionModel> NoteConnectionModels { get; set; } public List<NoteConnectionModel> NoteConnectionModels { get; set; }
public List<NoteSectionModel> NoteSectionModels { get; set; } public List<NoteSectionModel> NoteSectionModels { get; set; }
@ -101,9 +100,8 @@ public interface IDocumentationService
public bool IsLoaded(); public bool IsLoaded();
} }
public interface IGitService
public interface IGitService { {
#if NO_SQL #if NO_SQL
public List<GitChangeModel> GitChangeModels { get; set; } public List<GitChangeModel> GitChangeModels { get; set; }
public List<GitPatchModel> GitPatchModels { get; set; } public List<GitPatchModel> GitPatchModels { get; set; }
@ -124,7 +122,8 @@ public interface IGitService {
public bool IsLoaded(); public bool IsLoaded();
} }
public interface INavigationService { public interface INavigationService
{
public void Subscribe(Action action); public void Subscribe(Action action);
public void Unsubscribe(Action action); public void Unsubscribe(Action action);
@ -143,7 +142,8 @@ public interface INavigationService {
public Type GetRenderType(); public Type GetRenderType();
} }
public interface IBuildComparisonService { public interface IBuildComparisonService
{
public void SetBuilds(BuildComparisonModel buildComparisonModel); public void SetBuilds(BuildComparisonModel buildComparisonModel);
public BuildComparisonModel Get(); public BuildComparisonModel Get();
public string BuildOrderAsYaml(); public string BuildOrderAsYaml();
@ -153,14 +153,16 @@ public interface IBuildComparisonService {
public void Unsubscribe(Action action); public void Unsubscribe(Action action);
} }
public interface ITimingService { public interface ITimingService
{
public int GetTiming(); public int GetTiming();
public void SetTiming(int timing); public void SetTiming(int timing);
public void Subscribe(Action? action); public void Subscribe(Action? action);
public void Unsubscribe(Action? action); public void Unsubscribe(Action? action);
} }
public interface IEconomyService { public interface IEconomyService
{
public List<EconomyModel> GetOverTime(); public List<EconomyModel> GetOverTime();
public EconomyModel GetEconomy(int atInterval); public EconomyModel GetEconomy(int atInterval);
public void Calculate(IBuildOrderService buildOrder, ITimingService timing, int fromInterval); public void Calculate(IBuildOrderService buildOrder, ITimingService timing, int fromInterval);
@ -168,7 +170,8 @@ public interface IEconomyService {
public void Unsubscribe(Action action); public void Unsubscribe(Action action);
} }
public interface IEntityFilterService { public interface IEntityFilterService
{
public delegate void EntityFilterAction(EntityFilterEvent entityFilterEvent); public delegate void EntityFilterAction(EntityFilterEvent entityFilterEvent);
public string GetFactionType(); public string GetFactionType();
@ -191,24 +194,23 @@ public interface IEntityFilterService {
public void Unsubscribe(EntityFilterAction action); public void Unsubscribe(EntityFilterAction action);
} }
public interface IEntityService
public interface IEntityService { {
public List<EntityModel> GetEntities(); public List<EntityModel> GetEntities();
} }
public interface IEntityDisplayService public interface IEntityDisplayService
{ {
public List<string> DefaultChoices(); public List<string> DefaultChoices();
public string GetDisplayType(); public string GetDisplayType();
public void SetDisplayType(string displayType); public void SetDisplayType(string displayType);
public void Subscribe(Action action); public void Subscribe(Action action);
public void Unsubscribe(Action action); public void Unsubscribe(Action action);
} }
public interface IImmortalSelectionService { public interface IImmortalSelectionService
{
public string GetFactionType(); public string GetFactionType();
public string GetImmortalType(); public string GetImmortalType();
public bool SelectFactionType(string factionType); public bool SelectFactionType(string factionType);
@ -217,7 +219,8 @@ public interface IImmortalSelectionService {
public void Unsubscribe(Action action); public void Unsubscribe(Action action);
} }
public interface IKeyService { public interface IKeyService
{
public List<string> GetAllPressedKeys(); public List<string> GetAllPressedKeys();
public string? GetHotkey(); public string? GetHotkey();
public string GetHotkeyGroup(); public string GetHotkeyGroup();
@ -228,7 +231,8 @@ public interface IKeyService {
public void Unsubscribe(Action? action); public void Unsubscribe(Action? action);
} }
public interface IMemoryTesterService { public interface IMemoryTesterService
{
public delegate void MemoryAction(MemoryTesterEvent memoryEvent); public delegate void MemoryAction(MemoryTesterEvent memoryEvent);
public List<MemoryEntityModel> GetEntities(); public List<MemoryEntityModel> GetEntities();
@ -244,15 +248,16 @@ public interface IMemoryTesterService {
public void Unsubscribe(MemoryAction memoryAction); public void Unsubscribe(MemoryAction memoryAction);
} }
public interface IBuildOrderService { public interface IBuildOrderService
{
public int BuildingInputDelay { get; set; }
public Dictionary<int, List<EntityModel>> StartedOrders { get; } public Dictionary<int, List<EntityModel>> StartedOrders { get; }
public Dictionary<int, List<EntityModel>> CompletedOrders { get; } public Dictionary<int, List<EntityModel>> CompletedOrders { get; }
public Dictionary<string, int> UniqueCompletedTimes { get; } public Dictionary<string, int> UniqueCompletedTimes { get; }
public Dictionary<int, int> SupplyCountTimes { get; } public Dictionary<int, int> SupplyCountTimes { get; }
public bool Add(EntityModel entity, IEconomyService withEconomy, IToastService toastService); public bool Add(EntityModel entity, IEconomyService withEconomy, IToastService toastService);
public void Add(EntityModel entity, int atInterval); public void Add(EntityModel entity, int atInterval);
@ -272,6 +277,7 @@ public interface IBuildOrderService {
public List<EntityModel> GetHarvestersCompletedBefore(int interval); public List<EntityModel> GetHarvestersCompletedBefore(int interval);
public void RemoveLast(); public void RemoveLast();
public void Reset();
public int GetLastRequestInterval(); public int GetLastRequestInterval();
public string BuildOrderAsYaml(); public string BuildOrderAsYaml();

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save