feat(Documents) Notes/Docs page improvements and warning cleanup

This commit is contained in:
2022-04-07 13:30:00 -04:00
parent b270453030
commit d82e60efdf
223 changed files with 4396 additions and 2861 deletions
+30 -3
View File
@@ -17,21 +17,48 @@
<style>
a {
color: #8fc5ff;
color: white;
font-weight: 700;
}
a:hover {
color: #d2f0ff;
color: white;
text-decoration: underline;
text-decoration-color: #8fc5ff;
text-decoration-thickness: 3px;
}
:root {
/* Duplicate Code, to deal with cache issues. See wwwroot/css/app.css for proper :root */
--accent: #432462;
--primary: #4308a3;
--primary-border: #2c0b62;
--primary-hover: #5e00f7;
--primary-border-hover: #a168ff;
--background: #161618;
--secondary: #23133e;
--secondary-hover: #2a0070;
--secondary-border-hover: #a168ff;
--paper: #252526;
--paper-border: #151516;
--paper-hover: #52366f;
--paper-border-hover: #653497;
--info: #451376;
--info-border: #210b36;
--dialog-border-color: black;
--dialog-border-width: 2px;
--dialog-radius: 6px;
}
</style>
@code {
#if NO_SQL
#if NO_SQL
#else
[Inject]
BIN
View File
Binary file not shown.
+26 -26
View File
@@ -3,9 +3,9 @@
<div class="dialogBackground" onclick="@CloseDialog">
<div class="dialogContainer"
@onclick:preventDefault="true"
@onclick:stopPropagation="true">
<div class="dialogContainer"
@onclick:preventDefault="true"
@onclick:stopPropagation="true">
@if (entity == null)
{
<div>Entity is null</div>
@@ -26,26 +26,26 @@
</div>
<div class="dialogContent">
<CascadingValue Value="@entity">
<EntityVanguardAddedComponent />
<EntityInfoComponent />
<EntityVanguardsComponent />
<EntityProductionComponent />
<EntityStatsComponent />
<EntityMechanicsComponent />
<EntityPassivesComponent />
<EntityPyreSpellsComponent />
<EntityUpgradesComponent />
<EntityWeaponsComponent />
<EntityAbilitiesComponent />
</CascadingValue>
<CascadingValue Value="@entity">
<EntityVanguardAddedComponent/>
<EntityInfoComponent/>
<EntityVanguardsComponent/>
<EntityProductionComponent/>
<EntityStatsComponent/>
<EntityMechanicsComponent/>
<EntityPassivesComponent/>
<EntityPyreSpellsComponent/>
<EntityUpgradesComponent/>
<EntityWeaponsComponent/>
<EntityAbilitiesComponent/>
</CascadingValue>
</div>
<div class="dialogFooter"></div>
}
</div>
</div>
<style>
@@ -133,19 +133,20 @@
</style>
@code {
EntityModel entity = null;
EntityModel entity = default!;
private int refresh = 0;
protected override void OnInitialized()
{
entity = DATA.Get()[entityDialogService.GetEntityId()];
entity = DATA.Get()[entityDialogService.GetEntityId() ?? string.Empty];
entityDialogService.Subscribe(OnUpdate);
}
public void Dispose() {
public void Dispose()
{
entityDialogService.Unsubscribe(OnUpdate);
}
@@ -157,11 +158,10 @@
Console.WriteLine("OnUpdate()");
StateHasChanged();
}
public void CloseDialog()
{
entityDialogService.CloseDialog();
}
}
}
+16 -11
View File
@@ -8,32 +8,37 @@
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DefineConstants>TRACE;NO_SQL</DefineConstants>
<DefineConstants>TRACE;NO_SQL</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DefineConstants>TRACE;NO_SQL</DefineConstants>
<DefineConstants>TRACE;NO_SQL</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Markdig" Version="0.28.1" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.0-preview.2.22153.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.0-preview.2.22153.2" PrivateAssets="all" />
<PackageReference Include="Markdig" Version="0.28.1"/>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.0-preview.2.22153.2"/>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.0-preview.2.22153.2" PrivateAssets="all"/>
<!--
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.0-preview.2.22153.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="7.0.0-preview.2.22153.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.0-preview.2.22153.1" />
<NativeFileReference Include="e_sqlite3.o" /> -->
<NativeFileReference Include="e_sqlite3.o" /> -->
</ItemGroup>
<ItemGroup>
<ServiceWorker Include="wwwroot\service-worker.js" PublishedContent="wwwroot\service-worker.published.js" />
<ServiceWorker Include="wwwroot\service-worker.js" PublishedContent="wwwroot\service-worker.published.js"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Components\Components.csproj" />
<ProjectReference Include="..\Contexts\Contexts.csproj" />
<ProjectReference Include="..\Model\Model.csproj" />
<ProjectReference Include="..\Services\Services.csproj" />
<ProjectReference Include="..\Components\Components.csproj"/>
<ProjectReference Include="..\Contexts\Contexts.csproj"/>
<ProjectReference Include="..\Model\Model.csproj"/>
<ProjectReference Include="..\Services\Services.csproj"/>
</ItemGroup>
<ItemGroup>
<Folder Include="wwwroot\generated"/>
</ItemGroup>
</Project>
+4
View File
@@ -2,4 +2,8 @@
@layout PageLayout
<DevOnlyComponent>
<DocumentationIndexPage></DocumentationIndexPage>
</DevOnlyComponent>
<HomePage></HomePage>
+26 -29
View File
@@ -1,26 +1,26 @@
@inherits LayoutComponentBase;
@inject IWebsiteService WebService;
@inject IWebsiteService webService;
@implements IDisposable;
<div class="layoutContainer" @onclick="OnPageClicked">
@if (!WebService.IsLoaded()) {
<LoadingComponent></LoadingComponent>
} else {
<div class="layoutContainer">
@if (!webService.IsLoaded())
{
<LoadingComponent/>
}
else
{
<div class="content">
@Body
</div>
<DesktopNavComponent WebSections=WebService.WebSectionModels
WebPages=WebService.WebPageModels />
<TabletNavComponent WebSections=WebService.WebSectionModels
WebPages=WebService.WebPageModels />
<MobileNavComponent WebSections=WebService.WebSectionModels
WebPages=WebService.WebPageModels />
<DesktopNavComponent WebSections=webService.WebSectionModels
WebPages=webService.WebPageModels/>
<TabletNavComponent WebSections=webService.WebSectionModels
WebPages=webService.WebPageModels/>
<MobileNavComponent WebSections=webService.WebSectionModels
WebPages=webService.WebPageModels/>
}
</div>
@@ -32,32 +32,29 @@
[Inject]
DatabaseContext Database { get; set; }
#endif
bool NavOpen = true;
void OnPageClicked(EventArgs eventArgs) {
NavOpen = false;
protected override void OnInitialized()
{
webService.Subscribe(HasChanged);
}
protected override void OnInitialized() {
WebService.Subscribe(HasChanged);
}
protected override async Task OnInitializedAsync() {
protected override async Task OnInitializedAsync()
{
#if NO_SQL
await WebService.Load();
await webService.Load();
#else
await WebService.Load(Database);
#endif
}
void IDisposable.Dispose() {
WebService.Unsubscribe(HasChanged);
void IDisposable.Dispose()
{
webService.Unsubscribe(HasChanged);
}
void HasChanged() {
void HasChanged()
{
StateHasChanged();
}
+45 -32
View File
@@ -5,34 +5,39 @@
@page "/agile"
@if (AgileService.IsLoaded()) {
@if (AgileService.IsLoaded())
{
<LayoutMediumContentComponent>
<WebsiteTitleComponent>Agile</WebsiteTitleComponent>
<div class="agileViewContainer">
@foreach (var sprint in AgileService.SprintModels.OrderBy(e => e.EndDate).Reverse()) {
@foreach (var sprint in AgileService.AgileSprintModels!.OrderBy(e => e.EndDate).Reverse())
{
<details class="sprintDisplayContainer @sprint.GetSprintType().ToLower()" open="@(sprint.GetSprintType() == SprintType.Current)">
<summary class="sprintSummary">
<div class="sprintTitle">@sprint.Name</div>
<div style="flex: 1; flex-grow: 1;"></div>
<div class="sprintDates">
<div class="sprintStartDate">
@if (sprint.StartDate != null)
{
<b>Start: </b>@sprint.StartDate.Value.ToString("dd/MM/yyyy")
}
@if (sprint.StartDate != null)
{
<b>Start: </b>
@sprint.StartDate.Value.ToString("dd/MM/yyyy")
}
</div>
<div class="sprintEndDate">
@if (sprint.EndDate != null)
{
<b>End: </b>@sprint.EndDate.Value.ToString("dd/MM/yyyy")
}
{
<b>End: </b>
@sprint.EndDate.Value.ToString("dd/MM/yyyy")
}
</div>
</div>
</summary>
<SprintComponent Sprint=sprint Tasks=AgileService.TaskModels></SprintComponent>
<SprintComponent AgileSprint="sprint"></SprintComponent>
</details>
}
@@ -49,29 +54,31 @@
<ContentDividerComponent></ContentDividerComponent>
<InfoBodyComponent>
<InfoQuestionComponent>What is Agile?</InfoQuestionComponent>
<InfoAnswerComponent>
Agile is a work methodology for determing task assignment and release deadlines.
<br/><br/>
My agile practice will be creating tasks in a backlog. Assigning them to weekly sprints. And completing all tasks in the allotted time frame.
<br/><br/>
Any unfinished tasks are moved into the next sprint, or the sprint will be extended by a week.
</InfoAnswerComponent>
</InfoBodyComponent>
<PaperComponent>
<InfoBodyComponent>
<InfoQuestionComponent>What is Agile?</InfoQuestionComponent>
<InfoAnswerComponent>
Agile is a work methodology for determing task assignment and release deadlines.
<br/><br/>
My agile practice will be creating tasks in a backlog. Assigning them to weekly sprints. And completing all tasks in the allotted time frame.
<br/><br/>
Any unfinished tasks are moved into the next sprint, or the sprint will be extended by a week.
</InfoAnswerComponent>
</InfoBodyComponent>
</PaperComponent>
</LayoutMediumContentComponent>
}
else {
<LoadingComponent></LoadingComponent>
else
{
<LoadingComponent/>
}
@code {
#if NO_SQL
public List<TaskModel> Tasks => AgileService.TaskModels;
public List<SprintModel> Sprints => AgileService.SprintModels;
#else
[Inject]
DatabaseContext Database { get; set; }
@@ -83,21 +90,26 @@ else {
public DbSet<SprintModel> Sprints { get; set; }
#endif
private readonly List<TaskModel> backlog = new();
private readonly List<AgileTaskModel> backlog = new();
protected override void OnInitialized() {
protected override void OnInitialized()
{
AgileService.Subscribe(HasChanged);
}
void IDisposable.Dispose() {
void IDisposable.Dispose()
{
AgileService.Unsubscribe(HasChanged);
}
void HasChanged() {
void HasChanged()
{
backlog.Clear();
foreach (var task in Tasks) {
if (task.SprintModelId == null) {
foreach (var task in AgileService.AgileTaskModels!)
{
if (task.AgileSprintModelId == null)
{
backlog.Add(task);
}
}
@@ -105,7 +117,8 @@ else {
StateHasChanged();
}
protected override async Task OnInitializedAsync() {
protected override async Task OnInitializedAsync()
{
#if NO_SQL
await AgileService.Load();
#else
+1 -1
View File
@@ -7,7 +7,7 @@
.sprintDisplayContainer {
border: 4px solid var(--paper);
box-shadow: 0px 2px 12px rgba(0,0,0,0.2);
box-shadow: 0px 2px 12px rgba(0, 0, 0, 0.2);
border-radius: 2px;
padding: 25px;
margin: auto;
+5 -24
View File
@@ -1,6 +1,7 @@
<div class="sprintContainer">
<div class="tasksContainer">
@foreach (var task in Backlog) {
@foreach (var task in Backlog)
{
<div class="taskContainer @task.Status.ToLower()">
<div class="taskName">@task.Name</div>
<div class="taskDetails">
@@ -17,7 +18,8 @@
</div>
</LayoutColumnComponent>
<LayoutColumnComponent>
@if (task.Finished != null) {
@if (task.Finished != null)
{
<div class="taskFinished">
<b>Finished: </b>@task.Finished
</div>
@@ -49,19 +51,6 @@
padding-top: 16px;
}
.sprintDescription {
grid-area: description;
}
.sprintStartDate {
}
.sprintEndDate {
}
.sprintNotes {
}
@@media only screen and (max-width: 1025px) {
.sprintContainer {
@@ -73,14 +62,6 @@
box-shadow: none;
padding: 8px;
}
.sprintStartDate {
text-align: left;
}
.sprintEndDate {
text-align: left;
}
}
.tasksContainer {
@@ -197,6 +178,6 @@
@code {
[Parameter]
public List<TaskModel> Backlog { get; set; }
public List<AgileTaskModel> Backlog { get; set; } = default!;
}
+13 -33
View File
@@ -1,16 +1,18 @@
<div class="sprintContainer">
<div class="sprintStatus">
<b>Status: </b>@Sprint.GetSprintType()
<b>Status: </b>@AgileSprint.GetSprintType()
</div>
<div class="sprintDescription">
<b>Description: </b>@Sprint.Description
<b>Description: </b>@AgileSprint.Description
</div>
<div class="sprintNotes">
<b>Notes: </b>@Sprint.Notes
<b>Notes: </b>@AgileSprint.Notes
</div>
<div class="tasksContainer">
@if (selectedTasks.Count > 0) {
@foreach (var task in selectedTasks) {
@if (AgileSprint.AgileTaskModels.Count > 0)
{
@foreach (var task in AgileSprint.AgileTaskModels)
{
<div class="taskContainer @task.Status.ToLower() @task.Task.ToLower()">
<div class="taskName">@task.Name</div>
<div class="taskDetails">
@@ -28,13 +30,14 @@
</LayoutColumnComponent>
<LayoutColumnComponent>
@if (task.Finished != null) {
@if (task.Finished != null)
{
<div class="taskFinished">
<b>Finished: </b>@task.Finished.Value.ToString("dd/MM/yyyy")
</div>
}
<div class="taskCreated">
<b>Created: </b>@task.Created.Value.ToString("dd/MM/yyyy")
<b>Created: </b>@task.Created!.Value.ToString("dd/MM/yyyy")
</div>
</LayoutColumnComponent>
</LayoutRowComponent>
@@ -48,7 +51,8 @@
</div>
}
}
else {
else
{
<div>Add Tasks...</div>
}
</div>
@@ -66,14 +70,6 @@
grid-area: description;
}
.sprintStartDate {
}
.sprintEndDate {
}
.sprintNotes {
}
@@media only screen and (max-width: 1025px) {
@@ -221,23 +217,7 @@
@code {
#if NO_SQL
[Parameter]
public List<TaskModel> Tasks { get; set; }
#else
[Parameter]
public DbSet<TaskModel> Tasks { get; set; }
#endif
[Parameter]
public SprintModel Sprint { get; set; }
private List<TaskModel> selectedTasks { get; set; }
protected override void OnInitialized() {
selectedTasks = (from task in Tasks
where task.SprintModelId == Sprint.Id
select task).OrderBy(x => x.Created).OrderBy(x => x.Finished).Reverse().OrderBy(x => x.Status).ToList();
}
public AgileSprintModel AgileSprint { get; set; } = default!;
}
@@ -2,6 +2,12 @@
@layout PageLayout
@inject IKeyService keyService
@inject IImmortalSelectionService filterService
@inject IBuildOrderService buildOrderService
@inject IEconomyService economyService
@inject ITimingService timingService
@page "/build-calculator"
<LayoutLargeContentComponent>
@@ -20,19 +26,15 @@
<div class="calculatorGrid">
<div style="grid-area: timing;" class="gridItem">
<InfoTooltipComponent InfoText="Enter build details.
<b>Timing Interval:</b> set the max interval length for the build. <i>Ex. 240 (seconds) is 4 minutes, a possible timing for Thrum build order.</i>
<b>Name:</b> the name of the build for saving purposes. <i>Ex. 'Safe Thrum Opener'</i>
<b>Notes:</b> additional notes of the build for saving purposes. <i>Ex. 'Thrums are for harassing and defending against a ground Q'Rath army.'</i>
<b>Color:</b> value to color charts when comparing builds. Not currently implemented.">
<InfoTooltipComponent InfoText="">
<TimingComponent></TimingComponent>
</InfoTooltipComponent>
</div>
@if (true) {
@if (true)
{
<div style="grid-area: chart;" class="gridItem">
<InfoTooltipComponent InfoText="Shows economy at each game interval. Use to determine if spending additional resourcses on harvesters will help or hinder overall timing attack.">
<ChartComponent></ChartComponent>
@@ -70,18 +72,15 @@
<div class="gridItem gridKeys">
<InfoTooltipComponent InfoText="Click on the desired entity to build it. <i>You cannot build entities you cannot afford, construct an ether extractor before spending ether.</i>
You can also use the default Immortal hotkeys, but the above hotkey UI must have focus for this to work. <i>I.e. click on it if hotkeys aren't working, and a white border should appear after key input to indicate focus.</i>
Additionally, more entities will appear as you build the required technology. You can click or press ` to remove the last made entity. <i>But you cannot remove the starting entities at interval 0.</i>">
<InfoTooltipComponent InfoText="">
<HotkeyViewerComponent Size="80"></HotkeyViewerComponent>
</InfoTooltipComponent>
</div>
@if (false) {
@if (false)
{
<div style="grid-area: timeline;" class="gridItem">
<TimelineComponent></TimelineComponent>
</div>
@@ -216,72 +215,59 @@ Additionally, more entities will appear as you build the required technology. Yo
@code {
[Inject]
IKeyService KeyService { get; set; }
[Inject]
IImmortalSelectionService FilterService { get; set; }
[Inject]
IBuildOrderService BuildOrderService { get; set; }
[Inject]
IEconomyService EconomyService { get; set; }
[Inject]
ITimingService TimingService { get; set; }
Dictionary<int, List<EntityModel>> completedEntities = new();
List<EntityModel> entities = EntityModel.GetListOnlyHotkey();
protected override void OnInitialized() {
KeyService.Subscribe(HandleClick);
FilterService.Subscribe(StateHasChanged);
EconomyService.Subscribe(StateHasChanged);
TimingService.Subscribe(HandleTimingChanged);
EconomyService.Calculate(BuildOrderService, TimingService, 0);
protected override void OnInitialized()
{
keyService.Subscribe(HandleClick);
filterService.Subscribe(StateHasChanged);
economyService.Subscribe(StateHasChanged);
timingService.Subscribe(HandleTimingChanged);
economyService.Calculate(buildOrderService, timingService, 0);
}
void IDisposable.Dispose() {
KeyService.Unsubscribe(HandleClick);
FilterService.Unsubscribe(StateHasChanged);
TimingService.Unsubscribe(StateHasChanged);
EconomyService.Unsubscribe(StateHasChanged);
void IDisposable.Dispose()
{
keyService.Unsubscribe(HandleClick);
filterService.Unsubscribe(StateHasChanged);
timingService.Unsubscribe(StateHasChanged);
economyService.Unsubscribe(StateHasChanged);
}
protected void HandleTimingChanged() {
EconomyService.Calculate(BuildOrderService, TimingService, BuildOrderService.GetLastRequestInterval());
private void HandleTimingChanged()
{
economyService.Calculate(buildOrderService, timingService, buildOrderService.GetLastRequestInterval());
}
protected void HandleClick() {
var hotkey = KeyService.GetHotkey();
private void HandleClick()
{
var hotkey = keyService.GetHotkey();
if (hotkey == "") {
if (hotkey == "")
{
return;
}
if (hotkey == "`") {
BuildOrderService.RemoveLast();
EconomyService.Calculate(BuildOrderService, TimingService, BuildOrderService.GetLastRequestInterval());
if (hotkey == "`")
{
buildOrderService.RemoveLast();
economyService.Calculate(buildOrderService, timingService, buildOrderService.GetLastRequestInterval());
StateHasChanged();
return;
}
var hotkeyGroup = KeyService.GetHotkeyGroup();
var isHoldSpace = KeyService.IsHoldingSpace();
var faction = FilterService.GetFactionType();
var immortal = FilterService.GetImmortalType();
var hotkeyGroup = keyService.GetHotkeyGroup();
var isHoldSpace = keyService.IsHoldingSpace();
var faction = filterService.GetFactionType();
var immortal = filterService.GetImmortalType();
var entity = EntityModel.GetFrom(hotkey, hotkeyGroup, isHoldSpace, faction, immortal);
if (entity == null) {
if (entity == null)
{
return;
}
if (BuildOrderService.Add(entity, EconomyService)) {
EconomyService.Calculate(BuildOrderService, TimingService, BuildOrderService.GetLastRequestInterval());
if (buildOrderService.Add(entity, economyService))
{
economyService.Calculate(buildOrderService, timingService, buildOrderService.GetLastRequestInterval());
}
}
@@ -2,12 +2,13 @@
<FormLayoutComponent>
<FormDisplayComponent Label="Army ready at">
<Display>@LastInterval | T @Interval.ToTime(LastInterval)</Display>
<Display>@lastInterval | T @Interval.ToTime(lastInterval)</Display>
</FormDisplayComponent>
<FormDisplayComponent Label="Army units built">
<Display>
<div style="display: flex; width: 100%; gap: 12px; flex-wrap: wrap;">
@foreach (var unit in armyCount) {
@foreach (var unit in armyCount)
{
<div style="width:90px; height: 60px; border: 1px solid gray; padding: 8px;">
<div>@unit.Value.ToString()x</div>
<div>@unit.Key</div>
@@ -22,38 +23,46 @@
@code {
[Inject]
public IBuildOrderService BuildOrder { get; set; }
public IBuildOrderService BuildOrder { get; set; } = default!;
int LastInterval;
private int lastInterval;
readonly Dictionary<string, int> armyCount = new();
List<EntityModel> army = new();
protected override void OnInitialized() {
protected override void OnInitialized()
{
BuildOrder.Subscribe(OnBuildOrderChanged);
}
void IDisposable.Dispose() {
void IDisposable.Dispose()
{
BuildOrder.Unsubscribe(OnBuildOrderChanged);
}
void OnBuildOrderChanged() {
void OnBuildOrderChanged()
{
armyCount.Clear();
LastInterval = 0;
lastInterval = 0;
var entitiesOverTime = BuildOrder.GetOrders();
foreach (var entitiesAtTime in entitiesOverTime) {
foreach (var entity in entitiesAtTime.Value) {
if (entity.EntityType == EntityType.Army) {
if (!armyCount.TryAdd(entity.Info().Name, 1)) {
foreach (var entitiesAtTime in entitiesOverTime)
{
foreach (var entity in entitiesAtTime.Value)
{
if (entity.EntityType == EntityType.Army)
{
if (!armyCount.TryAdd(entity.Info().Name, 1))
{
armyCount[entity.Info().Name]++;
}
if (entity.Production() != null && entity.Production().BuildTime + entitiesAtTime.Key > LastInterval) {
LastInterval = entity.Production().BuildTime + entitiesAtTime.Key;
if (entity.Production() != null && entity.Production().BuildTime + entitiesAtTime.Key > lastInterval)
{
lastInterval = entity.Production().BuildTime + entitiesAtTime.Key;
}
}
}
@@ -23,27 +23,30 @@
@code {
[Inject]
IBuildOrderService BuildOrderService { get; set; }
IBuildOrderService BuildOrderService { get; set; } = default!;
[Inject]
IEconomyService EconomyService { get; set; }
IEconomyService EconomyService { get; set; } = default!;
EconomyModel economy = new();
int supplyGranted;
int supplyTaken;
int extraBuildings;
protected override void OnInitialized() {
protected override void OnInitialized()
{
BuildOrderService.Subscribe(OnBuildOrderChanged);
EconomyService.Subscribe(OnBuildOrderChanged);
}
void IDisposable.Dispose() {
void IDisposable.Dispose()
{
BuildOrderService.Unsubscribe(OnBuildOrderChanged);
EconomyService.Subscribe(OnBuildOrderChanged);
}
void OnBuildOrderChanged() {
void OnBuildOrderChanged()
{
economy = EconomyService.GetEconomy(BuildOrderService.GetLastRequestInterval());
var ordersOverTime = BuildOrderService.GetOrders();
@@ -61,7 +64,8 @@
select order.Supply().Grants).Sum();
extraBuildings = 0;
if (supplyGranted > 160) {
if (supplyGranted > 160)
{
extraBuildings = (supplyGranted - 160) / 16;
supplyGranted = 160;
}
@@ -1,23 +1,24 @@
@implements IDisposable
@inject IBuildOrderService buildOrderService
@implements IDisposable
<FormLayoutComponent>
<FormTextAreaComponent Label="JSON Data"
Rows="14"
Value="@BuildOrderService.AsJson()">
Value="@buildOrderService.AsJson()">
</FormTextAreaComponent>
</FormLayoutComponent>
@code {
[Inject]
IBuildOrderService BuildOrderService { get; set; }
protected override void OnInitialized() {
BuildOrderService.Subscribe(StateHasChanged);
protected override void OnInitialized()
{
buildOrderService.Subscribe(StateHasChanged);
}
void IDisposable.Dispose() {
BuildOrderService.Unsubscribe(StateHasChanged);
void IDisposable.Dispose()
{
buildOrderService.Unsubscribe(StateHasChanged);
}
}
@@ -1,10 +1,12 @@
@implements IDisposable
<div class="chartsContainer">
@foreach (var chart in charts) {
@foreach (var chart in charts)
{
<div style="width: @chart.IntervalDisplayMax.ToString()px; height: @chart.ValueDisplayMax.ToString()px">
<div style="position: relative; border: 2px solid gray; border-radius:2px; width: @chart.IntervalDisplayMax.ToString()px; height: @chart.ValueDisplayMax.ToString()px">
@foreach (var point in chart.Points) {
@foreach (var point in chart.Points)
{
<div style="position: absolute;
bottom:@point.GetValue(chart.HighestValuePoint, chart.ValueDisplayMax)px;
left:@point.GetInterval(chart.HighestIntervalPoint, chart.IntervalDisplayMax)px;
@@ -51,10 +53,10 @@
@code {
[Inject]
IEconomyService EconomyService { get; set; }
IEconomyService EconomyService { get; set; } = default!;
[Inject]
IBuildOrderService BuildOrderService { get; set; }
IBuildOrderService BuildOrderService { get; set; } = default!;
int height = 100;
@@ -70,43 +72,50 @@
float highestPyrePoint;
float highestArmyPoint;
protected override void OnInitialized() {
protected override void OnInitialized()
{
EconomyService.Subscribe(GenerateChart);
BuildOrderService.Subscribe(GenerateChart);
GenerateChart();
}
void IDisposable.Dispose() {
void IDisposable.Dispose()
{
EconomyService.Unsubscribe(GenerateChart);
BuildOrderService.Unsubscribe(GenerateChart);
}
void GenerateChart() {
void GenerateChart()
{
var economyOverTime = EconomyService.GetOverTime();
charts.Clear();
var alloyChart = new ChartModel {
var alloyChart = new ChartModel
{
IntervalDisplayMax = width,
ValueDisplayMax = 100,
ChartColor = "Cyan"
};
var etherChart = new ChartModel {
var etherChart = new ChartModel
{
Offset = width,
IntervalDisplayMax = width,
ValueDisplayMax = 100,
ChartColor = "LightGreen"
};
var pyreChart = new ChartModel {
var pyreChart = new ChartModel
{
Offset = width * 2,
IntervalDisplayMax = width,
ValueDisplayMax = 100,
ChartColor = "Red"
};
var armyChart = new ChartModel {
var armyChart = new ChartModel
{
Offset = width * 3,
IntervalDisplayMax = width,
ValueDisplayMax = 100,
@@ -118,13 +127,15 @@
highestPyrePoint = 0;
highestArmyPoint = 0;
for (var interval = 0; interval < economyOverTime.Count(); interval++) {
for (var interval = 0; interval < economyOverTime.Count(); interval++)
{
var army = from unit in BuildOrderService.GetCompletedBefore(interval)
where unit.EntityType == EntityType.Army
select unit;
var armyValue = 0;
foreach (var unit in army) {
foreach (var unit in army)
{
armyValue += unit.Production().Alloy + unit.Production().Ether;
}
@@ -135,7 +146,8 @@
}
for (var interval = 0; interval < economyOverTime.Count(); interval++) {
for (var interval = 0; interval < economyOverTime.Count(); interval++)
{
var alloyPoint = new PointModel { Interval = interval };
var etherPoint = new PointModel { Interval = interval };
var pyrePoint = new PointModel { Interval = interval };
@@ -167,26 +179,32 @@
float economySpending = 0;
foreach (var alloyAutoHarvester in alloyAutomaticHarvesters) {
foreach (var alloyAutoHarvester in alloyAutomaticHarvesters)
{
autoAlloy += alloyAutoHarvester.Harvest().Slots * alloyAutoHarvester.Harvest().HarvestedPerInterval;
var production = alloyAutoHarvester.Production();
if (production != null) {
if (production != null)
{
economySpending += production.Alloy;
}
}
foreach (var alloyWorkerHarvester in alloyWorkerHarvesters) {
foreach (var alloyWorkerHarvester in alloyWorkerHarvesters)
{
workerSlots += alloyWorkerHarvester.Harvest().Slots;
var production = alloyWorkerHarvester.Production();
if (production != null) {
if (production != null)
{
economySpending += production.Alloy;
}
}
foreach (var etherWorkerHarvester in etherAutomaticHarvesters) {
foreach (var etherWorkerHarvester in etherAutomaticHarvesters)
{
autoEther += etherWorkerHarvester.Harvest().Slots * etherWorkerHarvester.Harvest().HarvestedPerInterval;
var production = etherWorkerHarvester.Production();
if (production != null) {
if (production != null)
{
economySpending += production.Alloy;
}
}
@@ -200,7 +218,8 @@
etherPoint.Value = autoEther;
if (interval > 0) {
if (interval > 0)
{
alloyPoint.TempValue += alloyChart.Points.Last().TempValue;
etherPoint.Value += etherChart.Points.Last().Value;
pyrePoint.Value = pyreChart.Points.Last().Value + 1;
@@ -1,35 +1,39 @@
@implements IDisposable
<div style="overflow-y: scroll; width: 100%; overflow-x: hidden; height: 550px;">
@if (Entity != null) {
@if (entity != null)
{
<EntityViewComponent Entity=Entity></EntityViewComponent>
}
</div>
@code {
EntityModel Entity;
private EntityModel entity = default!;
[Inject]
IKeyService KeyService { get; set; }
IKeyService KeyService { get; set; } = default!;
[Inject]
IImmortalSelectionService FilterService { get; set; }
IImmortalSelectionService FilterService { get; set; } = default!;
[Inject]
IBuildOrderService BuildOrderService { get; set; }
IBuildOrderService BuildOrderService { get; set; } = default!;
protected override void OnInitialized() {
protected override void OnInitialized()
{
KeyService.Subscribe(HandleClick);
BuildOrderService.Subscribe(OnBuildOrderChanged);
}
void IDisposable.Dispose() {
void IDisposable.Dispose()
{
KeyService.Unsubscribe(HandleClick);
BuildOrderService.Unsubscribe(OnBuildOrderChanged);
}
protected void HandleClick() {
protected void HandleClick()
{
var hotkey = KeyService.GetHotkey();
var hotkeyGroup = KeyService.GetHotkeyGroup();
var isHoldSpace = KeyService.IsHoldingSpace();
@@ -38,13 +42,15 @@
var foundEntity = EntityModel.GetFrom(hotkey, hotkeyGroup, isHoldSpace, faction, immortal);
if (foundEntity != null) {
Entity = foundEntity;
if (foundEntity != null)
{
entity = foundEntity;
StateHasChanged();
}
}
void OnBuildOrderChanged() {
void OnBuildOrderChanged()
{
StateHasChanged();
}
@@ -10,11 +10,13 @@
<FormSelectComponent OnChange="@OnImmortalChanged">
<FormLabelComponent>Immortal</FormLabelComponent>
<ChildContent>
@if (FilterService.GetFactionType() == FactionType.QRath) {
@if (FilterService.GetFactionType() == FactionType.QRath)
{
<option value="@ImmortalType.Orzum" selected>Orzum</option>
<option value="@ImmortalType.Ajari">Ajari</option>
}
@if (FilterService.GetFactionType() == FactionType.Aru) {
@if (FilterService.GetFactionType() == FactionType.Aru)
{
<option value="@ImmortalType.Mala" selected>Mala</option>
<option value="@ImmortalType.Xol">Xol</option>
}
@@ -25,14 +27,16 @@
@code {
[Inject]
public IImmortalSelectionService FilterService { get; set; }
public IImmortalSelectionService FilterService { get; set; } = default!;
void OnFactionChanged(ChangeEventArgs e) {
FilterService.SelectFactionType(e.Value.ToString());
void OnFactionChanged(ChangeEventArgs e)
{
FilterService.SelectFactionType(e.Value!.ToString()!);
}
void OnImmortalChanged(ChangeEventArgs e) {
FilterService.SelectImmortalType(e.Value.ToString());
void OnImmortalChanged(ChangeEventArgs e)
{
FilterService.SelectImmortalType(e.Value!.ToString()!);
}
}
@@ -4,9 +4,12 @@
<div>
<div>Requested</div>
@for (var i = TimingService.GetTiming() - 1; i >= 0; i--) {
@foreach (var order in BuildOrderService.GetOrdersAt(i)) {
if (order.EntityType == EntityType.Worker) {
@for (var i = TimingService.GetTiming() - 1; i >= 0; i--)
{
@foreach (var order in BuildOrderService.GetOrdersAt(i))
{
if (order.EntityType == EntityType.Worker)
{
continue;
}
<div>
@@ -22,9 +25,12 @@
<div>
<div>Finished</div>
@for (var i = TimingService.GetTiming() - 1; i >= 0; i--) {
@foreach (var order in BuildOrderService.GetCompletedAt(i)) {
if (order.EntityType == EntityType.Worker) {
@for (var i = TimingService.GetTiming() - 1; i >= 0; i--)
{
@foreach (var order in BuildOrderService.GetCompletedAt(i))
{
if (order.EntityType == EntityType.Worker)
{
continue;
}
<div>
@@ -54,20 +60,22 @@
@code {
[Inject]
IEconomyService EconomyService { get; set; }
IEconomyService EconomyService { get; set; } = default!;
[Inject]
IBuildOrderService BuildOrderService { get; set; }
IBuildOrderService BuildOrderService { get; set; } = default!;
[Inject]
ITimingService TimingService { get; set; }
ITimingService TimingService { get; set; } = default!;
protected override void OnInitialized() {
protected override void OnInitialized()
{
EconomyService.Subscribe(StateHasChanged);
BuildOrderService.Subscribe(StateHasChanged);
}
void IDisposable.Dispose() {
void IDisposable.Dispose()
{
EconomyService.Unsubscribe(StateHasChanged);
BuildOrderService.Unsubscribe(StateHasChanged);
}
@@ -2,8 +2,10 @@
<InputPanelComponent>
<div class="keyContainer">
@foreach (var hotkey in hotkeys) {
if (hotkey.IsHidden) {
@foreach (var hotkey in hotkeys)
{
if (hotkey.IsHidden)
{
continue;
}
@@ -14,14 +16,17 @@
var y = hotkey.PositionY * Size;
var border = "1px solid black";
if (hotkey.KeyText.Equals(_key)) {
if (hotkey.KeyText.Equals(_key))
{
border = "5px solid black";
}
if (hotkey.KeyText.Equals(_controlGroup)) {
if (hotkey.KeyText.Equals(_controlGroup))
{
border = "5px solid green";
}
if (hotkey.KeyText.Equals("SPACE") && KeyService.IsHoldingSpace()) {
if (hotkey.KeyText.Equals("SPACE") && KeyService.IsHoldingSpace())
{
border = "5px solid green";
}
@@ -39,16 +44,20 @@
overflow: hidden;
padding: 4px;">
@hotkey.KeyText
@foreach (var entity in data.Values) {
if (!BuildOrderService.MeetsRequirements(entity, 9000)) {
@foreach (var entity in data.Values)
{
if (!BuildOrderService.MeetsRequirements(entity, 9000))
{
continue;
}
if (InvalidKey(entity, hotkey) || InvalidKeyGroup(entity, hotkey) || InvalidHoldSpace(entity)) {
if (InvalidKey(entity, hotkey) || InvalidKeyGroup(entity, hotkey) || InvalidHoldSpace(entity))
{
continue;
}
if (InvalidFaction(entity) || InvalidVanguard(entity) || InvalidNonVanguard(entity)) {
if (InvalidFaction(entity) || InvalidVanguard(entity) || InvalidNonVanguard(entity))
{
continue;
}
@@ -77,7 +86,7 @@
@@media only screen and (max-width: 1025px) {
.keyContainer {
transform: scale(0.85) translateX(-20px);
background-color: none;
background-color: transparent;
outline: none;
}
}
@@ -89,13 +98,13 @@
public int Size { get; set; } = 100;
[Inject]
public IKeyService KeyService { get; set; }
public IKeyService KeyService { get; set; } = default!;
[Inject]
public IBuildOrderService BuildOrderService { get; set; }
public IBuildOrderService BuildOrderService { get; set; } = default!;
[Inject]
public IImmortalSelectionService FilterService { get; set; }
public IImmortalSelectionService FilterService { get; set; } = default!;
readonly Dictionary<string, EntityModel> data = EntityModel.GetDictionary();
readonly List<HotkeyModel> hotkeys = HotkeyModel.GetAll();
@@ -103,21 +112,25 @@
public string _controlGroup = "C";
public string _key = "";
protected override void OnInitialized() {
protected override void OnInitialized()
{
base.OnInitialized();
KeyService.Subscribe(OnKeyPressed);
FilterService.Subscribe(StateHasChanged);
}
void IDisposable.Dispose() {
void IDisposable.Dispose()
{
KeyService.Unsubscribe(OnKeyPressed);
FilterService.Unsubscribe(StateHasChanged);
}
// Move to Filter Service
bool InvalidFaction(EntityModel entity) {
if (entity.Faction() != null && entity.Faction()?.Faction != FilterService.GetFactionType() && FilterService.GetFactionType() != FactionType.Any) {
bool InvalidFaction(EntityModel entity)
{
if (entity.Faction() != null && entity.Faction()?.Faction != FilterService.GetFactionType() && FilterService.GetFactionType() != FactionType.Any)
{
return true;
}
@@ -125,8 +138,10 @@
}
// Move to Filter Service
bool InvalidVanguard(EntityModel entity) {
if (entity.VanguardAdded() != null && entity.VanguardAdded()?.ImmortalId != FilterService.GetImmortalType() && FilterService.GetImmortalType() != ImmortalType.Any) {
bool InvalidVanguard(EntityModel entity)
{
if (entity.VanguardAdded() != null && entity.VanguardAdded()?.ImmortalId != FilterService.GetImmortalType() && FilterService.GetImmortalType() != ImmortalType.Any)
{
return true;
}
@@ -134,16 +149,21 @@
}
// Move to Filter Service
bool InvalidNonVanguard(EntityModel entity) {
if (entity.Replaceds().Count > 0) {
bool InvalidNonVanguard(EntityModel entity)
{
if (entity.Replaceds().Count > 0)
{
var isReplaced = false;
foreach (var replaced in entity.Replaceds()) {
if (FilterService.GetImmortalType() == replaced.ImmortalId) {
foreach (var replaced in entity.Replaceds())
{
if (FilterService.GetImmortalType() == replaced.ImmortalId)
{
isReplaced = true;
break;
}
}
if (isReplaced) {
if (isReplaced)
{
return true;
}
}
@@ -151,75 +171,96 @@
return false;
}
bool InvalidRequirements(EntityModel entity) {
bool InvalidRequirements(EntityModel entity)
{
return !BuildOrderService.MeetsRequirements(entity, 9000);
}
bool InvalidKey(EntityModel entity, HotkeyModel key) {
if (entity.Hotkey()?.Hotkey == key.KeyText) {
bool InvalidKey(EntityModel entity, HotkeyModel key)
{
if (entity.Hotkey()?.Hotkey == key.KeyText)
{
return false;
}
return true;
}
bool InvalidKeyGroup(EntityModel entity, HotkeyModel key) {
if (entity.Hotkey()?.HotkeyGroup == _controlGroup) {
bool InvalidKeyGroup(EntityModel entity, HotkeyModel key)
{
if (entity.Hotkey()?.HotkeyGroup == _controlGroup)
{
return false;
}
return true;
}
bool InvalidKey(EntityModel entity) {
if (entity.Hotkey()?.Hotkey == _key) {
bool InvalidKey(EntityModel entity)
{
if (entity.Hotkey()?.Hotkey == _key)
{
return false;
}
return true;
}
bool InvalidKeyGroup(EntityModel entity) {
if (entity.Hotkey()?.HotkeyGroup == _controlGroup) {
bool InvalidKeyGroup(EntityModel entity)
{
if (entity.Hotkey()?.HotkeyGroup == _controlGroup)
{
return false;
}
return true;
}
bool InvalidHoldSpace(EntityModel entity) {
if (entity.Hotkey()?.HoldSpace == KeyService.IsHoldingSpace()) {
bool InvalidHoldSpace(EntityModel entity)
{
if (entity.Hotkey()?.HoldSpace == KeyService.IsHoldingSpace())
{
return false;
}
return true;
}
void OnKeyPressed() {
if (KeyService.GetAllPressedKeys().Contains("Z")) {
void OnKeyPressed()
{
if (KeyService.GetAllPressedKeys().Contains("Z"))
{
_controlGroup = "Z";
}
if (KeyService.GetAllPressedKeys().Contains("TAB")) {
if (KeyService.GetAllPressedKeys().Contains("TAB"))
{
_controlGroup = "TAB";
}
if (KeyService.GetAllPressedKeys().Contains("C")) {
if (KeyService.GetAllPressedKeys().Contains("C"))
{
_controlGroup = "C";
}
if (KeyService.GetAllPressedKeys().Contains("D")) {
if (KeyService.GetAllPressedKeys().Contains("D"))
{
_controlGroup = "D";
}
if (KeyService.GetAllPressedKeys().Contains("1")) {
if (KeyService.GetAllPressedKeys().Contains("1"))
{
_controlGroup = "1";
}
//TODO This could be better. Duplicated code
if (KeyService.GetAllPressedKeys().Contains("2")) {
if (KeyService.GetAllPressedKeys().Contains("2"))
{
_controlGroup = "2";
}
if (KeyService.GetAllPressedKeys().Contains("SHIFT")) {
if (KeyService.GetAllPressedKeys().Contains("SHIFT"))
{
_controlGroup = "SHIFT";
}
if (KeyService.GetAllPressedKeys().Contains("CONTROL")) {
if (KeyService.GetAllPressedKeys().Contains("CONTROL"))
{
_controlGroup = "CONTROL";
}
if (KeyService.GetAllPressedKeys().Count > 0) {
if (KeyService.GetAllPressedKeys().Count > 0)
{
_key = KeyService.GetAllPressedKeys().First();
}
@@ -10,16 +10,18 @@
@code {
[Parameter]
public RenderFragment ChildContent { get; set; }
public RenderFragment ChildContent { get; set; } = default!;
[Inject]
public IKeyService KeyService { get; set; }
public IKeyService KeyService { get; set; } = default!;
private void HandleKeyDown(KeyboardEventArgs e) {
private void HandleKeyDown(KeyboardEventArgs e)
{
KeyService.AddPressedKey(e.Key);
}
private void HandleKeyUp(KeyboardEventArgs e) {
private void HandleKeyUp(KeyboardEventArgs e)
{
KeyService.RemovePressedKey(e.Key);
}
@@ -24,12 +24,14 @@
<br/>
</div>
<div>
@foreach (var order in BuildOrderService.GetOrdersAt(economyAtSecond.Interval)) {
@foreach (var order in BuildOrderService.GetOrdersAt(economyAtSecond.Interval))
{
<div>
Requested: @order.Info().Name
</div>
}
@foreach (var order in BuildOrderService.GetCompletedAt(economyAtSecond.Interval)) {
@foreach (var order in BuildOrderService.GetCompletedAt(economyAtSecond.Interval))
{
<div>
New: @order.Info().Name
</div>
@@ -42,17 +44,19 @@
@code {
[Inject]
IEconomyService EconomyService { get; set; }
IEconomyService EconomyService { get; set; } = default!;
[Inject]
IBuildOrderService BuildOrderService { get; set; }
IBuildOrderService BuildOrderService { get; set; } = default!;
protected override void OnInitialized() {
protected override void OnInitialized()
{
EconomyService.Subscribe(StateHasChanged);
BuildOrderService.Subscribe(StateHasChanged);
}
void IDisposable.Dispose() {
void IDisposable.Dispose()
{
EconomyService.Unsubscribe(StateHasChanged);
BuildOrderService.Unsubscribe(StateHasChanged);
}
@@ -20,31 +20,36 @@
@code {
[Inject]
public ITimingService TimingService { get; set; }
public ITimingService TimingService { get; set; } = default!;
[Inject]
public IBuildOrderService BuildOrderService { get; set; }
public IBuildOrderService BuildOrderService { get; set; } = default!;
void OnTimingChanged(ChangeEventArgs changeEventArgs) {
TimingService.SetTiming(int.Parse(changeEventArgs.Value.ToString()));
void OnTimingChanged(ChangeEventArgs changeEventArgs)
{
TimingService.SetTiming(int.Parse(changeEventArgs.Value!.ToString()!));
}
void OnTimingChanged(int value) {
void OnTimingChanged(int value)
{
TimingService.SetTiming(value);
}
void OnNameChanged(ChangeEventArgs changeEventArgs) {
BuildOrderService.SetName(changeEventArgs.Value.ToString());
void OnNameChanged(ChangeEventArgs changeEventArgs)
{
BuildOrderService.SetName(changeEventArgs.Value!.ToString()!);
}
void OnColorChanged(ChangeEventArgs changeEventArgs) {
BuildOrderService.SetColor(changeEventArgs.Value.ToString());
void OnColorChanged(ChangeEventArgs changeEventArgs)
{
BuildOrderService.SetColor(changeEventArgs.Value!.ToString()!);
}
void OnNotesChanged(ChangeEventArgs changeEventArgs) {
BuildOrderService.SetNotes(changeEventArgs.Value.ToString());
void OnNotesChanged(ChangeEventArgs changeEventArgs)
{
BuildOrderService.SetNotes(changeEventArgs.Value!.ToString()!);
}
}
+34 -20
View File
@@ -5,7 +5,8 @@
@layout PageLayout
@if (GitService.IsLoaded()) {
@if (GitService.IsLoaded())
{
<LayoutMediumContentComponent>
<WebsiteTitleComponent>Change Log</WebsiteTitleComponent>
@@ -20,8 +21,10 @@
</PaperComponent>
<PaperComponent>
@foreach (var patch in Patches.OrderBy(x => x.Date).Reverse()) {
@if (!patch.Important.Equals("True") && isViewImportant) {
@foreach (var patch in Patches.OrderBy(x => x.Date).Reverse())
{
@if (!patch.Important.Equals("True") && isViewImportant)
{
continue;
}
@@ -33,21 +36,26 @@
@patch.Name
</div>
<div>
@if (daysAgo == 0) {
@if (daysAgo == 0)
{
<i>Today</i>
}
else if (daysAgo < 8) {
else if (daysAgo < 8)
{
<i>@daysAgo days ago</i>
}
else {
else
{
<i>@patch.Date.ToString("dd/MM/yyyy")</i>
}
</div>
</div>
<div>
@foreach (var change in Changes.FindAll(e => e.PatchModelId == patch.Id)) {
@if (!change.Important.Equals("True") && isViewImportant) {
@foreach (var change in Changes.FindAll(e => e.GitPatchModelId == patch.Id))
{
@if (!change.Important.Equals("True") && isViewImportant)
{
continue;
}
@@ -57,7 +65,8 @@
<b>
<span>- @change.Name </span>
@if (change.Commit != CommitType.None) {
@if (change.Commit != CommitType.None)
{
<span>(@change.Commit)</span>
}
<span>: </span>
@@ -68,23 +77,23 @@
}
</div>
</div>
}
</PaperComponent>
</LayoutMediumContentComponent>
}
else {
<LoadingComponent></LoadingComponent>
else
{
<LoadingComponent/>
}
@code {
#if NO_SQL
public List<PatchModel> Patches => GitService.PatchModels;
public List<GitPatchModel> Patches => GitService.GitPatchModels;
public List<ChangeModel> Changes => GitService.ChangeModels;
public List<GitChangeModel> Changes => GitService.GitChangeModels;
#else
[Inject]
DatabaseContext Database { get; set; }
@@ -99,24 +108,29 @@ else {
private bool isViewImportant = true;
protected override void OnInitialized() {
protected override void OnInitialized()
{
GitService.Subscribe(HasChanged);
}
void IDisposable.Dispose() {
void IDisposable.Dispose()
{
GitService.Unsubscribe(HasChanged);
}
void OnChangeClicked(ChangeEventArgs changeEventArgs) {
isViewImportant = (bool)changeEventArgs.Value;
void OnChangeClicked(ChangeEventArgs changeEventArgs)
{
isViewImportant = (bool)changeEventArgs.Value!;
}
void HasChanged() {
void HasChanged()
{
StateHasChanged();
}
protected override async Task OnInitializedAsync() {
protected override async Task OnInitializedAsync()
{
#if NO_SQL
GitService.Load();
#else
+19 -12
View File
@@ -28,19 +28,19 @@ grid-template-areas: 'loader sand compare compare' ;">
@code {
[Inject]
IKeyService KeyService { get; set; }
IKeyService KeyService { get; set; } = default!;
[Inject]
IImmortalSelectionService FilterService { get; set; }
IImmortalSelectionService FilterService { get; set; } = default!;
[Inject]
IBuildOrderService BuildOrderService { get; set; }
IBuildOrderService BuildOrderService { get; set; } = default!;
[Inject]
IEconomyService EconomyService { get; set; }
IEconomyService EconomyService { get; set; } = default!;
[Inject]
ITimingService TimingService { get; set; }
ITimingService TimingService { get; set; } = default!;
Dictionary<int, List<EntityModel>> completedEntities = new();
@@ -48,7 +48,8 @@ grid-template-areas: 'loader sand compare compare' ;">
List<EntityModel> entities = EntityModel.GetListOnlyHotkey();
protected override void OnInitialized() {
protected override void OnInitialized()
{
KeyService.Subscribe(HandleClick);
FilterService.Subscribe(StateHasChanged);
EconomyService.Subscribe(StateHasChanged);
@@ -56,7 +57,8 @@ grid-template-areas: 'loader sand compare compare' ;">
EconomyService.Calculate(BuildOrderService, TimingService, 0);
}
void IDisposable.Dispose() {
void IDisposable.Dispose()
{
KeyService.Unsubscribe(HandleClick);
FilterService.Unsubscribe(StateHasChanged);
TimingService.Unsubscribe(StateHasChanged);
@@ -64,18 +66,21 @@ grid-template-areas: 'loader sand compare compare' ;">
}
protected void HandleTimingChanged() {
protected void HandleTimingChanged()
{
EconomyService.Calculate(BuildOrderService, TimingService, BuildOrderService.GetLastRequestInterval());
}
protected void HandleClick() {
protected void HandleClick()
{
var hotkey = KeyService.GetHotkey();
var hotkeyGroup = KeyService.GetHotkeyGroup();
var isHoldSpace = KeyService.IsHoldingSpace();
var faction = FilterService.GetFactionType();
var immortal = FilterService.GetImmortalType();
if (hotkey == "`") {
if (hotkey == "`")
{
BuildOrderService.RemoveLast();
EconomyService.Calculate(BuildOrderService, TimingService, BuildOrderService.GetLastRequestInterval());
StateHasChanged();
@@ -83,10 +88,12 @@ grid-template-areas: 'loader sand compare compare' ;">
}
var entity = EntityModel.GetFrom(hotkey, hotkeyGroup, isHoldSpace, faction, immortal);
if (entity == null) {
if (entity == null)
{
return;
}
if (BuildOrderService.Add(entity, EconomyService)) {
if (BuildOrderService.Add(entity, EconomyService))
{
EconomyService.Calculate(BuildOrderService, TimingService, BuildOrderService.GetLastRequestInterval());
}
}
@@ -16,17 +16,20 @@
string buildData = "";
[Inject]
IBuildComparisonService BuildComparisionService { get; set; }
IBuildComparisonService BuildComparisionService { get; set; } = default!;
protected override void OnInitialized() {
protected override void OnInitialized()
{
BuildComparisionService.Subscribe(StateHasChanged);
}
void IDisposable.Dispose() {
void IDisposable.Dispose()
{
BuildComparisionService.Unsubscribe(StateHasChanged);
}
void OnLoad() {
void OnLoad()
{
BuildComparisionService.LoadJson(buildData);
}
@@ -9,13 +9,15 @@
@code {
[Inject]
IBuildComparisonService BuildComparisonService { get; set; }
IBuildComparisonService BuildComparisonService { get; set; } = default!;
protected override void OnInitialized() {
protected override void OnInitialized()
{
BuildComparisonService.Subscribe(StateHasChanged);
}
void IDisposable.Dispose() {
void IDisposable.Dispose()
{
BuildComparisonService.Unsubscribe(StateHasChanged);
}
+1 -1
View File
@@ -11,7 +11,7 @@
How do I contact you for feature requests and bug reports?
</InfoQuestionComponent>
<InfoAnswerComponent>
You can direct message me at <b>Iremirror#3544</b> on the <a href="https://discord.gg/uMq8bMGeeN" target="_blank">IGP Fan Reference</a> discord.
You can message me at <b>JonathanMcCaffrey#3544</b> on my <a href="https://discord.gg/uMq8bMGeeN" target="_blank">Discord</a> channel.
</InfoAnswerComponent>
</InfoBodyComponent>
</PaperComponent>
+66 -42
View File
@@ -10,27 +10,29 @@
<WebsiteTitleComponent>Database</WebsiteTitleComponent>
<PaperComponent>
<FormDisplayComponent Label="Patch">
<Display>
Game Patch: @EntityModel.GameVersion
</Display>
</FormDisplayComponent>
<FormDisplayComponent Label="Patch">
<Display>
Game Patch: @EntityModel.GameVersion
</Display>
</FormDisplayComponent>
</PaperComponent>
<div style="margin-left: 8px">
<ButtonGroupComponent OnClick="((choice => { entityDisplayService.SetDisplayType(choice); }))" Choice="@entityDisplayService.GetDisplayType()" Choices="@entityDisplayService.DefaultChoices()"></ButtonGroupComponent>
</div>
<ButtonGroupComponent OnClick="choice => { entityDisplayService.SetDisplayType(choice); }" Choice="@entityDisplayService.GetDisplayType()" Choices="@entityDisplayService.DefaultChoices()"></ButtonGroupComponent>
</div>
<PaperComponent>
<EntityFilterComponent></EntityFilterComponent>
@if (searches != null) {
@if (searches != null)
{
<div class="databaseItems">
@foreach (var entity in searches) {
@foreach (var entity in searches)
{
<CascadingValue Value="entity">
<CascadingValue Value="@entityDisplayService.GetDisplayType()">
<EntityViewComponent></EntityViewComponent>
</CascadingValue>
</CascadingValue>
</CascadingValue>
}
</div>
@@ -112,16 +114,16 @@
@code {
[Inject]
public IEntityFilterService EntityFilterService { get; set; }
public IEntityFilterService EntityFilterService { get; set; } = default!;
readonly List<EntityModel> defaults = (from entity in EntityModel.GetList()
where entity.IsSpeculative == false
select entity).ToList();
List<EntityModel> factions;
List<EntityModel> immortals;
List<EntityModel> entities;
List<EntityModel> searches;
List<EntityModel> factions = default!;
List<EntityModel> immortals = default!;
List<EntityModel> entities = default!;
List<EntityModel> searches = default!;
string selectedFactionType = FactionType.Any;
@@ -129,44 +131,54 @@
string selectedEntityType = EntityType.Army;
string searchText = "";
protected override void OnInitialized() {
protected override void OnInitialized()
{
RefreshFactionSearch();
EntityFilterService.Subscribe(OnChange);
entityDisplayService.Subscribe(StateHasChanged);
}
void IDisposable.Dispose() {
void IDisposable.Dispose()
{
EntityFilterService.Unsubscribe(OnChange);
entityDisplayService.Unsubscribe(StateHasChanged);
}
void OnChange(EntityFilterEvent filterEntityEvent) {
if (filterEntityEvent == EntityFilterEvent.OnRefreshFaction) {
void OnChange(EntityFilterEvent filterEntityEvent)
{
if (filterEntityEvent == EntityFilterEvent.OnRefreshFaction)
{
RefreshFactionSearch();
}
if (filterEntityEvent == EntityFilterEvent.OnRefreshImmortal) {
if (filterEntityEvent == EntityFilterEvent.OnRefreshImmortal)
{
RefreshImmortalSearch();
}
if (filterEntityEvent == EntityFilterEvent.OnRefreshEntity) {
if (filterEntityEvent == EntityFilterEvent.OnRefreshEntity)
{
RefreshEntitySearch();
}
if (filterEntityEvent == EntityFilterEvent.OnRefreshSearch) {
if (filterEntityEvent == EntityFilterEvent.OnRefreshSearch)
{
RefreshTextSearch();
}
}
void RefreshFactionSearch() {
void RefreshFactionSearch()
{
selectedFactionType = EntityFilterService.GetFactionType();
if (selectedFactionType == FactionType.Any) {
if (selectedFactionType == FactionType.Any)
{
factions = defaults.ToList();
}
else {
else
{
factions = (from entity in defaults
where entity.Faction() != null && entity.Faction().Faction == selectedFactionType
select entity).ToList();
@@ -176,18 +188,22 @@
}
void OnImmortalChanged(ChangeEventArgs e) {
selectedImmortalType = e.Value.ToString();
void OnImmortalChanged(ChangeEventArgs e)
{
selectedImmortalType = e.Value!.ToString()!;
RefreshImmortalSearch();
}
void RefreshImmortalSearch() {
void RefreshImmortalSearch()
{
selectedImmortalType = EntityFilterService.GetImmortalType();
if (selectedImmortalType == ImmortalType.Any) {
if (selectedImmortalType == ImmortalType.Any)
{
immortals = factions.ToList();
}
else {
else
{
immortals = (from entity in factions
where entity.VanguardAdded() == null || entity.VanguardAdded().ImmortalId == selectedImmortalType
select entity).ToList();
@@ -196,18 +212,22 @@
RefreshEntitySearch();
}
void OnEntityChanged(ChangeEventArgs e) {
selectedEntityType = e.Value.ToString();
void OnEntityChanged(ChangeEventArgs e)
{
selectedEntityType = e.Value!.ToString()!;
RefreshEntitySearch();
}
void RefreshEntitySearch() {
void RefreshEntitySearch()
{
selectedEntityType = EntityFilterService.GetEntityType();
if (selectedEntityType == EntityType.Any) {
if (selectedEntityType == EntityType.Any)
{
entities = immortals.ToList();
}
else {
else
{
entities = (from entity in immortals
where entity.EntityType == selectedEntityType
select entity).ToList();
@@ -216,18 +236,22 @@
RefreshTextSearch();
}
void OnSearchTextChanged(ChangeEventArgs e) {
searchText = e.Value.ToString();
void OnSearchTextChanged(ChangeEventArgs e)
{
searchText = e.Value!.ToString()!;
RefreshTextSearch();
}
void RefreshTextSearch() {
void RefreshTextSearch()
{
searchText = EntityFilterService.GetSearchText();
if (searchText.Trim() == "") {
if (searchText.Trim() == "")
{
searches = entities.ToList();
}
else {
else
{
searches = (from entity in entities
where entity.Info().Name.ToLower().Contains(searchText.ToLower())
select entity).ToList();
+20 -19
View File
@@ -7,7 +7,7 @@
@implements IDisposable
<LayoutLargeContentComponent>
<PaperComponent>
<FormDisplayComponent Label="Patch">
<Display>
@@ -15,18 +15,19 @@
</Display>
</FormDisplayComponent>
</PaperComponent>
<div style="margin-left: 8px">
<ButtonGroupComponent OnClick="((choice => { entityDisplayService.SetDisplayType(choice); }))" Choice="@entityDisplayService.GetDisplayType()" Choices="@entityDisplayService.DefaultChoices()"></ButtonGroupComponent>
<ButtonGroupComponent OnClick="choice => { entityDisplayService.SetDisplayType(choice); }" Choice="@entityDisplayService.GetDisplayType()" Choices="@entityDisplayService.DefaultChoices()"></ButtonGroupComponent>
</div>
@if(Text.Trim().ToLower().Equals("walter"))
@if (Text!.Trim().ToLower().Equals("walter"))
{
<PaperComponent>
<CodeComponent>Unhandled Exception: EXCEPTION_MEMORY_SIZE_VIOLATION
<CodeComponent>
Unhandled Exception: EXCEPTION_MEMORY_SIZE_VIOLATION
UNIT_WALTER too powerful to be displayed.
This SHOULD NEVER HAPPEN!
</CodeComponent>
</PaperComponent>
@@ -37,36 +38,35 @@
<div>Invalid entity name entered: @Text</div>
<div>No such entity. Did you mean <b>"Throne"</b>?</div>
</PaperComponent>
}
}
else
{
<PaperComponent>
<CascadingValue Value="entity">
<CascadingValue Value="@entityDisplayService.GetDisplayType()">
<EntityViewComponent></EntityViewComponent>
</CascadingValue>
</CascadingValue>
</PaperComponent>
</PaperComponent>
}
</LayoutLargeContentComponent>
@code {
[Parameter]
public string? Text { get; set; }
private EntityModel? entity = null;
private EntityModel? entity;
protected override void OnInitialized()
{
entityDisplayService.Subscribe(StateHasChanged);
foreach (var e in DATA.Get().Values)
{
if (e.Info().Name.Equals(Text))
@@ -76,8 +76,9 @@
}
}
}
void IDisposable.Dispose() {
void IDisposable.Dispose()
{
entityDisplayService.Unsubscribe(StateHasChanged);
}
@@ -1,4 +1,5 @@
@if (Entity != null) {
@if (Entity != null)
{
var isVanguard = Entity.VanguardAdded() != null ? " vanguard" : "";
<div class="enititiesContainer @isVanguard">
@@ -47,9 +48,11 @@
</style>
@code {
[CascadingParameter]
public EntityModel? Entity { get; set; }
[CascadingParameter]
public string? StyleType { get; set; }
}
@@ -1,7 +1,9 @@
@if (Entity.IdAbilities().Count > 0) {
@if (Entity!.IdAbilities().Count > 0)
{
@if (StyleType.Equals("Plain"))
{
@foreach (var idAbility in Entity.IdAbilities()) {
@foreach (var idAbility in Entity.IdAbilities())
{
var spell = EntityModel.Get(idAbility.Id);
var info = spell.Info();
@@ -14,26 +16,31 @@
<div>
<b>- Description:</b> @((MarkupString)info.Description)
</div>
@if (!info.Notes.Trim().Equals("")) {
@if (!info.Notes.Trim().Equals(""))
{
<div>
<b>- Notes:</b> @((MarkupString)info.Notes)
</div>
</div>
}
<div>
@if (production != null) {
if (production.Energy != 0) {
@if (production != null)
{
if (production.Energy != 0)
{
<div>
<b>- Energy: </b> @production.Energy
</div>
}
if (production.BuildTime != 0) {
if (production.BuildTime != 0)
{
<div>
<b>- BuildTime: </b> @production.BuildTime
<b>- BuildTime: </b> @production.BuildTime
</div>
}
if (production.Cooldown != 0) {
if (production.Cooldown != 0)
{
<div>
<b>- Cooldown: </b> @production.Cooldown
</div>
@@ -42,13 +49,12 @@
</div>
</div>
}
}
else
{
<EntityDisplayComponent Title="Abilities">
@foreach (var idAbility in Entity.IdAbilities()) {
@foreach (var idAbility in Entity.IdAbilities())
{
var spell = EntityModel.Get(idAbility.Id);
var info = spell.Info();
@@ -61,26 +67,31 @@
<div>
<b>Description:</b> @((MarkupString)info.Description)
</div>
@if (!info.Notes.Trim().Equals("")) {
@if (!info.Notes.Trim().Equals(""))
{
<div>
<b>Notes:</b> @((MarkupString)info.Notes)
</div>
</div>
}
<div>
@if (production != null) {
if (production.Energy != 0) {
@if (production != null)
{
if (production.Energy != 0)
{
<div>
<b> Energy: </b> @production.Energy
</div>
}
if (production.BuildTime != 0) {
if (production.BuildTime != 0)
{
<div>
<b> BuildTime: </b> @production.BuildTime
<b> BuildTime: </b> @production.BuildTime
</div>
}
if (production.Cooldown != 0) {
if (production.Cooldown != 0)
{
<div>
<b> Cooldown: </b> @production.Cooldown
</div>
@@ -89,19 +100,18 @@
</div>
</div>
}
</EntityDisplayComponent>
</EntityDisplayComponent>
}
}
@code {
[CascadingParameter]
public EntityModel? Entity { get; set; }
public EntityModel? Entity { get; set; } = default!;
[CascadingParameter]
public string StyleType { get; set; } = "Detailed";
}
@@ -1,11 +1,12 @@
@if (StyleType.Equals("Plain"))
{
<div><b>@Entity?.Info().Name</b>
@if (Entity?.Info().Descriptive != DescriptiveType.None)
{
<span>, @Entity?.Info().Descriptive.Replace("_", " ")</span>
}
</div>
<div>
<b>@Entity?.Info().Name</b>
@if (Entity?.Info().Descriptive != DescriptiveType.None)
{
<span>, @Entity?.Info().Descriptive.Replace("_", " ")</span>
}
</div>
}
else
{
@@ -18,7 +19,7 @@ else
@if (Entity?.Info().Descriptive != DescriptiveType.None)
{
<span>
<b>:</b> @Entity.Info().Descriptive.Replace("_", " ")
<b>:</b> @Entity!.Info().Descriptive.Replace("_", " ")
</span>
}
</div>
@@ -53,9 +54,9 @@ else
@code {
[CascadingParameter]
public EntityModel? Entity { get; set; }
public EntityModel? Entity { get; set; } = default!;
[CascadingParameter]
public string StyleType { get; set; } = "Detailed";
@@ -1,34 +1,38 @@
@if (StyleType.Equals("Plain"))
@if (StyleType.Equals("Plain"))
{
@if (Entity.Info().Description != "") {
@if (Entity!.Info().Description != "")
{
<div>
<b>Description:</b> @((MarkupString)Entity.Info().Description)
</div>
}
@if (Entity.Info().Notes != "") {
@if (Entity.Info().Notes != "")
{
<div>
<b>Notes:</b> @((MarkupString)Entity.Info().Notes)
</div>
}
<div class="infoDisplayContainer">
<div>
@if (Entity.Faction() != null) {
@if (Entity.Faction() != null)
{
<div>
<b>Faction:</b> @Entity.Faction().Faction
</div>
}
@if (Entity.Tier() != null) {
@if (Entity.Tier() != null)
{
<div>
<b>Tier:</b> @Entity.Tier().Tier
</div>
}
</div>
@if (Entity.Hotkey() != null) {
@if (Entity.Hotkey() != null)
{
<div>
<div>
<b>Hotkey Group:</b> @Entity.Hotkey().HotkeyGroup
@@ -46,34 +50,39 @@
else
{
<EntityDisplayComponent Title="Info">
@if (Entity.Info().Description != "") {
@if (Entity!.Info().Description != "")
{
<div>
<b>Description:</b> @((MarkupString)Entity.Info().Description)
</div>
}
@if (Entity.Info().Notes != "") {
@if (Entity.Info().Notes != "")
{
<div>
<b>Notes:</b> @((MarkupString)Entity.Info().Notes)
</div>
}
<div class="infoDisplayContainer">
<div>
@if (Entity.Faction() != null) {
@if (Entity.Faction() != null)
{
<div>
<b>Faction:</b> @Entity.Faction().Faction
</div>
}
@if (Entity.Tier() != null) {
@if (Entity.Tier() != null)
{
<div>
<b>Tier:</b> @Entity.Tier().Tier
</div>
}
</div>
@if (Entity.Hotkey() != null) {
@if (Entity.Hotkey() != null)
{
<div>
<div>
<b>Hotkey Group:</b> @Entity.Hotkey().HotkeyGroup
@@ -101,7 +110,7 @@ else
gap: 4px;
}
}
</style>
</style>
}
@@ -109,7 +118,7 @@ else
@code {
[CascadingParameter]
public EntityModel? Entity { get; set; }
public EntityModel? Entity { get; set; } = default!;
[CascadingParameter]
public string StyleType { get; set; } = "Detailed";
@@ -1,7 +1,9 @@
@if (Entity.Mechanics().Count > 0) {
@if (Entity!.Mechanics().Count > 0)
{
<EntityDisplayComponent Title="Mechanics">
<div>
@foreach (var data in Entity.Mechanics()) {
@foreach (var data in Entity.Mechanics())
{
<div>
<div>
<span>
@@ -22,8 +24,8 @@
@code {
[CascadingParameter]
public EntityModel? Entity { get; set; }
public EntityModel? Entity { get; set; } = default!;
[CascadingParameter]
public string StyleType { get; set; } = "Detailed";
@@ -1,100 +1,106 @@
@if (Entity.IdPassives().Count > 0) {
@if (Entity!.IdPassives().Count > 0)
{
@if (StyleType.Equals("Plain"))
{
@foreach (var idPassive in Entity.IdPassives()) {
@foreach (var idPassive in Entity.IdPassives())
{
var passive = EntityModel.Get(idPassive.Id);
var info = passive.Info();
var production = passive.Production();
<div>
<div>
<b>Name:</b> @info.Name
<b>Name:</b> @info.Name
</div>
<div>
<b>- Description:</b> @((MarkupString)info.Description)
</div>
@if (!info.Notes.Trim().Equals("")) {
@if (!info.Notes.Trim().Equals(""))
{
<div>
<b>- Description:</b> @((MarkupString)info.Notes)
</div>
</div>
}
</div>
@if (production != null) {
@if (production != null)
{
<div>
@if (production.Pyre != 0) {
@if (production.Pyre != 0)
{
<div>
<b>- Pyre:</b> @production.Pyre
</div>
</div>
}
@if (production.Cooldown != 0) {
@if (production.Cooldown != 0)
{
<div>
<b>- Cooldown:</b> @production.Cooldown.ToString()s
</div>
</div>
}
</div>
}
}
}
else
{
<EntityDisplayComponent Title="Passives">
@foreach (var idPassive in Entity.IdPassives()) {
@foreach (var idPassive in Entity.IdPassives())
{
var passive = EntityModel.Get(idPassive.Id);
var info = passive.Info();
var production = passive.Production();
<div>
<div>
<b>Name:</b> <EntityLabelComponent EntityId="@passive.DataType"/>
<b>Name:</b> <EntityLabelComponent EntityId="@passive.DataType"/>
</div>
<div>
<b>Description:</b> @((MarkupString)info.Description)
</div>
@if (!info.Notes.Trim().Equals("")) {
@if (!info.Notes.Trim().Equals(""))
{
<div>
<b>Description:</b> @((MarkupString)info.Notes)
</div>
</div>
}
</div>
@if (production != null) {
@if (production != null)
{
<div>
@if (production.Pyre != 0) {
@if (production.Pyre != 0)
{
<div>
<b>Pyre:</b> @production.Pyre
</div>
</div>
}
@if (production.Cooldown != 0) {
@if (production.Cooldown != 0)
{
<div>
<b>Cooldown:</b> @production.Cooldown.ToString()s
</div>
</div>
}
</div>
}
}
</EntityDisplayComponent>
</EntityDisplayComponent>
}
}
@code {
[CascadingParameter]
public EntityModel? Entity { get; set; }
public EntityModel? Entity { get; set; } = default!;
[CascadingParameter]
public string StyleType { get; set; } = "Detailed";
@@ -1,87 +1,99 @@
@if (Production != null || Supply != null || Requirements.Count > 0) {
@if (Production != null || Supply != null || Requirements.Count > 0)
{
@if (StyleType.Equals("Plain"))
{
@if (Requirements.Count() > 0) {
@if (Requirements.Count() > 0)
{
<div>
@foreach (var requirement in Requirements)
{
var replaced = DATA.Get()[requirement.DataType];
<div>
@foreach (var requirement in Requirements)
{
var replaced = DATA.Get()[requirement.DataType];
<div>
<span>
<b>@requirement.Requirement.Replace("_", " "):</b> @replaced.Info().Name
</span>
</div>
}
<span>
<b>@requirement.Requirement.Replace("_", " "):</b> @replaced.Info().Name
</span>
</div>
}
</div>
}
@if (Production != null && (!Production.Alloy.Equals(0)
|| !Production.Ether.Equals(0)
|| !Production.BuildTime.Equals(0)
|| !Production.Cooldown.Equals(0)))
{
<div>
@if (!Production.Alloy.Equals(0))
{
<div>
<b>Alloy:</b> @Production.Alloy
</div>
}
@if (!Production.Ether.Equals(0))
{
<div>
<b>Ether:</b> @Production.Ether
</div>
}
@if (!Production.Pyre.Equals(0))
{
<div>
<b>Pyre:</b> @Production.Pyre
</div>
}
@if (Production != null && (!Production.Alloy.Equals(0)
|| !Production.Ether.Equals(0)
|| !Production.BuildTime.Equals(0)
|| !Production.Cooldown.Equals(0))) {
<div>
@if (!Production.Alloy.Equals(0)) {
<div>
<b>Alloy:</b> @Production.Alloy
</div>
}
@if (!Production.Ether.Equals(0)) {
<div>
<b>Ether:</b> @Production.Ether
</div>
}
@if (!Production.Pyre.Equals(0)) {
<div>
<b>Pyre:</b> @Production.Pyre
</div>
}
@if (!Production.BuildTime.Equals(0)) {
<div>
<b>Build Time:</b> @Production.BuildTime.ToString()s
</div>
}
@if (!Production.Energy.Equals(0)) {
<div>
<b>Energy:</b> @Production.Energy
</div>
}
@if (!Production.Cooldown.Equals(0)) {
<div>
<b>Cooldown:</b> @Production.Cooldown.ToString()s
</div>
}
</div>
}
@if (Supply != null) {
@if (!Production.BuildTime.Equals(0))
{
<div>
@if (!Supply.Grants.Equals(0)) {
<div>
<b>Grants:</b> @Supply.Grants
</div>
}
@if (!Supply.Takes.Equals(0)) {
<div>
<b>Takes:</b> @Supply.Takes Supply
</div>
}
<b>Build Time:</b> @Production.BuildTime.ToString()s
</div>
}
@if (!Production.Energy.Equals(0))
{
<div>
<b>Energy:</b> @Production.Energy
</div>
}
@if (!Production.Cooldown.Equals(0))
{
<div>
<b>Cooldown:</b> @Production.Cooldown.ToString()s
</div>
}
</div>
}
@if (Supply != null)
{
<div>
@if (!Supply.Grants.Equals(0))
{
<div>
<b>Grants:</b> @Supply.Grants
</div>
}
@if (!Supply.Takes.Equals(0))
{
<div>
<b>Takes:</b> @Supply.Takes Supply
</div>
}
</div>
}
}
else
{
<EntityDisplayComponent Title="Production">
<div class="ProductionContainer">
@if (Requirements.Count() > 0) {
@if (Requirements.Count() > 0)
{
<div>
@foreach (var requirement in Requirements) {
@foreach (var requirement in Requirements)
{
<div>
<span>
@@ -95,52 +107,62 @@
@if (Production != null && (!Production.Alloy.Equals(0)
|| !Production.Ether.Equals(0)
|| !Production.BuildTime.Equals(0)
|| !Production.Cooldown.Equals(0))) {
<div>
@if (!Production.Alloy.Equals(0)) {
<div>
<b>Alloy:</b> @Production.Alloy
</div>
}
@if (!Production.Ether.Equals(0)) {
<div>
<b>Ether:</b> @Production.Ether
</div>
}
@if (!Production.Pyre.Equals(0)) {
<div>
<b>Pyre:</b> @Production.Pyre
</div>
}
@if (!Production.BuildTime.Equals(0)) {
<div>
<b>Build Time:</b> @Production.BuildTime.ToString()s
</div>
}
@if (!Production.Energy.Equals(0)) {
<div>
<b>Energy:</b> @Production.Energy
</div>
}
@if (!Production.Cooldown.Equals(0)) {
<div>
<b>Cooldown:</b> @Production.Cooldown.ToString()s
</div>
}
</div>
}
@if (Supply != null) {
|| !Production.Cooldown.Equals(0)))
{
<div>
@if (!Supply.Grants.Equals(0)) {
@if (!Production.Alloy.Equals(0))
{
<div>
<b>Alloy:</b> @Production.Alloy
</div>
}
@if (!Production.Ether.Equals(0))
{
<div>
<b>Ether:</b> @Production.Ether
</div>
}
@if (!Production.Pyre.Equals(0))
{
<div>
<b>Pyre:</b> @Production.Pyre
</div>
}
@if (!Production.BuildTime.Equals(0))
{
<div>
<b>Build Time:</b> @Production.BuildTime.ToString()s
</div>
}
@if (!Production.Energy.Equals(0))
{
<div>
<b>Energy:</b> @Production.Energy
</div>
}
@if (!Production.Cooldown.Equals(0))
{
<div>
<b>Cooldown:</b> @Production.Cooldown.ToString()s
</div>
}
</div>
}
@if (Supply != null)
{
<div>
@if (!Supply.Grants.Equals(0))
{
<div>
<b>Grants:</b> @Supply.Grants
</div>
}
@if (!Supply.Takes.Equals(0)) {
@if (!Supply.Takes.Equals(0))
{
<div>
<b>Takes:</b> @Supply.Takes Supply
</div>
@@ -149,8 +171,8 @@
}
</div>
</EntityDisplayComponent>
<style>
.ProductionContainer {
display: flex;
@@ -164,7 +186,6 @@
}
}
</style>
}
}
@@ -173,14 +194,14 @@
[CascadingParameter]
public EntityModel? Entity { get; set; }
[CascadingParameter]
public string StyleType { get; set; } = "Detailed";
private EntityProductionModel Production => Entity.Production();
private List<EntityRequirementModel> Requirements => Entity.Requirements();
private EntitySupplyModel Supply => Entity.Supply();
private EntityProductionModel Production => Entity!.Production();
private List<EntityRequirementModel> Requirements => Entity!.Requirements();
private EntitySupplyModel Supply => Entity!.Supply();
protected override void OnParametersSet()
@@ -1,8 +1,9 @@
@if (Entity.IdPyreSpells().Count > 0)
@if (Entity!.IdPyreSpells().Count > 0)
{
@if (StyleType.Equals("Plain"))
{
@foreach (var pyreSpell in Entity.IdPyreSpells()) {
@foreach (var pyreSpell in Entity.IdPyreSpells())
{
var spell = EntityModel.Get(pyreSpell.Id);
var info = spell.Info();
@@ -16,16 +17,20 @@
<b>- Description:</b> @((MarkupString)info.Description)
</div>
<div>
@if (production != null) {
if (production.Pyre != 0) {
@if (production != null)
{
if (production.Pyre != 0)
{
<b>- Pyre: </b>
@production.Pyre
}
if (production.BuildTime != 0) {
if (production.BuildTime != 0)
{
<b>- BuildTime: </b>
@production.BuildTime
}
if (production.Cooldown != 0) {
if (production.Cooldown != 0)
{
<b>- Cooldown: </b>
@production.Cooldown
}
@@ -33,12 +38,12 @@
</div>
</div>
}
}
else
{
<EntityDisplayComponent Title="Pyre Spells">
@foreach (var pyreSpell in Entity.IdPyreSpells()) {
@foreach (var pyreSpell in Entity.IdPyreSpells())
{
var spell = EntityModel.Get(pyreSpell.Id);
var info = spell.Info();
@@ -52,16 +57,20 @@
<b>Description:</b> @((MarkupString)info.Description)
</div>
<div>
@if (production != null) {
if (production.Pyre != 0) {
@if (production != null)
{
if (production.Pyre != 0)
{
<b> Pyre: </b>
@production.Pyre
}
if (production.BuildTime != 0) {
if (production.BuildTime != 0)
{
<b> BuildTime: </b>
@production.BuildTime
}
if (production.Cooldown != 0) {
if (production.Cooldown != 0)
{
<b> Cooldown: </b>
@production.Cooldown
}
@@ -70,7 +79,6 @@
</div>
}
</EntityDisplayComponent>
}
}
@@ -78,9 +86,9 @@
@code {
[CascadingParameter]
public EntityModel? Entity { get; set; }
public EntityModel? Entity { get; set; } = default!;
[CascadingParameter]
public string StyleType { get; set; } = "Detailed";
@@ -1,97 +1,112 @@
@if (Vitality != null || Movement != null) {
@if (Vitality != null || Movement != null)
{
@if (StyleType.Equals("Plain"))
{
@if (Vitality != null) {
@if (Vitality != null)
{
<div>
@if (!Vitality.DefenseLayer.Equals(0))
{
<div>
@if (!Vitality.DefenseLayer.Equals(0)) {
<div>
<b>Shield:</b> @Vitality.DefenseLayer
</div>
}
@if (!Vitality.Health.Equals(0)) {
<div>
<b>Health:</b> @Vitality.Health
</div>
}
@if (!Vitality.Energy.Equals(0)) {
<div>
<b>Energy:</b> @Vitality.Energy
</div>
}
@if (Vitality.Armor != "") {
<div>
<b>Armor:</b> @Vitality.Armor
</div>
}
@if (Vitality.IsEtheric) {
<div>
<b> + Etheric</b>
</div>
}
@if (Vitality.IsStructure) {
<div>
<b> + Structure</b>
</div>
}
<b>Shield:</b> @Vitality.DefenseLayer
</div>
}
@if (!Vitality.Health.Equals(0))
{
<div>
<b>Health:</b> @Vitality.Health
</div>
}
@if (!Vitality.Energy.Equals(0))
{
<div>
<b>Energy:</b> @Vitality.Energy
</div>
}
@if (Vitality.Armor != "")
{
<div>
<b>Armor:</b> @Vitality.Armor
</div>
}
@if (Movement != null) {
@if (Vitality.IsEtheric)
{
<div>
@if (!Movement.Speed.Equals(0)) {
<div>
<b>Speed:</b> @Movement.Speed
</div>
}
else {
<div>
<b>Speed:</b> Immobile
</div>
}
<div>
<b>Move Type:</b> @Movement.Movement
</div>
<b> + Etheric</b>
</div>
}
@if (Vitality.IsStructure)
{
<div>
<b> + Structure</b>
</div>
}
</div>
}
@if (Movement != null)
{
<div>
@if (!Movement.Speed.Equals(0))
{
<div>
<b>Speed:</b> @Movement.Speed
</div>
}
else
{
<div>
<b>Speed:</b> Immobile
</div>
}
<div>
<b>Move Type:</b> @Movement.Movement
</div>
</div>
}
}
else
{
<EntityDisplayComponent Title="Stats">
<div class="statContainer">
@if (Vitality != null) {
@if (Vitality != null)
{
<div>
@if (!Vitality.DefenseLayer.Equals(0)) {
@if (!Vitality.DefenseLayer.Equals(0))
{
<div>
<b>Shield:</b> @Vitality.DefenseLayer
</div>
}
@if (!Vitality.Health.Equals(0)) {
@if (!Vitality.Health.Equals(0))
{
<div>
<b>Health:</b> @Vitality.Health
</div>
}
@if (!Vitality.Energy.Equals(0)) {
@if (!Vitality.Energy.Equals(0))
{
<div>
<b>Energy:</b> @Vitality.Energy
</div>
}
@if (Vitality.Armor != "") {
@if (Vitality.Armor != "")
{
<div>
<b>Armor:</b> @Vitality.Armor
</div>
}
@if (Vitality.IsEtheric) {
@if (Vitality.IsEtheric)
{
<div>
<b> + Etheric</b>
</div>
}
@if (Vitality.IsStructure) {
@if (Vitality.IsStructure)
{
<div>
<b> + Structure</b>
</div>
@@ -100,14 +115,17 @@
}
@if (Movement != null) {
@if (Movement != null)
{
<div>
@if (!Movement.Speed.Equals(0)) {
@if (!Movement.Speed.Equals(0))
{
<div>
<b>Speed:</b> @Movement.Speed
</div>
}
else {
else
{
<div>
<b>Speed:</b> Immobile
</div>
@@ -132,21 +150,20 @@
}
}
</style>
}
}
@code {
[CascadingParameter]
public EntityModel? Entity { get; set; }
[CascadingParameter]
public EntityModel? Entity { get; set; } = default!;
[CascadingParameter]
public string StyleType { get; set; } = "Detailed";
private EntityVitalityModel Vitality => Entity.Vitality();
private EntityMovementModel Movement => Entity.Movement();
private EntityVitalityModel Vitality => Entity!.Vitality();
private EntityMovementModel Movement => Entity!.Movement();
}
@@ -1,7 +1,9 @@
@if (Entity.IdUpgrades().Count > 0) {
@if (Entity!.IdUpgrades().Count > 0)
{
@if (StyleType.Equals("Plain"))
{
@foreach (var upgradeId in Entity.IdUpgrades()) {
@foreach (var upgradeId in Entity.IdUpgrades())
{
var entity = EntityModel.Get(upgradeId.Id);
<div>
<div>
@@ -12,13 +14,13 @@
</div>
</div>
}
}
else
{
<EntityDisplayComponent Title="Upgrades">
<div class="upgradesContainer">
@foreach (var upgradeId in Entity.IdUpgrades()) {
@foreach (var upgradeId in Entity.IdUpgrades())
{
var entity = EntityModel.Get(upgradeId.Id);
<div>
<div>
@@ -30,9 +32,9 @@
</div>
}
</div>
</EntityDisplayComponent>
</EntityDisplayComponent>
<style>
.upgradesContainer {
display: flex;
@@ -47,16 +49,15 @@
}
</style>
}
}
@code {
[CascadingParameter]
public EntityModel? Entity { get; set; }
public EntityModel? Entity { get; set; } = default!;
[CascadingParameter]
public string StyleType { get; set; } = "Detailed";
@@ -1,17 +1,19 @@
@if (Vanguard != null) {
@if (Vanguard != null)
{
var immortalId = Vanguard.ImmortalId;
var immortal = DATA.Get()[immortalId];
var replaced = DATA.Get()[Vanguard.ReplaceId];
@if (StyleType.Equals("Plain"))
{
<div>
<b>Immortal:</b> @immortal.Info().Name
</div>
@if (!Vanguard.ReplaceId.Equals("")) {
@if (!Vanguard.ReplaceId.Equals(""))
{
<div>
<b>Replaces:</b> @replaced.Info().Name
<b>Replaces:</b> @replaced.Info().Name
</div>
}
}
@@ -22,25 +24,27 @@
<div>
<b>Immortal:</b> <EntityLabelComponent EntityId="@immortal.DataType"/>
</div>
@if (!Vanguard.ReplaceId.Equals("")) {
@if (!Vanguard.ReplaceId.Equals(""))
{
<div>
<b>Replaces:</b> <EntityLabelComponent EntityId="@Vanguard.ReplaceId"></EntityLabelComponent>
<b>Replaces:</b> <EntityLabelComponent EntityId="@Vanguard.ReplaceId"></EntityLabelComponent>
</div>
}
</div>
</EntityDisplayComponent>
</EntityDisplayComponent>
}
}
@code {
[CascadingParameter]
public EntityModel? Entity { get; set; }
public EntityModel? Entity { get; set; } = default!;
private EntityVanguardAddedModel? Vanguard => Entity?.VanguardAdded();
[CascadingParameter]
public string StyleType { get; set; } = "Detailed";
}
@@ -1,7 +1,9 @@
@if (Entity.IdVanguards().Count > 0) {
@if (Entity!.IdVanguards().Count > 0)
{
@if (StyleType.Equals("Plain"))
{
@foreach (var data in Entity.IdVanguards()) {
@foreach (var data in Entity.IdVanguards())
{
var entity = EntityModel.Get(data.Id);
var requirements = entity.Requirements();
@@ -9,7 +11,7 @@
var replaced = DATA.Get()[vanguardAdded.ReplaceId];
var immortal = DATA.Get()[vanguardAdded.ImmortalId];
var productionBuilding = (from building in requirements
where building.Requirement == RequirementType.Production_Building
select building).First().DataType;
@@ -22,7 +24,7 @@
<b>- Replaces:</b> @replaced.Info().Name
</div>
<div>
<b>- Built From:</b> @immortal.Info().Name
<b>- Built From:</b> @immortal.Info().Name
</div>
</div>
}
@@ -30,7 +32,8 @@
else
{
<EntityDisplayComponent Title="Vanguards">
@foreach (var data in Entity.IdVanguards()) {
@foreach (var data in Entity.IdVanguards())
{
var entity = EntityModel.Get(data.Id);
var requirements = entity.Requirements();
@@ -44,7 +47,7 @@
<b>Name:</b> <EntityLabelComponent EntityId="@entity.DataType"/>
</div>
<div>
<b>Replaces:</b> <EntityLabelComponent EntityId="@vanguard.ReplaceId"/>
<b>Replaces:</b> <EntityLabelComponent EntityId="@vanguard.ReplaceId"/>
</div>
<div>
<b>Built From:</b> <EntityLabelComponent EntityId="@productionBuilding"/>
@@ -52,17 +55,15 @@
</div>
}
</EntityDisplayComponent>
}
}
@code {
[CascadingParameter]
public EntityModel? Entity { get; set; }
public EntityModel? Entity { get; set; } = default!;
[CascadingParameter]
public string StyleType { get; set; } = "Detailed";
@@ -1,205 +1,204 @@
@if (Entity.Weapons().Count > 0)
@if (Entity!.Weapons().Count > 0)
{
@if (StyleType.Equals("Plain"))
{
int index = 0;
var index = 0;
foreach (var data in Entity.Weapons())
{
index++;
<div>
<div>
<div class="damageContainer">
<div>
<b>Weapon @index</b>
</div>
<div>
<b>- Damage:</b> @data.Damage
</div>
@if (data.LightDamage != 0)
{
<div class="alternateDamage">
<i>- vs Light: @data.LightDamage</i>&nbsp;
</div>
}
@if (data.MediumDamage != 0)
{
<div class="alternateDamage">
<i>- vs Medium: @data.MediumDamage</i>&nbsp;
</div>
}
@if (data.HeavyDamage != 0)
{
<div class="alternateDamage">
<i>- vs Heavy: @data.HeavyDamage</i>&nbsp;
</div>
}
@if (data.EthericDamageBonus != 0)
{
<div class="alternateDamage">
<i>- vs Etheric +@data.EthericDamageBonus</i>&nbsp;
</div>
}
@if (data.StructureDamageBonus != 0)
{
<div class="alternateDamage">
<i>- vs Structure: +@data.StructureDamageBonus</i>&nbsp;
</div>
}
</div>
</div>
<div>
<b>- Range:</b> @data.Range
</div>
@if (data.SecondsBetweenAttacks > 0)
{
<div>
<b>- AttacksPerSecond:</b> @(1 / data.SecondsBetweenAttacks)
</div>
<div>
- (or <b>SecondsBetweenAttacks:</b> @data.SecondsBetweenAttacks)
</div>
}
else if (data.AttacksPerSecond > 0)
{
<div>
<b>- AttacksPerSecond:</b> @data.AttacksPerSecond
</div>
<div>
- (or <b>SecondsBetweenAttacks:</b> @(1 / data.AttacksPerSecond))
</div>
}
<div>
<b>- Targets:</b> @data.Targets
</div>
@if (data.AttacksPerSecond != 0)
{
<span>
<b>- DPS:</b> @(Math.Round(data.Damage * data.AttacksPerSecond))&nbsp;
</span>
<div>
<div>
<div class="damageContainer">
<div>
<b>Weapon @index</b>
</div>
<div>
<b>- Damage:</b> @data.Damage
</div>
@if (data.LightDamage != 0)
{
<span>
<i>- Light DPS: @(Math.Round(data.LightDamage * data.AttacksPerSecond))</i>&nbsp;
</span>
<div class="alternateDamage">
<i>- vs Light: @data.LightDamage</i>&nbsp;
</div>
}
@if (data.MediumDamage != 0)
{
<span>
<i>- Medium DPS: @(Math.Round(data.MediumDamage * data.AttacksPerSecond))</i>&nbsp;
</span>
<div class="alternateDamage">
<i>- vs Medium: @data.MediumDamage</i>&nbsp;
</div>
}
@if (data.HeavyDamage != 0)
{
<span>
<i>- Heavy DPS: @(Math.Round(data.HeavyDamage * data.AttacksPerSecond))</i>&nbsp;
</span>
<div class="alternateDamage">
<i>- vs Heavy: @data.HeavyDamage</i>&nbsp;
</div>
}
}
@if (data.EthericDamageBonus != 0)
{
<div class="alternateDamage">
<i>- vs Etheric +@data.EthericDamageBonus</i>&nbsp;
</div>
}
@if (data.StructureDamageBonus != 0)
{
<div class="alternateDamage">
<i>- vs Structure: +@data.StructureDamageBonus</i>&nbsp;
</div>
}
</div>
</div>
}
<div>
<b>- Range:</b> @data.Range
</div>
@if (data.SecondsBetweenAttacks > 0)
{
<div>
<b>- AttacksPerSecond:</b> @(1 / data.SecondsBetweenAttacks)
</div>
<div>
- (or <b>SecondsBetweenAttacks:</b> @data.SecondsBetweenAttacks)
</div>
}
else if (data.AttacksPerSecond > 0)
{
<div>
<b>- AttacksPerSecond:</b> @data.AttacksPerSecond
</div>
<div>
- (or <b>SecondsBetweenAttacks:</b> @(1 / data.AttacksPerSecond))
</div>
}
<div>
<b>- Targets:</b> @data.Targets
</div>
@if (data.AttacksPerSecond != 0)
{
<span>
<b>- DPS:</b> @(Math.Round(data.Damage * data.AttacksPerSecond))&nbsp;
</span>
@if (data.LightDamage != 0)
{
<span>
<i>- Light DPS: @(Math.Round(data.LightDamage * data.AttacksPerSecond))</i>&nbsp;
</span>
}
@if (data.MediumDamage != 0)
{
<span>
<i>- Medium DPS: @(Math.Round(data.MediumDamage * data.AttacksPerSecond))</i>&nbsp;
</span>
}
@if (data.HeavyDamage != 0)
{
<span>
<i>- Heavy DPS: @(Math.Round(data.HeavyDamage * data.AttacksPerSecond))</i>&nbsp;
</span>
}
}
</div>
}
}
else
{
<EntityDisplayComponent Title="Weapons">
<div class="weaponsContainer">
@foreach (var data in Entity.Weapons())
{
<div>
<EntityDisplayComponent Title="Weapons">
<div class="weaponsContainer">
@foreach (var data in Entity.Weapons())
{
<div>
<div class="damageContainer">
<div>
<div class="damageContainer">
<div>
<b>Damage:</b> @data.Damage
</div>
@if (data.LightDamage != 0)
{
<div class="alternateDamage">
<i>vs Light: @data.LightDamage</i>&nbsp;
</div>
}
@if (data.MediumDamage != 0)
{
<div class="alternateDamage">
<i>vs Medium: @data.MediumDamage</i>&nbsp;
</div>
}
@if (data.HeavyDamage != 0)
{
<div class="alternateDamage">
<i>vs Heavy: @data.HeavyDamage</i>&nbsp;
</div>
}
@if (data.EthericDamageBonus != 0)
{
<div class="alternateDamage">
<i>vs Etheric +@data.EthericDamageBonus</i>&nbsp;
</div>
}
@if (data.StructureDamageBonus != 0)
{
<div class="alternateDamage">
<i>vs Structure: +@data.StructureDamageBonus</i>&nbsp;
</div>
}
</div>
</div>
<div>
<b>Range:</b> @data.Range
</div>
@if (data.SecondsBetweenAttacks > 0)
{
<div>
<b>Damage:</b> @data.Damage
<b>AttacksPerSecond:</b> @(1 / data.SecondsBetweenAttacks)
</div>
<div>
(or <b>SecondsBetweenAttacks:</b> @data.SecondsBetweenAttacks)
</div>
}
else if (data.AttacksPerSecond > 0)
{
<div>
<b>AttacksPerSecond:</b> @data.AttacksPerSecond
</div>
<div>
(or <b>SecondsBetweenAttacks:</b> @(1 / data.AttacksPerSecond))
</div>
}
<div>
<b>Targets:</b> @data.Targets
</div>
@if (data.AttacksPerSecond != 0)
{
<div>
<b>DPS:</b> @(Math.Round(data.Damage * data.AttacksPerSecond))&nbsp;
</div>
@if (data.LightDamage != 0)
{
<div class="alternateDamage">
<i>vs Light: @data.LightDamage</i>&nbsp;
<div>
<i>Light DPS: @(Math.Round(data.LightDamage * data.AttacksPerSecond))</i>&nbsp;
</div>
}
@if (data.MediumDamage != 0)
{
<div class="alternateDamage">
<i>vs Medium: @data.MediumDamage</i>&nbsp;
<div>
<i>Medium DPS: @(Math.Round(data.MediumDamage * data.AttacksPerSecond))</i>&nbsp;
</div>
}
@if (data.HeavyDamage != 0)
{
<div class="alternateDamage">
<i>vs Heavy: @data.HeavyDamage</i>&nbsp;
<div>
<i>Heavy DPS: @(Math.Round(data.HeavyDamage * data.AttacksPerSecond))</i>&nbsp;
</div>
}
@if (data.EthericDamageBonus != 0)
{
<div class="alternateDamage">
<i>vs Etheric +@data.EthericDamageBonus</i>&nbsp;
</div>
}
@if (data.StructureDamageBonus != 0)
{
<div class="alternateDamage">
<i>vs Structure: +@data.StructureDamageBonus</i>&nbsp;
</div>
}
</div>
</div>
<div>
<b>Range:</b> @data.Range
</div>
@if (data.SecondsBetweenAttacks > 0)
{
<div>
<b>AttacksPerSecond:</b> @(1 / data.SecondsBetweenAttacks)
</div>
<div>
(or <b>SecondsBetweenAttacks:</b> @data.SecondsBetweenAttacks)
</div>
}
else if (data.AttacksPerSecond > 0)
{
<div>
<b>AttacksPerSecond:</b> @data.AttacksPerSecond
</div>
<div>
(or <b>SecondsBetweenAttacks:</b> @(1 / data.AttacksPerSecond))
</div>
}
<div>
<b>Targets:</b> @data.Targets
</div>
@if (data.AttacksPerSecond != 0)
{
<div>
<b>DPS:</b> @(Math.Round(data.Damage * data.AttacksPerSecond))&nbsp;
</div>
@if (data.LightDamage != 0)
{
<div>
<i>Light DPS: @(Math.Round(data.LightDamage * data.AttacksPerSecond))</i>&nbsp;
</div>
}
@if (data.MediumDamage != 0)
{
<div>
<i>Medium DPS: @(Math.Round(data.MediumDamage * data.AttacksPerSecond))</i>&nbsp;
</div>
}
@if (data.HeavyDamage != 0)
{
<div>
<i>Heavy DPS: @(Math.Round(data.HeavyDamage * data.AttacksPerSecond))</i>&nbsp;
</div>
}
}
</div>
}
</div>
</EntityDisplayComponent>
</div>
}
</div>
</EntityDisplayComponent>
<style>
.weaponsContainer {
@@ -222,16 +221,15 @@
margin-bottom: 6px;
}
</style>
}
}
}
@code {
[CascadingParameter]
public EntityModel? Entity { get; set; }
public EntityModel? Entity { get; set; } = default!;
[CascadingParameter]
public string StyleType { get; set; } = "Detailed";
@@ -2,23 +2,27 @@
<div class="desktopFiltersContainer">
<div class="filtersContainer">
<div class="filterContainer">
@foreach (var choice in EntityFilterService.GetFactionChoices()) {
@foreach (var choice in EntityFilterService.GetFactionChoices())
{
var styleClass = "";
if (choice.Equals(EntityFilterService.GetFactionType())) {
if (choice.Equals(EntityFilterService.GetFactionType()))
{
styleClass = "selected";
}
<button @onclick="@(e => OnChangeFaction(choice))" class="choiceButton @styleClass">@choice</button>
}
</div>
@if (EntityFilterService.GetFactionType() != "Any" && EntityFilterService.GetFactionType() != "None") {
@if (EntityFilterService.GetFactionType() != "Any" && EntityFilterService.GetFactionType() != "None")
{
<div class="filterContainer">
@foreach (var choice in EntityFilterService.GetImmortalChoices())
{
var name = DATA.Get()[choice].Info().Name;
var styleClass = "";
if (choice.Equals(EntityFilterService.GetImmortalType())) {
if (choice.Equals(EntityFilterService.GetImmortalType()))
{
styleClass = "selected";
}
<button class="choiceButton @styleClass" @onclick="@(e => OnChangeImmortal(choice))">@name</button>
@@ -27,16 +31,18 @@
}
</div>
<div class="filterContainer">
@foreach (var choice in EntityFilterService.GetEntityChoices()) {
@foreach (var choice in EntityFilterService.GetEntityChoices())
{
var styleClass = "";
if (choice.Equals(EntityFilterService.GetEntityType())) {
if (choice.Equals(EntityFilterService.GetEntityType()))
{
styleClass = "selected";
}
<button class="choiceButton @styleClass" @onclick="@(e => OnChangeEntity(choice))">@choice.Replace("_", " ")</button>
}
</div>
<FormTextComponent Label="Search Label" Placeholder="Throne..." OnChange="@(e => EntityFilterService.EnterSearchText(e.Value.ToString()))"/>
<FormTextComponent Label="Search Label" Placeholder="Throne..." OnChange="@(e => EntityFilterService.EnterSearchText(e.Value!.ToString()!))"/>
</div>
</div>
@@ -199,40 +205,49 @@
@code {
[Inject]
public IEntityFilterService EntityFilterService { get; set; }
public IEntityFilterService EntityFilterService { get; set; } = default!;
protected override void OnInitialized() { }
protected override void OnInitialized()
{
}
void OnChangeFaction(string clickedFaction) {
void OnChangeFaction(string clickedFaction)
{
EntityFilterService.SelectFactionType(clickedFaction);
StateHasChanged();
}
void OnChangeImmortal(string clickedImmortal) {
void OnChangeImmortal(string clickedImmortal)
{
EntityFilterService.SelectImmortalType(clickedImmortal);
}
void OnChangeEntity(string clickedEntity) {
void OnChangeEntity(string clickedEntity)
{
EntityFilterService.SelectEntityType(clickedEntity);
}
void OnFactionChanged(ChangeEventArgs e) {
EntityFilterService.SelectFactionType(e.Value.ToString());
void OnFactionChanged(ChangeEventArgs e)
{
EntityFilterService.SelectFactionType(e.Value!.ToString()!);
}
void OnImmortalChanged(ChangeEventArgs e) {
EntityFilterService.SelectImmortalType(e.Value.ToString());
void OnImmortalChanged(ChangeEventArgs e)
{
EntityFilterService.SelectImmortalType(e.Value!.ToString()!);
}
void OnEntityChanged(ChangeEventArgs e) {
EntityFilterService.SelectEntityType(e.Value.ToString());
void OnEntityChanged(ChangeEventArgs e)
{
EntityFilterService.SelectEntityType(e.Value!.ToString()!);
}
void OnSearchTextChanged(ChangeEventArgs e) {
EntityFilterService.EnterSearchText(e.Value.ToString());
void OnSearchTextChanged(ChangeEventArgs e)
{
EntityFilterService.EnterSearchText(e.Value!.ToString()!);
}
}
@@ -0,0 +1,115 @@
@layout PageLayout
@inject IDocumentationService documentationService
@implements IDisposable
@page "/docs"
@if (!documentationService.IsLoaded())
{
<LoadingComponent/>
}
else
{
<LayoutMediumContentComponent>
<PaperComponent>
@foreach (var docSection in documentationService.DocSectionModels)
{
<div class="docSectionContainer">
<div class="docSectionTitle">@docSection.Name</div>
<div class="docContentContainer">
@foreach (var docContent in docSection.DocumentationModels)
{
<NavLink class="docContentLink" href="@docContent.GetDocLink()">
<div class="docContentName">@docContent.Name</div>
<div class="docContentDescription">@docContent.Description</div>
</NavLink>
}
</div>
</div>
}
</PaperComponent>
</LayoutMediumContentComponent>
}
<style>
.docSectionContainer {
width: 100%;
padding: 8px;
}
.docSectionTitle {
font-size: 3rem;
font-weight: bold;
text-align: center;
margin-bottom: 32px;
}
.docContentContainer {
display: grid;
gap: 12px;
grid-template-columns: 1fr 1fr;
}
@@media only screen and (max-width: 1025px) {
.docContentContainer {
grid-template-columns: 1fr;
}
}
.docContentName {
font-weight: bold;
font-size: 1.6rem;
}
.docContentDescription {
font-weight: normal;
}
.docContentLink {
background-color: var(--paper);
border: 1px solid var(--paper-border);
border-radius: 2px;
padding-left: 12px;
padding-right: 12px;
padding-top: 24px;
padding-bottom: 24px;
color: white;
display: flex;
flex-direction: column;
gap: 12px;
text-align: center;
margin-left: 12px;
margin-right: 12px;
}
.docContentLink:hover {
background-color: var(--paper-hover);
border-color: var(--paper-border-hover);
text-decoration: none;
box-shadow: 0 4px 6px rgba(0,0,0,0.6);
transform: translateY(-2px) scale(1.01);
}
</style>
@code {
[Parameter]
public string? Text { get; set; }
protected override void OnInitialized()
{
documentationService.Subscribe(StateHasChanged);
documentationService.Load();
}
public void Dispose()
{
documentationService.Unsubscribe(StateHasChanged);
}
}
+46 -68
View File
@@ -1,69 +1,40 @@
@layout PageLayout
@inject IDocumentationService DocumentationService
@using Markdig
@inject IDocumentationService documentationService
@implements IDisposable
@page "/docs/{text?}"
@page "/docs/{href1}/{href2?}/{href3?}/{href4?}/{href5?}"
@if (!DocumentationService.IsLoaded())
@if (!documentationService.IsLoaded())
{
<LoadingComponent></LoadingComponent>
<LoadingComponent/>
}
else
{
<LayoutMediumContentComponent>
<WebsiteTitleComponent>Documentation</WebsiteTitleComponent>
<div class="section">
<div for="docSection">Section: </div>
<div style="flex: 1"></div>
<select @oninput="OnSectionChanged" style="background-color: #36393F; width: 250px; margin-right: 16px;" name="docSection">
<option value="All">All</option>
</select>
</div>
<div class="docsContainer">
@foreach (var doc in DocumentationService.DocumentationModels) {
if (selectedSection != "All" && doc.Section != selectedSection) {
continue;
<LayoutWithSidebarComponent>
<Sidebar>
<DocumentNavComponent
Connections="documentationService.DocConnectionModels"
Documents="documentationService.DocContentModels"/>
</Sidebar>
<Content>
<PaperComponent>
@foreach (var doc in documentationService.DocContentModels)
{
if (!doc.Href.Equals(Href))
{
continue;
}
<DocumentComponent DocContentModel="doc"/>
}
<PaperComponent>
<div style="display: flex; flex-direction: row;">
<span style="font-weight: bold; font-style:italic;">@doc.Section</span>
<div style="flex: 1"></div>
<span style="font-weight: bold; font-style:italic;">Last Updated on @doc.UpdatedDate.ToString("MM/dd/yyyy")</span>
</div>
<div>
<div id="@doc.Id" style="font-weight: bold; font-size: 1.4rem;">@doc.Name</div>
<div>@((MarkupString)Markdown.ToHtml(doc.Description))</div>
</div>
</PaperComponent>
}
</div>
</LayoutMediumContentComponent>
</PaperComponent>
</Content>
</LayoutWithSidebarComponent>
}
<style>
.section {
display: flex;
width: 500px;
flex-direction: row;
background-color: var(--paper);
justify-content: center;
padding: 24px;
border: 4px solid var(--paper-border);
box-shadow: 0px 6px var(--paper-border);
}
.docsContainer {
display: flex;
flex-direction: column;
gap: 16px;
}
<style>
pre code {
color: white;
@@ -121,25 +92,32 @@ else
@code {
[Parameter]
public string? Text { get; set; }
string selectedSection = "All";
public string? Href1 { get; set; }
[Parameter]
public string? Href2 { get; set; }
[Parameter]
public string? Href3 { get; set; }
[Parameter]
public string? Href4 { get; set; }
[Parameter]
public string? Href5 { get; set; }
private string Href => Href5 ?? Href4 ?? Href3 ?? Href2 ?? Href1 ?? "";
protected override void OnInitialized()
{
DocumentationService.Subscribe(StateHasChanged);
DocumentationService.Load();
documentationService.Subscribe(StateHasChanged);
documentationService.Load();
}
public void Dispose()
{
DocumentationService.Unsubscribe(StateHasChanged);
}
void OnSectionChanged(ChangeEventArgs e) {
selectedSection = e.Value.ToString();
StateHasChanged();
documentationService.Unsubscribe(StateHasChanged);
}
}
@@ -0,0 +1,35 @@
<div class="doc">
<div class="docHeader">
<div class="docTitle">@DocContentModel.Name</div>
<div class="docDates">
<div class="docDateUpdated"><b>Updated</b>: @DocContentModel.UpdatedDate.ToString("MM/dd/yyyy")</div>
<div class="docDateCreated"><b>Created</b>: @DocContentModel.CreatedDate.ToString("MM/dd/yyyy")</div>
</div>
</div>
<div class="docContent">@((MarkupString)Markdown.ToHtml(DocContentModel.Content))</div>
</div>
<style>
.docTitle {
font-weight: bold;
}
.docHeader {
display: flex;
justify-content: space-between;
}
.docDates {
display: flex;
flex-direction: column;
}
</style>
@code {
[Parameter]
public DocContentModel DocContentModel { get; set; } = default!;
}
@@ -0,0 +1,70 @@
@if (Document!.DocumentationModels.Count > 0)
{
<div class="docInnerNavContainer">
@foreach (var innerDoc in Document.DocumentationModels)
{
var linkStyle = $"docInnerNavButton inner_{Layers}";
<NavLink class="@linkStyle" href="@innerDoc.GetDocLink()">@innerDoc.Name</NavLink>
<DocumentInnerNavComponent Document="@innerDoc" Layers="@IncrementLayers()"/>
}
</div>
}
<style>
.docInnerNavContainer {
display: flex;
flex-direction: column;
}
.docInnerNavButton a {
color: white;
}
.docInnerNavButton a:hover {
color: white;
}
.docInnerNavButton {
padding: 8px;
margin-left: 8px;
color: white;
}
.inner_1 {
margin-left: 8px;
}
.inner_2 {
margin-left: 16px;
}
.inner_3 {
margin-left: 24px;
}
</style>
@code {
[Parameter]
public DocContentModel? Document { get; set; } = default!;
[Parameter]
public int Layers { get; set; } = 1;
public int IncrementLayers()
{
return Layers + 1;
}
private string GetLink(DocContentModel doc)
{
return $"docs/{doc.Href}";
}
}
@@ -0,0 +1,46 @@
<div class="docNavContainer">
@foreach (var doc in Documents)
{
if (doc.Parent == null)
{
<NavLink class="docNavButton" href="@doc.GetDocLink()">@doc.Name</NavLink>
<DocumentInnerNavComponent Document="@doc"/>
}
}
</div>
<style>
.docNavContainer {
display: flex;
flex-direction: column;
}
.docNavButton a {
color: white;
}
.docNavButton a:hover {
color: white;
}
.docNavButton {
padding: 8px;
color: white;
}
</style>
@code {
[Parameter]
public List<DocContentModel> Documents { get; set; } = default!;
[Parameter]
public List<DocConnectionModel> Connections { get; set; } = default!;
private string GetLink(DocContentModel doc)
{
return $"docs/{doc.Href}";
}
}
+21 -12
View File
@@ -31,19 +31,19 @@
<FormLayoutComponent>
<FormNumberComponent Min="0"
Value="@((int)NumberOfWorkersLostToHarass)"
OnChange="@(e => { NumberOfWorkersLostToHarass = int.Parse(e.Value.ToString()); Calculate();})">
OnChange="@(e => { NumberOfWorkersLostToHarass = int.Parse(e.Value!.ToString()!); Calculate();})">
<FormLabelComponent>Number of workers lost to harass</FormLabelComponent>
</FormNumberComponent>
<FormNumberComponent Min="0"
Value="@((int)NumberOfTownHallsExisting)"
OnChange="@(e => { NumberOfTownHallsExisting = int.Parse(e.Value.ToString()); Calculate();})">
OnChange="@(e => { NumberOfTownHallsExisting = int.Parse(e.Value!.ToString()!); Calculate();})">
<FormLabelComponent>Number of townhalls existing</FormLabelComponent>
</FormNumberComponent>
<FormNumberComponent Min="0"
Value="@((int)TravelTime)"
OnChange="@(e => { TravelTime = int.Parse(e.Value.ToString()); Calculate();})">
OnChange="@(e => { TravelTime = int.Parse(e.Value!.ToString()!); Calculate();})">
<FormLabelComponent>Travel time</FormLabelComponent>
</FormNumberComponent>
@@ -230,42 +230,51 @@
float NumberOfWorkersLostToHarass = 1;
float NumberOfTownHallsExisting = 1;
float SimultaneousProductionFloor() {
if (NumberOfTownHallsExisting <= 0 || NumberOfWorkersLostToHarass <= 0) {
float SimultaneousProductionFloor()
{
if (NumberOfTownHallsExisting <= 0 || NumberOfWorkersLostToHarass <= 0)
{
return 0;
}
return (float)Math.Floor(NumberOfWorkersLostToHarass / Math.Min(NumberOfTownHallsExisting, NumberOfWorkersLostToHarass));
}
float LeftOverWorkersToProduceCount() {
float LeftOverWorkersToProduceCount()
{
return NumberOfWorkersLostToHarass % Math.Min(NumberOfTownHallsExisting, NumberOfWorkersLostToHarass);
}
float WorkerReplacementCost() {
float WorkerReplacementCost()
{
return CostOfWorker * NumberOfWorkersLostToHarass;
}
float DelayedMiningCost() {
float DelayedMiningCost()
{
return TotalAlloyHarassment - WorkerReplacementCost();
}
void Calculate() {
void Calculate()
{
TotalAlloyHarassment = WorkerReplacementCost();
for (var workerProductionIndex = 0; workerProductionIndex < SimultaneousProductionFloor(); workerProductionIndex++) {
for (var workerProductionIndex = 0; workerProductionIndex < SimultaneousProductionFloor(); workerProductionIndex++)
{
TotalAlloyHarassment += AlloyMinedPerSecondByWorker * (TimeToProduceWorker + TravelTime) * (workerProductionIndex + 1);
}
TotalAlloyHarassment += LeftOverWorkersToProduceCount() * (TimeToProduceWorker + TravelTime) * AlloyMinedPerSecondByWorker;
}
protected override void OnInitialized() {
protected override void OnInitialized()
{
Calculate();
}
void ValueChanged(float test) {
void ValueChanged(float test)
{
Calculate();
}
+82
View File
@@ -0,0 +1,82 @@
@layout PageLayout;
@page "/immortal-home"
<LayoutMediumContentComponent>
<PaperComponent>
<div class="mainContainer">
<div class="mainTitle">
Fan Reference
</div>
<div>
Refer to various aspects of "IMMORTAL: Gates of Pyre" from this external reference!
</div>
</div>
</PaperComponent>
<ContentDividerComponent></ContentDividerComponent>
<PaperComponent>
<div class="heroesContainer">
<ContentHighlightComponent
Title="Database"
Description="Review the units!"
Href="/database"
ImageHref="image/hero/Database.png"/>
<ContentHighlightComponent
Title="Build Calculator"
Description="Make a build!"
Href="/build-calculator"
ImageHref="image/hero/Build.png"/>
<ContentHighlightComponent
Title="Notes"
Description="Read some notes!"
Href="/notes"
ImageHref="image/hero/Notes.png"/>
<ContentHighlightComponent
Title="Streams"
Description="Watch live development!"
Href="/streams"
ImageHref="image/hero/Streams.png"/>
</div>
</PaperComponent>
<ContentDividerComponent></ContentDividerComponent>
<AlertComponent>
<Title>Under Construction</Title>
<Message>Website is still being made. Check out <NavLink Href="/immortal-roadmap">Road Map</NavLink> for future plans, <NavLink Href="/immortal-agile">Agile</NavLink> for present tasks, and <NavLink Href="/immortal-changelog">Change Log</NavLink> for past changes.</Message>
</AlertComponent>
</LayoutMediumContentComponent>
<style>
.mainContainer {
padding-bottom: 32px;
}
.mainTitle {
font-size: 2.2rem;
font-weight: bold;
}
.heroesContainer {
display: grid;
gap: 64px;
justify-content: center;
margin: auto;
grid-template-columns: 1fr 1fr;
}
@@media only screen and (max-width: 1025px) {
.heroesContainer {
grid-template-columns: 1fr; }
}
</style>
@@ -0,0 +1,76 @@
<NavLink Href="@Href" class="contentHighlight">
<div class="contentHighlightTitle">
@Title
</div>
<img src="@ImageHref" class="contentHighlightImage" alt="@Title"/>
<div class="contentHighlightCallToAction">
@Description
</div>
</NavLink>
<style>
.contentHighlight {
background-color: var(--paper);
border: 1px solid var(--paper-border);
border-radius: 2px;
padding-left: 12px;
padding-right: 12px;
padding-top: 24px;
padding-bottom: 24px;
color: white;
display: flex;
flex-direction: column;
gap: 12px;
text-align: center;
margin-left: 12px;
margin-right: 12px;
}
.contentHighlight:hover {
background-color: var(--paper-hover);
border-color: var(--paper-border-hover);
text-decoration: none;
box-shadow: 0 4px 6px rgba(0,0,0,0.6);
transform: translateY(-2px) scale(1.01);
}
.contentHighlightTitle {
font-weight: 800;
font-size: 1.3rem;
margin: auto;
}
.contentHighlightImage {
border: 1px solid rgba(0,0,0,0.5);
box-shadow: 2px 2px 2px rgba(0,0,0,0.5);
height: 400px;
width: 400px;
margin: auto;
}
.contentHighlightCallToAction {
font-weight: 700;
font-size: 1.1rem;
margin: auto;
padding: 16px;
}
</style>
@code {
[Parameter]
public string Href { get; set; } = default!;
[Parameter]
public string Title { get; set; } = default!;
[Parameter]
public string Description { get; set; } = default!;
[Parameter]
public string ImageHref { get; set; } = default!;
}
-149
View File
@@ -1,149 +0,0 @@
@layout PageLayout;
@page "/immortal-home"
<LayoutMediumContentComponent>
<div class="mainContainer">
<div class="mainTitle">
Fan Reference
</div>
<div>
Refer to various aspects of "IMMORTAL: Gates of Pyre" from this external reference!
</div>
</div>
<ContentDividerComponent></ContentDividerComponent>
<div class="herosContainer">
<div class="hero">
<div class="heroTitle">
Database
</div>
<img src="image/hero/Database.png" class="heroImage"/>
<NavLink Href="/database" class="heroCallToAction">
Review the units!
</NavLink>
</div>
<div class="hero">
<div class="heroTitle">
Build Calculator
</div>
<img src="image/hero/Build.png" class="heroImage"/>
<NavLink Href="/build-calculator" class="heroCallToAction">
Make a build!
</NavLink>
</div>
<div class="hero">
<div class="heroTitle">
Notes
</div>
<img src="image/hero/Notes.png" class="heroImage"/>
<NavLink Href="/notes" class="heroCallToAction">
Read some notes!
</NavLink>
</div>
<div class="hero">
<div class="heroTitle">
Streams
</div>
<img src="image/hero/Streams.png" class="heroImage"/>
<NavLink Href="/streams" class="heroCallToAction">
Watch live development!
</NavLink>
</div>
</div>
<ContentDividerComponent></ContentDividerComponent>
<AlertComponent>
<Title>Under Construction</Title>
<Message>Website is still being made. Check out <NavLink Href="/immortal-roadmap">Road Map</NavLink> for future plans, <NavLink Href="/immortal-agile">Agile</NavLink> for present tasks, and <NavLink Href="/immortal-changelog">Change Log</NavLink> for past changes.</Message>
</AlertComponent>
</LayoutMediumContentComponent>
<style>
.mainContainer {
padding-bottom: 32px;
}
.mainTitle {
font-size: 2.2rem;
font-weight: bold;
}
.quoteContainer {
display: flex;
flex-direction: column;
gap: 8px;
max-width: 600px;
margin: auto;
}
.quoteTitle {
font-weight: 800;
margin-bottom: 8px;
}
.quoteText {
margin: auto;
font-style: italic;
}
.herosContainer {
display: flex;
flex-wrap: wrap;
gap: 64px;
justify-content: center;
}
.hero {
padding: 32px;
display: flex;
flex-direction: column;
gap: 32px;
}
.heroTitle {
font-weight: 800;
font-size: 1.3rem;
margin: auto;
}
.heroImage {
border: 1px solid rgba(0,0,0,0.5);
box-shadow: 2px 2px 2px rgba(0,0,0,0.5);
height: 400px;
width: 400px;
margin: auto;
}
.heroCallToAction {
font-weight: 700;
font-size: 1.1rem;
margin: auto;
background-color: var(--primary);
border: 1px solid var(--primary);
padding: 16px;
cursor: pointer;
color: white;
}
.heroCallToAction:hover {
background-color: var(--primary-hover);
border-color: var(--primary-border-hover);
}
</style>
+13 -13
View File
@@ -16,60 +16,60 @@
--info: @info;
--info-border: @info_border;
</CodeComponent>
<br />
<br/>
<div class="color accent">
<div>Accent</div>
<div>
Base: <input type="color" value="@accent" @onchange="e => accent = e.Value.ToString()" />
Base: <input type="color" value="@accent" @onchange="e => accent = e.Value!.ToString()!"/>
</div>
</div>
<div class="color primary">
<div>Primary</div>
<div>
Base: <input type="color" value="@primary" @onchange="e => primary = e.Value.ToString()" />
Base: <input type="color" value="@primary" @onchange="e => primary = e.Value!.ToString()!"/>
</div>
<div>
Border: <input type="color" value="@primary_border" @onchange="e => primary_border = e.Value.ToString()" />
Border: <input type="color" value="@primary_border" @onchange="e => primary_border = e.Value!.ToString()!"/>
</div>
<div>
Hover Base: <input type="color" value="@primary_hover" @onchange="e => primary_hover = e.Value.ToString()" />
Hover Base: <input type="color" value="@primary_hover" @onchange="e => primary_hover = e.Value!.ToString()!"/>
</div>
<div>
Hover Border: <input type="color" value="@primary_border_hover" @onchange="e => primary_border_hover = e.Value.ToString()" />
Hover Border: <input type="color" value="@primary_border_hover" @onchange="e => primary_border_hover = e.Value!.ToString()!"/>
</div>
</div>
<div class="color secondary">
<div>Secondary</div>
<div>
Base: <input type="color" value="@secondary" @onchange="e => secondary = e.Value.ToString()" />
Base: <input type="color" value="@secondary" @onchange="e => secondary = e.Value!.ToString()!"/>
</div>
<div>
Hover Base: <input type="color" value="@secondary_hover" @onchange="e => secondary_hover = e.Value.ToString()" />
Hover Base: <input type="color" value="@secondary_hover" @onchange="e => secondary_hover = e.Value!.ToString()!"/>
</div>
<div>
Hover Border: <input type="color" value="@secondary_border_hover" @onchange="e => secondary_border_hover = e.Value.ToString()" />
Hover Border: <input type="color" value="@secondary_border_hover" @onchange="e => secondary_border_hover = e.Value!.ToString()!"/>
</div>
</div>
<div class="color paper">
<div>Paper</div>
<div>
Base: <input type="color" value="@paper" @onchange="e => paper = e.Value.ToString()" />
Base: <input type="color" value="@paper" @onchange="e => paper = e.Value!.ToString()!"/>
</div>
<div>
Border: <input type="color" value="@paper_border" @onchange="e => paper_border = e.Value.ToString()" />
Border: <input type="color" value="@paper_border" @onchange="e => paper_border = e.Value!.ToString()!"/>
</div>
</div>
<div class="color background">
<div>Background</div>
<div>
Base: <input type="color" value="@background" @onchange="e => background = e.Value.ToString()" />
Base: <input type="color" value="@background" @onchange="e => background = e.Value!.ToString()!"/>
</div>
</div>
<div class="color info">
<div>Info</div>
<div>
Base: <input type="color" value="@info" @onchange="e => info = e.Value.ToString()" />
Base: <input type="color" value="@info" @onchange="e => info = e.Value!.ToString()!"/>
</div>
</div>
</div>
@@ -2,7 +2,6 @@
<Title>Dialog</Title>
<Description>...</Description>
<Example>
<DialogComponent></DialogComponent>
</Example>
<Usage>
//TODO
@@ -12,7 +11,6 @@
</Code>
</MakingOfComponent>
@code {
}
@@ -12,7 +12,8 @@
Example Entity Content
</div>
@for (var i = 0; i < 1; i++) {
@for (var i = 0; i < 1; i++)
{
<div>
-@i Example Entity Content
</div>
@@ -27,7 +28,8 @@
Example Entity Content
</div>
@for (var i = 0; i < 2; i++) {
@for (var i = 0; i < 2; i++)
{
<div>
-@i Example Entity Content
</div>
@@ -42,7 +44,8 @@
Example Entity Content
</div>
@for (var i = 0; i < 1; i++) {
@for (var i = 0; i < 1; i++)
{
<div>
-@i Example Entity Content
</div>
@@ -12,7 +12,7 @@
<Example>
<div style="width: 300px; height: 450px;">
<LoadingComponent></LoadingComponent>
<LoadingComponent/>
</div>
</Example>
<Usage>
+26 -14
View File
@@ -7,14 +7,16 @@
<Display>@EntityMemory.Name</Display>
</FormDisplayComponent>
@foreach (var question in questions) {
@foreach (var question in questions)
{
var questionWrong = hasBeenSubmitted && !question.IsRevealed && question.Guess != question.Answer;
<FormGuessComponent IsSubmitted="hasBeenSubmitted"
OnChange="answerEventArgs => OnAnswerEntered(answerEventArgs, question)"
MemoryQuestion="question"/>
@if (questionWrong) {
@if (questionWrong)
{
<div class="wrongAnswer">The correct answer was @question.Answer</div>
}
}
@@ -48,9 +50,9 @@
@code {
[Parameter]
public MemoryEntityModel EntityMemory { get; set; }
public MemoryEntityModel EntityMemory { get; set; } = default!;
private List<MemoryQuestionModel> questions { get; set; }
private List<MemoryQuestionModel> questions { get; set; } = default!;
private bool hasBeenSubmitted = false;
private bool isCorrect = false;
@@ -58,40 +60,49 @@
public int Guess { get; set; }
protected override void OnInitialized() {
protected override void OnInitialized()
{
MemoryTesterService.Subscribe(OnMemoryEvent);
OnRefresh();
}
void IDisposable.Dispose() {
void IDisposable.Dispose()
{
MemoryTesterService.Unsubscribe(OnMemoryEvent);
}
void OnMemoryEvent(MemoryTesterEvent memoryTesterEvent) {
if (memoryTesterEvent == MemoryTesterEvent.OnVerify) {
void OnMemoryEvent(MemoryTesterEvent memoryTesterEvent)
{
if (memoryTesterEvent == MemoryTesterEvent.OnVerify)
{
OnVerify();
}
if (memoryTesterEvent == MemoryTesterEvent.OnRefresh) {
if (memoryTesterEvent == MemoryTesterEvent.OnRefresh)
{
OnRefresh();
}
}
public void OnAnswerEntered(AnswerEventArgs answerEventArgs, MemoryQuestionModel question) {
public void OnAnswerEntered(AnswerEventArgs answerEventArgs, MemoryQuestionModel question)
{
question.Guess = answerEventArgs.Guess;
MemoryTesterService.Update(question);
}
void OnVerify() {
void OnVerify()
{
hasBeenSubmitted = true;
isCorrect = true;
foreach (var question in questions) {
if (question.Answer != question.Guess) {
foreach (var question in questions)
{
if (question.Answer != question.Guess)
{
isCorrect = false;
isWrong = true;
return;
@@ -101,7 +112,8 @@
StateHasChanged();
}
void OnRefresh() {
void OnRefresh()
{
hasBeenSubmitted = false;
isCorrect = false;
isWrong = false;
@@ -4,8 +4,10 @@
<div class="quizContainer">
<div class="quizListContainer">
@if (entities != null && questions != null) {
@foreach (var entityMemory in entities) {
@if (entities != null && questions != null)
{
@foreach (var entityMemory in entities)
{
<UnitMemory EntityMemory="entityMemory"></UnitMemory>
}
}
@@ -57,25 +59,30 @@
@code {
private List<MemoryEntityModel> entities;
private List<MemoryQuestionModel> questions;
private List<MemoryEntityModel> entities = null!;
private List<MemoryQuestionModel> questions = null!;
protected override void OnInitialized() {
protected override void OnInitialized()
{
MemoryTesterService.Subscribe(OnMemoryEvent);
MemoryTesterService.GenerateQuiz();
}
void IDisposable.Dispose() {
void IDisposable.Dispose()
{
MemoryTesterService.Unsubscribe(OnMemoryEvent);
}
void OnMemoryEvent(MemoryTesterEvent memoryTesterEvent) {
if (memoryTesterEvent == MemoryTesterEvent.OnVerify) {
void OnMemoryEvent(MemoryTesterEvent memoryTesterEvent)
{
if (memoryTesterEvent == MemoryTesterEvent.OnVerify)
{
StateHasChanged();
}
if (memoryTesterEvent == MemoryTesterEvent.OnRefresh) {
if (memoryTesterEvent == MemoryTesterEvent.OnRefresh)
{
entities = MemoryTesterService.GetEntities();
questions = MemoryTesterService.GetQuestions();
@@ -83,11 +90,13 @@
}
}
void OnSubmitQuiz(EventArgs eventArgs) {
void OnSubmitQuiz(EventArgs eventArgs)
{
MemoryTesterService.Verify();
}
void OnRefreshQuiz(EventArgs eventArgs) {
void OnRefreshQuiz(EventArgs eventArgs)
{
MemoryTesterService.GenerateQuiz();
}
+140
View File
@@ -0,0 +1,140 @@
@layout PageLayout
@inject INoteService noteService
@implements IDisposable
@page "/notes"
@if (!noteService.IsLoaded())
{
<LoadingComponent/>
}
else
{
<LayoutMediumContentComponent>
<PaperComponent>
@foreach (var noteSection in noteService.NoteSectionModels)
{
<div class="noteSectionContainer">
<div class="noteSectionTitle">@noteSection.Name</div>
<div class="noteContentContainer">
@foreach (var noteContent in noteSection.NoteContentModels)
{
<NavLink class="noteContentLink" href="@noteContent.GetNoteLink()">
<div class="noteContentName">@noteContent.Name</div>
<div class="noteContentDescription">@noteContent.Description</div>
</NavLink>
}
</div>
</div>
}
</PaperComponent>
</LayoutMediumContentComponent>
}
<style>
.noteSectionContainer {
width: 100%;
padding: 8px;
}
.noteSectionTitle {
font-size: 3rem;
font-weight: bold;
text-align: center;
margin-bottom: 32px;
}
.noteContentContainer {
display: grid;
gap: 12px;
grid-template-columns: 1fr 1fr;
}
@@media only screen and (max-width: 1025px) {
.noteContentContainer {
grid-template-columns: 1fr;
}
}
.noteContentName {
font-weight: bold;
font-size: 1.6rem;
}
.noteContentDescription {
font-weight: normal;
}
.noteContentLink {
background-color: var(--paper);
border: 1px solid var(--paper-border);
border-radius: 2px;
padding-left: 12px;
padding-right: 12px;
padding-top: 24px;
padding-bottom: 24px;
color: white;
display: flex;
flex-direction: column;
gap: 12px;
text-align: center;
margin-left: 12px;
margin-right: 12px;
}
.noteContentLink:hover {
background-color: var(--paper-hover);
border-color: var(--paper-border-hover);
text-decoration: none;
box-shadow: 0 4px 6px rgba(0,0,0,0.6);
transform: translateY(-2px) scale(1.01);
}
</style>
@code {
[Parameter]
public string? Href1 { get; set; }
[Parameter]
public string? Href2 { get; set; }
[Parameter]
public string? Href3 { get; set; }
[Parameter]
public string? Href4 { get; set; }
[Parameter]
public string? Href5 { get; set; }
private string Href => Href5 ?? Href4 ?? Href3 ?? Href2 ?? Href1 ?? "";
string selectedSection = "All";
protected override void OnInitialized()
{
noteService.Subscribe(StateHasChanged);
noteService.Load();
}
public void Dispose()
{
noteService.Unsubscribe(StateHasChanged);
}
void OnSectionChanged(ChangeEventArgs e)
{
selectedSection = e.Value!.ToString()!;
StateHasChanged();
}
}
+44 -82
View File
@@ -1,109 +1,71 @@
@layout PageLayout
@inject INoteService NoteService
@inject INoteService noteService
@implements IDisposable
@page "/notes"
@page "/notes/{href1}/{href2?}/{href3?}/{href4?}/{href5?}"
@if (!NoteService.IsLoaded())
@if (!noteService.IsLoaded())
{
<LoadingComponent></LoadingComponent>
<LoadingComponent/>
}
else
{
<LayoutMediumContentComponent>
<WebsiteTitleComponent>Notes</WebsiteTitleComponent>
<div class="section">
<div for="noteSection">Section: </div>
<div style="flex: 1"></div>
<select @oninput="OnSectionChanged" style="background-color: #36393F; width: 250px; margin-right: 16px;" name="noteSection">
<option value="All">All</option>
</select>
</div>
<div class="notesContainer">
@foreach (var note in NoteService.NoteModels) {
if (note.IsHidden) {
continue;
<LayoutWithSidebarComponent>
<Sidebar>
<NoteNavComponent
Connections="noteService.NoteConnectionModels"
Notes="noteService.NoteContentModels"/>
</Sidebar>
<Content>
<PaperComponent>
@foreach (var note in noteService.NoteContentModels)
{
if (!note.Href.Equals(Href))
{
continue;
}
<NoteComponent NoteContentModel="note"/>
}
if (selectedSection != "All" && note.Section != selectedSection) {
continue;
}
@if (note.IsPreAlpha) {
<AlertComponent Type=SeverityType.Warning>
<Title>Pre Alpha</Title>
<Message>This note refers to content that is in pre-alpha. It won't be accurate in future updates to IGP.</Message>
</AlertComponent>
}
<PaperComponent>
<div style="display: flex; flex-direction: row;">
<span style="font-weight: bold; font-style:italic;">@note.Section</span>
<div style="flex: 1"></div>
<span style="font-weight: bold; font-style:italic;">Last Updated on @note.LastUpdated</span>
</div>
<div>
<div id="@note.DEPRECATED_Id()" style="font-weight: bold; font-size: 1.4rem;">@note.Name</div>
<div style="white-space:break-spaces;">@((MarkupString)note.Description)</div>
</div>
</PaperComponent>
}
</div>
</LayoutMediumContentComponent>
</PaperComponent>
</Content>
</LayoutWithSidebarComponent>
}
<style>
.section {
display: flex;
width: 500px;
flex-direction: row;
background-color: var(--paper);
justify-content: center;
padding: 24px;
border: 4px solid var(--paper-border);
box-shadow: 0px 6px var(--paper-border);
}
.notesContainer {
display: flex;
flex-direction: column;
gap: 16px;
}
.noteContainer {
padding: 24px;
border: 2px solid black;
margin: auto;
overflow-y: auto;
overflow-x: hidden;
background-color: var(--paper);
}
</style>
@code {
string selectedSection = "All";
[Parameter]
public string? Href1 { get; set; }
[Parameter]
public string? Href2 { get; set; }
[Parameter]
public string? Href3 { get; set; }
[Parameter]
public string? Href4 { get; set; }
[Parameter]
public string? Href5 { get; set; }
private string Href => Href5 ?? Href4 ?? Href3 ?? Href2 ?? Href1 ?? "";
protected override void OnInitialized()
{
NoteService.Subscribe(StateHasChanged);
NoteService.Load();
noteService.Subscribe(StateHasChanged);
noteService.Load();
}
public void Dispose()
{
NoteService.Unsubscribe(StateHasChanged);
noteService.Unsubscribe(StateHasChanged);
}
void OnSectionChanged(ChangeEventArgs e) {
selectedSection = e.Value.ToString();
StateHasChanged();
}
}
+35
View File
@@ -0,0 +1,35 @@
<div class="note">
<div class="noteHeader">
<div class="noteTitle">@NoteContentModel.Name</div>
<div class="noteDates">
<div class="noteDateUpdated"><b>Updated</b>: @NoteContentModel.UpdatedDate.ToString("MM/dd/yyyy")</div>
<div class="noteDateCreated"><b>Created</b>: @NoteContentModel.CreatedDate.ToString("MM/dd/yyyy")</div>
</div>
</div>
<div class="noteContent">@((MarkupString)Markdown.ToHtml(NoteContentModel.Content))</div>
</div>
<style>
.noteTitle {
font-weight: bold;
}
.noteHeader {
display: flex;
justify-content: space-between;
}
.noteDates {
display: flex;
flex-direction: column;
}
</style>
@code {
[Parameter]
public NoteContentModel NoteContentModel { get; set; } = default!;
}
@@ -0,0 +1,75 @@
@if (Note!.NoteContentModels.Count > 0)
{
<div class="noteInnerNavContainer">
@foreach (var innerNote in Note.NoteContentModels)
{
var linkStyle = $"noteInnerNavButton inner_{Layers}";
<NavLink class="@linkStyle" href="@innerNote.GetNoteLink()">@innerNote.Name</NavLink>
<NoteInnerNavComponent Note="@innerNote" Layers="@IncrementLayers()"/>
}
</div>
}
<style>
.noteInnerNavContainer {
display: flex;
flex-direction: column;
}
.noteInnerNavButton a {
color: white;
}
.noteInnerNavButton a:hover {
color: white;
}
.noteInnerNavButton {
padding: 8px;
margin-left: 8px;
color: white;
}
.noteInnerNavButton:hover {
}
.inner_1 {
margin-left: 8px;
}
.inner_2 {
margin-left: 16px;
}
.inner_3 {
margin-left: 24px;
}
</style>
@code {
[Parameter]
public NoteContentModel? Note { get; set; } = default!;
[Parameter]
public int Layers { get; set; } = 1;
public int IncrementLayers()
{
return Layers + 1;
}
private string GetLink(NoteContentModel note)
{
return $"notes/{note.Href}";
}
}
@@ -0,0 +1,43 @@
<div class="noteNavContainer">
@foreach (var note in Notes)
{
if (note.Parent == null)
{
<NavLink class="noteNavButton" href="@note.GetNoteLink()">@note.Name</NavLink>
<NoteInnerNavComponent Note="@note"/>
}
}
</div>
<style>
.noteNavContainer {
display: flex;
flex-direction: column;
}
.noteNavButton a {
color: white;
}
.noteNavButton a:hover {
color: white;
background-color: var(--primary-hover);
}
.noteNavButton {
padding: 8px;
color: white;
}
</style>
@code {
[Parameter]
public List<NoteContentModel> Notes { get; set; } = default!;
[Parameter]
public List<NoteConnectionModel> Connections { get; set; } = default!;
}
@@ -1,4 +1,4 @@
<div class="roadMapContainer @RoadMap.Status.ToLower()">
<div class="roadMapContainer @RoadMap!.Status.ToLower()">
<div class="roadMapTitle">@RoadMap.Name</div>
<div>
<b>Priority:</b> @RoadMap.Priority.Replace("_", " ")
@@ -53,6 +53,7 @@
</style>
@code {
[Parameter]
public ImmortalRoadMapModel? RoadMap { get; set; }
+2 -1
View File
@@ -6,7 +6,8 @@
<WebsiteTitleComponent>Road Map</WebsiteTitleComponent>
<div class="roadMapsContainer">
@foreach (var roadMap in data) {
@foreach (var roadMap in data)
{
<RoadMapComponent RoadMap=roadMap/>
}
</div>
-229
View File
@@ -1,229 +0,0 @@
@layout PageLayout
@page "/sandbox"
@inject IJSRuntime JS
<LayoutLargeContentComponent>
<WebsiteTitleComponent>Sandbox</WebsiteTitleComponent>
<div>
Generic Page of Testing In Progress code
</div>
<button @onclick="() => DownloadFile(typeof(WebPageModel))">
WebPageModel
</button>
<button @onclick="() => DownloadFile(typeof(WebSectionModel))">
WebSectionModel
</button>
<button @onclick="() => DownloadFile(typeof(PatchModel))">
PatchModel
</button>
<button @onclick="() => DownloadFile(typeof(ChangeModel))">
ChangeModel
</button>
<button @onclick="() => DownloadFile(typeof(SprintModel))">
SprintModel
</button>
<button @onclick="() => DownloadFile(typeof(TaskModel))">
TaskModel
</button>
<FormLayoutComponent>
<FormTextAreaComponent Value="@infoText"></FormTextAreaComponent>
</FormLayoutComponent>
</LayoutLargeContentComponent>
@code {
readonly List<EntityModel> entities = EntityModel.GetList();
List<EntityInfoModel> infos = new();
string infoText = "";
string weaponText = "";
readonly List<ChangeModel> changes = new();
readonly List<PatchModel> patches = new();
private async Task DownloadFile(Type type) {
var fileName = $"{type.ToString().Split(".").Last()}s.csv";
var objectData =
type == typeof(PatchModel) ? new List<object>(patches)
: type == typeof(ChangeModel) ? new List<object>(changes)
: new List<object>();
await JS.InvokeVoidAsync("download", fileName, Generate(type, objectData));
}
void GenerateEntityModels() {
var properties = typeof(EntityInfoModel).GetProperties();
infoText += "Id,Name,Descriptive,Description,Notes\n";
var id = 1;
foreach (var entity in entities) {
infoText += $"{id++},{entity.Info().Name},{entity.Info().Descriptive},{entity.Info().Description},{entity.Info().Notes}\n";
}
}
string Generate(Type type, List<object> dataList) {
var properties = type.GetProperties();
var generatedText = "";
for (var index = 0; index < properties.Count(); index++) {
var property = properties[index];
if (property.GetAccessors().First().IsVirtual) {
continue;
}
var attributes = property.GetCustomAttributes().OfType<ObsoleteAttribute>();
if (attributes.Count() > 0) {
continue;
}
generatedText += property.Name;
if (index != properties.Count() - 1) {
generatedText += ",";
}
}
generatedText = generatedText.Trim();
if (generatedText.EndsWith(",")) {
generatedText = generatedText.Remove(generatedText.Length - 1);
}
generatedText += "\n";
foreach (var data in dataList) {
for (var index = 0; index < properties.Count(); index++) {
var property = properties[index];
if (property.GetAccessors().First().IsVirtual) {
continue;
}
var attributes = property.GetCustomAttributes().OfType<ObsoleteAttribute>();
if (attributes.Count() > 0) {
continue;
}
if (property.GetValue(data) != null) {
generatedText += "\"" + property.GetValue(data).ToString().Replace("\"", "\"\"") + "\"";
if (index != properties.Count() - 1) {
generatedText += ",";
}
}
else {
generatedText += "\"" + " " + "\"";
if (index != properties.Count() - 1) {
generatedText += ",";
}
}
}
generatedText = generatedText.Trim();
if (generatedText.EndsWith(",")) {
generatedText = generatedText.Remove(generatedText.Length - 1);
}
generatedText += "\n";
}
return generatedText;
}
void GenerateWeapons() {
var properties = typeof(EntityWeaponModel).GetProperties();
for (var index = 0; index < properties.Count(); index++) {
var property = properties[index];
if (property.GetAccessors().First().IsVirtual) {
continue;
}
var attributes = property.GetCustomAttributes().OfType<ObsoleteAttribute>
();
if (attributes.Count() > 0) {
continue;
}
weaponText += property.Name;
if (index != properties.Count() - 1) {
weaponText += ",";
}
}
weaponText += "\n";
foreach (var entity in entities) {
foreach (var weapon in entity.Weapons()) {
for (var index = 0; index < properties.Count(); index++) {
var property = properties[index];
if (property.GetAccessors().First().IsVirtual) {
continue;
}
var attributes = property.GetCustomAttributes().OfType<ObsoleteAttribute>
();
if (attributes.Count() > 0) {
continue;
}
weaponText += property.GetValue(weapon);
if (index != properties.Count() - 1) {
weaponText += ",";
}
}
weaponText += "\n";
}
}
}
void GenerateExample() {
var properties = typeof(EntityInfoModel).GetProperties();
for (var index = 0; index < properties.Count(); index++) {
var property = properties[index];
infoText += property.Name;
if (index != properties.Count() - 1) {
infoText += ",";
}
}
infoText += "\n";
foreach (var entity in entities) {
if (entity.Info() != null) {
for (var index = 0; index < properties.Count(); index++) {
var property = properties[index];
infoText += property.GetValue(entity.Info());
if (index != properties.Count() - 1) {
infoText += ",";
}
}
infoText += "\n";
}
}
}
}
+5 -4
View File
@@ -9,12 +9,14 @@
@code {
protected override void OnInitialized()
{
entityDialogService.Subscribe(OnUpdate);
}
public void Dispose() {
public void Dispose()
{
entityDialogService.Unsubscribe(OnUpdate);
}
@@ -23,5 +25,4 @@
StateHasChanged();
}
}
}
+6 -9
View File
@@ -1,20 +1,16 @@
using IGP;
using Microsoft.AspNetCore.Components.Web;
using Services;
using Services.Development;
using Services.Immortal;
using Services.Website;
#if NO_SQL
#else
using Contexts;
using Microsoft.EntityFrameworkCore;
#endif
using Services;
using Services.Immortal;
using Services.Website;
using Services.Development;
using IEntityDisplayService = Services.IEntityDisplayService;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.Logging.SetMinimumLevel(LogLevel.Warning);
@@ -37,7 +33,8 @@ builder.Services.AddSingleton<IEntityFilterService, EntityFilterService>();
builder.Services.AddSingleton<IEntityDisplayService, EntityDisplayService>();
builder.Services.AddSingleton(new HttpClient {
builder.Services.AddSingleton(new HttpClient
{
BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
});
+25 -19
View File
@@ -1,6 +1,4 @@
@using Components.Display
@using Components.Display
@using Components.Feedback
@using Components.Form
@using Components.Info
@@ -9,17 +7,26 @@
@using Components.Navigation
@using Components.Shared
@using Components.Utils
@using IGP.Portals
@using IGP.Pages
@using IGP.Dialog
@using IGP.Pages
@using IGP.Pages.Agile.Parts
@using IGP.Pages.BuildCalculator.Parts
@using IGP.Pages.Comparision
@using IGP.Pages.Comparision.Parts
@using IGP.Pages.Database.Entity
@using IGP.Pages.Database.Entity.Parts
@using IGP.Pages.Database.Parts
@using IGP.Pages.Documentation
@using IGP.Pages.Documentation.Parts
@using IGP.Pages.Home
@using IGP.Pages.Home.Parts
@using IGP.Pages.MakingOf.Parts
@using IGP.Pages.MemoryTester.Parts
@using IGP.Pages.RoadMap.Parts
@using IGP.Pages.Notes
@using IGP.Pages.Notes.Parts
@using IGP.Portals
@using Markdig
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@@ -27,21 +34,20 @@
@using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.EntityFrameworkCore
@using Microsoft.JSInterop
@using Model.Immortal.Chart
@using Model.Immortal.Economy
@using Model.Immortal.Entity
@using Model.Immortal.Entity.Data
@using Model.Immortal.Entity.Parts
@using Model.Immortal.Hotkeys
@using Model.Immortal.MemoryTester
@using Model.Immortal.MemoryTester
@using Model.Immortal.Notes
@using Model.Immortal.RoadMap
@using Model.Immortal.RoadMap
@using Model.Immortal.RoadMap.Enums
@using Model.Immortal.Types
@using Model.Chart
@using Model.Development.Git
@using Model.Doc
@using Model.Economy
@using Model.Entity
@using Model.Entity.Data
@using Model.Entity.Parts
@using Model.Hotkeys
@using Model.MemoryTester
@using Model.Notes
@using Model.RoadMap
@using Model.RoadMap.Enums
@using Model.Types
@using Model.Website
@using Model.Work.Git
@using Model.Work.Tasks
@using Model.Work.Tasks.Enums
@using Services
+5 -1
View File
@@ -15,9 +15,13 @@
--secondary-border-hover: #a168ff;
--paper: #252526;
--paper-border: #151516;
--paper-hover: #52366f;
--paper-border-hover: #653497;
--info: #451376;
--info-border: #210b36;
--dialog-border-color: black;
--dialog-border-width: 2px;
--dialog-radius: 6px;
@@ -0,0 +1 @@
[{"Id":1,"Name":"Agile Sprint","Description":"Changelogs and sprint views were going to be pushed till later, but I am feeling inspired by the IGP Content Creators\u0027 minimum weekly lifecycle requirement. So I am going to focus on agile-related tasks, and handle roadmap tasks after this initial sprint. All weekly sprints will release on Sunday, starting next Sunday.","StartDate":"2022-02-14T00:00:00","EndDate":"2022-02-20T00:00:00","Notes":null,"AgileTaskModels":[]},{"Id":2,"Name":"SQL Update","Description":"The SQL update is big enough to be a full sprint in of itself, and I spent less time this week for development. Will just extend sprint by 2 week, and remove all non SQL tasks from the sprint.","StartDate":"2022-02-20T00:00:00","EndDate":"2022-03-27T00:00:00","Notes":null,"AgileTaskModels":[]},{"Id":3,"Name":"Database Page","Description":"Improvements to the Database page","StartDate":"2022-03-27T00:00:00","EndDate":"2022-04-03T00:00:00","Notes":null,"AgileTaskModels":[]},{"Id":4,"Name":"Branding","Description":"Improve streaming branding around the website","StartDate":"2022-04-03T00:00:00","EndDate":"2022-04-10T00:00:00","Notes":null,"AgileTaskModels":[]},{"Id":5,"Name":"Calculators","Description":"Improve Calculators","StartDate":"2022-04-10T00:00:00","EndDate":"2022-04-24T00:00:00","Notes":null,"AgileTaskModels":[]},{"Id":6,"Name":"Infrastructure","Description":"Localization, Analytics, and Test Automation","StartDate":"2022-04-24T00:00:00","EndDate":"2022-05-08T00:00:00","Notes":null,"AgileTaskModels":[]}]
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
[]
@@ -0,0 +1 @@
[{"Id":1,"ParentId":1,"DocSectionModelId":1,"Href":"setup","DocumentationModels":[],"Parent":null,"PageOrder":0,"CreatedDate":"2022-03-30T00:00:00","UpdatedDate":"2022-04-07T00:00:00","Name":"Development Setup","Description":"Get set up on developing this web project.","Content":"# Overview\n\nThis document will contain general setup notes for the project.\n\n## Prerequisite\n\nTo understand content in this document, it is recommended to have some software development experience. Particularly using GitHub and Visual Studio.\n\n- [GitHub Documentation](https://docs.github.com/en/get-started)\n\n- [Visual Studio Documentation](https://visualstudio.microsoft.com/vs/getting-started/)\n\nTo make updates to this website, it is recommended to understand HTML/CSS and C#.\n\n- [C# Documentation](https://docs.microsoft.com/en-us/dotnet/csharp/)\n- [Mozilla\u0027s HTML Documentation](https://developer.mozilla.org/en-US/docs/Learn/HTML/Introduction_to_HTML/Getting_started)\n- [W3SCHOOLS\u0027 HTML Documentation](https://www.w3schools.com/html/)\n\nFurther, you should understand the product and clients this website is for. So it is recommended to play \u0022Immortal: Gates of Pyre\u0022.\n\n- [IGP Website](https://gatesofpyre.com/)\n - **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.\n\n## Installation\n\nDownload and install Visual Studio preview.\n\n**Note:** Visual Studio Preview currently doesn\u0027t work on Mac for this project. Use a PC, or Rider.\n\n[https://visualstudio.microsoft.com/vs/preview/](https://visualstudio.microsoft.com/vs/preview/)\n\nWhen installing, ensure you have selected \u0022Workloads | **ASP.NET and web development**\u0022 and \u0022Individual components | **.NET WebAssembly build tools**\u0022.\n\n## Download Project\n\nGet this project from GitHub.\n\n\u0060\u0060\u0060bash\ngit clone https://github.com/JonathanMcCaffrey/IGP-Fan-Reference.git\n\u0060\u0060\u0060\n\n## Project Tree\n\n\u0060\u0060\u0060\nC:.\n\u251C\u2500\u2500\u2500.github\n\u2502 \u2514\u2500\u2500\u2500workflows # Workflows to deploy website\n\u251C\u2500\u2500\u2500Components # Components used be website\n\u251C\u2500\u2500\u2500Contexts\n\u251C\u2500\u2500\u2500IGP\n\u2502 \u251C\u2500\u2500\u2500Pages # Website pages\n\u2502 \u2514\u2500\u2500\u2500wwwroot\n\u2502 \u251C\u2500\u2500\u2500css\n\u2502 \u251C\u2500\u2500\u2500generated # Files generated by IGP_Convert. Do not edit\n\u2502 \u251C\u2500\u2500\u2500image\n\u2502 \u2514\u2500\u2500\u2500javascript\n\u251C\u2500\u2500\u2500IGP_Convert # Converts SQL into JSON for Blazor Wasm\n\u251C\u2500\u2500\u2500Model # Data models\n\u2514\u2500\u2500\u2500Services # Web services\n\u0060\u0060\u0060\n\n## Running\n\n- Open \u0060IGP/IGP.sln\u0060.\n- Click the green RUN button in Visual Studio.\n- A local copy of the IGP Website should have launched on your machine.\n\n## Publishing\n\nCode committed to the \u0060main\u0060 branch will automatically be deployed to [production](https://www.igpfanreference.com/).\n\nCode committed to the \u0060develop\u0060 branch will automatically be deployed to [development](https://calm-mud-04916b210.1.azurestaticapps.net/).\n\n_This is handle via the files in \u0060.github/workflow\u0060. Look into these [GitHub Actions Documents](https://docs.github.com/en/actions) if curious about how this CI system works._\n\n## Troubleshooting\n\n\nNothing that some good internet searches cannot resolved. But you can also contact the project maintainer on [Discord](https://discord.gg/uMq8bMGeeN)."}]
@@ -0,0 +1 @@
[{"Id":1,"Name":"Start","DocumentationModels":[]}]
@@ -1 +0,0 @@
[{"Id":1,"CreatedDate":"2022-03-30T00:00:00","UpdatedDate":"2022-03-30T00:00:00","Name":"Setup","Section":"Getting Started","Description":"# Setup\n\nThis document will contain general setup notes for the project.\n\n## Prerequisite\n\nTo understand content in this document, it is recommended to have some software development experience. Particularly using GitHub and Visual Studio.\n\n- [GitHub Documentation](https://docs.github.com/en/get-started)\n\n- [Visual Studio Documentation](https://visualstudio.microsoft.com/vs/getting-started/)\n\nTo make updates to this website, it is recommended to understand HTML/CSS and C#.\n\n- [C# Documentation](https://docs.microsoft.com/en-us/dotnet/csharp/)\n- [Mozilla\u0027s HTML Documentation](https://developer.mozilla.org/en-US/docs/Learn/HTML/Introduction_to_HTML/Getting_started)\n- [W3SCHOOLS\u0027 HTML Documentation](https://www.w3schools.com/html/)\n\nFurther, you should understand the product and clients this website is for. So it is recommended to play \u0022Immortal: Gates of Pyre\u0022.\n- [IGP Website](https://gatesofpyre.com/) \n - **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.\n\n\n## Installation\n\nDownload and install Visual Studio preview.\n\n**Note:** Visual Studio Preview currently doesn\u0027t work on Mac for this project. Use a PC, or Rider.\n\nhttps://visualstudio.microsoft.com/vs/preview/\n\nWhen installing, ensure you have selected \u0022Workloads | **ASP.NET and web development**\u0022 and \u0022Individual components | **.NET WebAssembly build tools**\u0022.\n\n## Download Project\n\nGet this project from GitHub. \n\n\u0060\u0060\u0060bash\ngit clone https://github.com/JonathanMcCaffrey/IGP-Fan-Reference.git\n\u0060\u0060\u0060\n\n## Project Tree\n\u0060\u0060\u0060\nC:.\n\u251C\u2500\u2500\u2500.github\n\u2502 \u2514\u2500\u2500\u2500workflows # Workflows to deploy website\n\u251C\u2500\u2500\u2500Components # Components used be website\n\u251C\u2500\u2500\u2500Contexts\n\u251C\u2500\u2500\u2500IGP\n\u2502 \u251C\u2500\u2500\u2500Pages # Website pages\n\u2502 \u2514\u2500\u2500\u2500wwwroot \n\u2502 \u251C\u2500\u2500\u2500css\n\u2502 \u251C\u2500\u2500\u2500generated # Files generated by IGP_Convert. Do not edit\n\u2502 \u251C\u2500\u2500\u2500image\n\u2502 \u251C\u2500\u2500\u2500javascript\n\u2502 \u2514\u2500\u2500\u2500markdown\n\u2502 \u2514\u2500\u2500\u2500documentation # Documentation files\n\u251C\u2500\u2500\u2500IGP_Convert # Converts SQL into JSON for Blazor Wasm\n\u251C\u2500\u2500\u2500Model # Data models\n\u2514\u2500\u2500\u2500Services # Web services\n\u0060\u0060\u0060\n\n## Running\n\n- Open \u0060IGP/IGP.sln\u0060. \n- Click the green RUN button in Visual Studio.\n- A local copy of the IGP Website should have launched on your machine.\n\n\n## Publishing\n\nCode committed to the \u0060main\u0060 branch will automatically be deployed to [production](https://www.igpfanreference.com/).\n\nCode committed to the \u0060develop\u0060 branch will automatically be deployed to [development](https://calm-mud-04916b210.1.azurestaticapps.net/).\n\n*This is handle via the files in \u0060.github/workflow\u0060. Look into these [GitHub Actions Documents](https://docs.github.com/en/actions) if curious about how this CI system works.*\n\n\n## Troubleshooting\n\nNothing that some good internet searches cannot resolved. But you can also contact the project maintainer on [IGP Fan Reference](https://discord.gg/uMq8bMGeeN) Discord.\n\n"}]
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
[{"Id":1,"Name":"Database UX Patch","Date":"2022-03-13T00:00:00","GitChangeModels":[],"Important":"False"},{"Id":2,"Name":"Thrum Stats Hotfix","Date":"2022-03-12T00:00:00","GitChangeModels":[],"Important":"False"},{"Id":3,"Name":"Memory Tester Patch","Date":"2022-03-01T00:00:00","GitChangeModels":[],"Important":"False"},{"Id":4,"Name":"Hide Pyre Hotfix","Date":"2022-02-20T00:00:00","GitChangeModels":[],"Important":"False"},{"Id":5,"Name":"Stream Patch","Date":"2022-02-20T00:00:00","GitChangeModels":[],"Important":"False"},{"Id":6,"Name":"Agile UI Hotfix","Date":"2022-02-20T00:00:00","GitChangeModels":[],"Important":"False"},{"Id":7,"Name":"Armor Patch","Date":"2022-02-19T00:00:00","GitChangeModels":[],"Important":"False"},{"Id":8,"Name":"Home Page Patch","Date":"2022-02-19T00:00:00","GitChangeModels":[],"Important":"False"},{"Id":9,"Name":"Mobile Menu Hotfix 2","Date":"2022-02-19T00:00:00","GitChangeModels":[],"Important":"False"},{"Id":10,"Name":"Mobile Menu Hotfix","Date":"2022-02-19T00:00:00","GitChangeModels":[],"Important":"False"},{"Id":11,"Name":"Mobile Menu Patch","Date":"2022-02-19T00:00:00","GitChangeModels":[],"Important":"False"},{"Id":12,"Name":"0.0.6.8375a Patch","Date":"2022-02-18T00:00:00","GitChangeModels":[],"Important":"True"},{"Id":13,"Name":"Google Tracking Hotfix","Date":"2022-02-18T00:00:00","GitChangeModels":[],"Important":"False"},{"Id":14,"Name":"Privacy Policy Patch","Date":"2022-02-17T00:00:00","GitChangeModels":[],"Important":"False"},{"Id":15,"Name":"Home Page Quick Hotfix","Date":"2022-02-16T00:00:00","GitChangeModels":[],"Important":"False"},{"Id":16,"Name":"Early Agile Patch","Date":"2022-02-16T00:00:00","GitChangeModels":[],"Important":"False"},{"Id":17,"Name":"Form Text Rendering Hotfix","Date":"2022-02-15T00:00:00","GitChangeModels":[],"Important":"False"},{"Id":18,"Name":"Reducing Timing Interval Hotfix","Date":"2022-02-15T00:00:00","GitChangeModels":[],"Important":"False"},{"Id":19,"Name":"Changelog Patch","Date":"2022-02-14T00:00:00","GitChangeModels":[],"Important":"False"},{"Id":20,"Name":"SQL Patch","Date":"2022-03-26T00:00:00","GitChangeModels":[],"Important":"False"},{"Id":21,"Name":"Stream Patch","Date":"2022-03-30T00:00:00","GitChangeModels":[],"Important":"False"},{"Id":22,"Name":"0.0.6.8900a Patch","Date":"2022-03-30T00:00:00","GitChangeModels":[],"Important":"True"},{"Id":23,"Name":"Database Links Patch","Date":"2022-04-01T00:00:00","GitChangeModels":[],"Important":"False"},{"Id":24,"Name":"Open Source Patch","Date":"2022-04-03T00:00:00","GitChangeModels":[],"Important":"False"},{"Id":25,"Name":"Stream Patch","Date":"2022-04-03T00:00:00","GitChangeModels":[],"Important":"False"}]
@@ -0,0 +1 @@
[]
@@ -0,0 +1 @@
[{"Id":1,"ParentId":null,"NoteSectionModelId":1,"Href":"holdout","CreatedDate":"2022-02-18T00:00:00","UpdatedDate":"2022-02-18T00:00:00","Name":"Coop Holdout, Some distant place (Nuath)","Description":"First coop test map in pre-alpha.","Content":"Information contained in this note is based on this \u003Ca href=\u0022https://www.youtube.com/watch?v=XkAgOCIz3DE\u0022\u003EYouTube, Reference Video\u003C/a\u003E.\n\n\u003Cimg width=\u0022420\u0022 style=\u0022margin: auto; border:2px solid black;\u0022 src=\u0022image/notes/coop-holdout/OpenBases.png\u0022 /\u003E\n\u003Cdiv style=\u0022margin: auto; text-align:center;\u0022\u003E\u003Cb\u003EOpen Bases\u003C/b\u003E\u003C/div\u003E\n\nOn 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.\n\nYou 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.\n\n\n\u003Cimg width=\u0022420\u0022 style=\u0022margin: auto; border:2px solid black;\u0022 src=\u0022image/notes/coop-holdout/EnemySpawns.png\u0022 /\u003E\n\u003Cdiv style=\u0022margin: auto; text-align:center;\u0022\u003E\u003Cb\u003EEnemy Spawn Areas\u003C/b\u003E\u003C/div\u003E\n\nThe first enemy wave will spawn at 1 minute, and every 2 minutes after will spawn a new wave. These waves are small, and won\u0027t be a threat until the 15-minute mark.\n\n\u003Cimg width=\u0022420\u0022 style=\u0022margin: auto; border:2px solid black;\u0022 src=\u0022image/notes/coop-holdout/DefendPoints.png\u0022 /\u003E\n\u003Cdiv style=\u0022margin: auto; text-align:center;\u0022\u003E\u003Cb\u003EPyre Towers\u003C/b\u003E\u003C/div\u003E\n\nYou have till then to take all 5 of your bases, and set a defensive line at the outer Pyre towers.\n\nThe 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.\n\n\u003Cimg width=\u0022420\u0022 style=\u0022margin: auto; border:2px solid black;\u0022 src=\u0022image/notes/coop-holdout/Pyre.png\u0022 /\u003E\n\u003Cdiv style=\u0022margin: auto; text-align:center;\u0022\u003E\u003Cb\u003EPyre Camps\u003C/b\u003E\u003C/div\u003E\n\nWhen 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.\n\n\u003Cimg width=\u0022420\u0022 style=\u0022margin: auto; border:2px solid black;\u0022 src=\u0022image/notes/coop-holdout/Multipliers.png\u0022 /\u003E\n\u003Cdiv style=\u0022margin: auto; text-align:center;\u0022\u003E\u003Cb\u003EMultipliers\u003C/b\u003E\u003C/div\u003E\n\nIf 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\u0027s possible to go past the supply cap.\n\n\nBut really, these optional objectives can be completely ignored, so you can just focus on surviving for as long as possible.","IsHidden":"False","IsPreAlpha":"True","NoteContentModels":[],"Parent":null,"PageOrder":0}]
-1
View File
@@ -1 +0,0 @@
[{"Id":1,"LastUpdated":"2022-02-18T00:00:00","Name":"Coop Holdout, Some distant place (Nuath)","Section":"Coop","Description":"Information contained in this note is based on this \u003Ca href=\u0022https://www.youtube.com/watch?v=XkAgOCIz3DE\u0022\u003EYouTube, Reference Video\u003C/a\u003E.\n\n\u003Cimg width=\u0022420\u0022 style=\u0022margin: auto; border:2px solid black;\u0022 src=\u0022image/notes/coop-holdout/OpenBases.png\u0022 /\u003E\n\u003Cdiv style=\u0022margin: auto; text-align:center;\u0022\u003E\u003Cb\u003EOpen Bases\u003C/b\u003E\u003C/div\u003E\n\nOn 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.\n\nYou 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.\n\n\n\u003Cimg width=\u0022420\u0022 style=\u0022margin: auto; border:2px solid black;\u0022 src=\u0022image/notes/coop-holdout/EnemySpawns.png\u0022 /\u003E\n\u003Cdiv style=\u0022margin: auto; text-align:center;\u0022\u003E\u003Cb\u003EEnemy Spawn Areas\u003C/b\u003E\u003C/div\u003E\n\nThe first enemy wave will spawn at 1 minute, and every 2 minutes after will spawn a new wave. These waves are small, and won\u0027t be a threat until the 15-minute mark.\n\n\u003Cimg width=\u0022420\u0022 style=\u0022margin: auto; border:2px solid black;\u0022 src=\u0022image/notes/coop-holdout/DefendPoints.png\u0022 /\u003E\n\u003Cdiv style=\u0022margin: auto; text-align:center;\u0022\u003E\u003Cb\u003EPyre Towers\u003C/b\u003E\u003C/div\u003E\n\nYou have till then to take all 5 of your bases, and set a defensive line at the outer Pyre towers.\n\nThe 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.\n\n\u003Cimg width=\u0022420\u0022 style=\u0022margin: auto; border:2px solid black;\u0022 src=\u0022image/notes/coop-holdout/Pyre.png\u0022 /\u003E\n\u003Cdiv style=\u0022margin: auto; text-align:center;\u0022\u003E\u003Cb\u003EPyre Camps\u003C/b\u003E\u003C/div\u003E\n\nWhen 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.\n\n\u003Cimg width=\u0022420\u0022 style=\u0022margin: auto; border:2px solid black;\u0022 src=\u0022image/notes/coop-holdout/Multipliers.png\u0022 /\u003E\n\u003Cdiv style=\u0022margin: auto; text-align:center;\u0022\u003E\u003Cb\u003EMultipliers\u003C/b\u003E\u003C/div\u003E\n\nIf 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\u0027s possible to go past the supply cap.\n\n\nBut really, these optional objectives can be completely ignored, so you can just focus on surviving for as long as possible.","IsHidden":false,"IsPreAlpha":false}]
@@ -0,0 +1 @@
[{"Id":1,"Name":"PVE Content","NoteContentModels":[]}]
-1
View File
@@ -1 +0,0 @@
[{"Id":1,"Name":"Database UX Patch","Date":"2022-03-13T00:00:00","ChangeModels":[],"Important":"False"},{"Id":2,"Name":"Thrum Stats Hotfix","Date":"2022-03-12T00:00:00","ChangeModels":[],"Important":"False"},{"Id":3,"Name":"Memory Tester Patch","Date":"2022-03-01T00:00:00","ChangeModels":[],"Important":"False"},{"Id":4,"Name":"Hide Pyre Hotfix","Date":"2022-02-20T00:00:00","ChangeModels":[],"Important":"False"},{"Id":5,"Name":"Stream Patch","Date":"2022-02-20T00:00:00","ChangeModels":[],"Important":"False"},{"Id":6,"Name":"Agile UI Hotfix","Date":"2022-02-20T00:00:00","ChangeModels":[],"Important":"False"},{"Id":7,"Name":"Armor Patch","Date":"2022-02-19T00:00:00","ChangeModels":[],"Important":"False"},{"Id":8,"Name":"Home Page Patch","Date":"2022-02-19T00:00:00","ChangeModels":[],"Important":"False"},{"Id":9,"Name":"Mobile Menu Hotfix 2","Date":"2022-02-19T00:00:00","ChangeModels":[],"Important":"False"},{"Id":10,"Name":"Mobile Menu Hotfix","Date":"2022-02-19T00:00:00","ChangeModels":[],"Important":"False"},{"Id":11,"Name":"Mobile Menu Patch","Date":"2022-02-19T00:00:00","ChangeModels":[],"Important":"False"},{"Id":12,"Name":"0.0.6.8375a Patch","Date":"2022-02-18T00:00:00","ChangeModels":[],"Important":"True"},{"Id":13,"Name":"Google Tracking Hotfix","Date":"2022-02-18T00:00:00","ChangeModels":[],"Important":"False"},{"Id":14,"Name":"Privacy Policy Patch","Date":"2022-02-17T00:00:00","ChangeModels":[],"Important":"False"},{"Id":15,"Name":"Home Page Quick Hotfix","Date":"2022-02-16T00:00:00","ChangeModels":[],"Important":"False"},{"Id":16,"Name":"Early Agile Patch","Date":"2022-02-16T00:00:00","ChangeModels":[],"Important":"False"},{"Id":17,"Name":"Form Text Rendering Hotfix","Date":"2022-02-15T00:00:00","ChangeModels":[],"Important":"False"},{"Id":18,"Name":"Reducing Timing Interval Hotfix","Date":"2022-02-15T00:00:00","ChangeModels":[],"Important":"False"},{"Id":19,"Name":"Changelog Patch","Date":"2022-02-14T00:00:00","ChangeModels":[],"Important":"False"},{"Id":20,"Name":"SQL Patch","Date":"2022-03-26T00:00:00","ChangeModels":[],"Important":"False"},{"Id":21,"Name":"Stream Patch","Date":"2022-03-30T00:00:00","ChangeModels":[],"Important":"False"},{"Id":22,"Name":"0.0.6.8900a Patch","Date":"2022-03-30T00:00:00","ChangeModels":[],"Important":"True"},{"Id":23,"Name":"Database Links Patch","Date":"2022-04-01T00:00:00","ChangeModels":[],"Important":"False"},{"Id":24,"Name":"Open Source Patch","Date":"2022-04-03T00:00:00","ChangeModels":[],"Important":"False"},{"Id":25,"Name":"Stream Patch","Date":"2022-04-03T00:00:00","ChangeModels":[],"Important":"False"}]
-1
View File
@@ -1 +0,0 @@
[{"Id":1,"Name":"Agile Sprint","Description":"Changelogs and sprint views were going to be pushed till later, but I am feeling inspired by the IGP Content Creators\u0027 minimum weekly lifecycle requirement. So I am going to focus on agile-related tasks, and handle roadmap tasks after this initial sprint. All weekly sprints will release on Sunday, starting next Sunday.","StartDate":"2022-02-14T00:00:00","EndDate":"2022-02-20T00:00:00","Notes":null},{"Id":2,"Name":"SQL Update","Description":"The SQL update is big enough to be a full sprint in of itself, and I spent less time this week for development. Will just extend sprint by 2 week, and remove all non SQL tasks from the sprint.","StartDate":"2022-02-20T00:00:00","EndDate":"2022-03-27T00:00:00","Notes":null},{"Id":3,"Name":"Database Page","Description":"Improvements to the Database page","StartDate":"2022-03-27T00:00:00","EndDate":"2022-04-03T00:00:00","Notes":null},{"Id":4,"Name":"Branding","Description":"Improve streaming branding around the website","StartDate":"2022-04-03T00:00:00","EndDate":"2022-04-10T00:00:00","Notes":null}]
File diff suppressed because one or more lines are too long
+21 -14
View File
@@ -4,7 +4,8 @@ This document will contain general setup notes for the project.
## 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)
@@ -16,10 +17,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)
- [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".
- [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.
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/)
- **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
@@ -27,17 +31,19 @@ Download and install Visual Studio 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
Get this project from GitHub.
Get this project from GitHub.
```bash
git clone https://github.com/JonathanMcCaffrey/IGP-Fan-Reference.git
```
## Project Tree
```
C:.
├───.github
@@ -60,24 +66,25 @@ C:.
## Running
- Open `IGP/IGP.sln`.
- Open `IGP/IGP.sln`.
- Click the green RUN button in Visual Studio.
- A local copy of the IGP Website should have launched on your machine.
## Publishing
**Important:** publishing new version of the website will not occur until issue [39528](https://github.com/dotnet/aspnetcore/issues/39528) in dotnet/aspnetcore is resolved.
**Important:** publishing new version of the website will not occur until
issue [39528](https://github.com/dotnet/aspnetcore/issues/39528) in dotnet/aspnetcore is resolved.
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/).
*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.*
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.*
## Troubleshooting
Nothing that some good internet searches cannot resolved. But you can also contact the project maintainer on [IGP Fan Reference](https://discord.gg/uMq8bMGeeN) Discord.
Nothing that some good internet searches cannot resolved. But you can also contact the project maintainer
on [IGP Fan Reference](https://discord.gg/uMq8bMGeeN) Discord.
+22 -10
View File
@@ -1,42 +1,54 @@
---
LastUpdated: 2022-02-18
Section: "Coop"
LastUpdated: 2022-02-18 Section: "Coop"
Name: "Coop Holdout, Some distant place (Nuath)"
IsPreAlpha: true
---
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>.
<img width="420" style="margin: auto; border:2px solid black;" src="image/notes/coop-holdout/OpenBases.png" />
<div style="margin: auto; text-align:center;"><b>Open Bases</b></div>
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.
<img width="420" style="margin: auto; border:2px solid black;" src="image/notes/coop-holdout/EnemySpawns.png" />
<div style="margin: auto; text-align:center;"><b>Enemy Spawn Areas</b></div>
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.
<img width="420" style="margin: auto; border:2px solid black;" src="image/notes/coop-holdout/DefendPoints.png" />
<div style="margin: auto; text-align:center;"><b>Pyre Towers</b></div>
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.
<img width="420" style="margin: auto; border:2px solid black;" src="image/notes/coop-holdout/Pyre.png" />
<div style="margin: auto; text-align:center;"><b>Pyre Camps</b></div>
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.
<img width="420" style="margin: auto; border:2px solid black;" src="image/notes/coop-holdout/Multipliers.png" />
<div style="margin: auto; text-align:center;"><b>Multipliers</b></div>
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.