@layout PageLayout @inherits BasePage @inject IStringLocalizer Locale @inject IKeyService KeyService @inject IImmortalSelectionService FilterService @inject IBuildOrderService BuildOrderService @inject IEconomyService EconomyService @inject IToastService ToastService @inject ITimingService TimingService @inject IDataCollectionService DataCollectionService @page "/build-calculator" @using Services.Website @implements IDisposable Build Calculator Work In Progress and Not Fully Tested Build Calculator hasn't been thoroughly tested. Bugs and inaccurate results assumed.
Currently not considering running out of alloy and ether to harvest.
Clear Build Order
What is this tool? This is a calculator to determine build timings. Mostly so someone can quickly try out a few build orders to see if they somewhat make sense. How does it work? The tool calculates every second of game time. So if you attempt to build a Legion Hall as your first action, the tool will scan every second, until you get to one where the request can be made. In this case, that is interval 58.

If you then build 2 Apostle of Bindings a Soul Foundry and a 3 Absolvers you should see yourself roughly floating 500 alloy, with barely having any ether. Which means you could of gotten an Acropolis and a Zentari without hurting your build.

Try building Apostle of Bindings before the Legion Hall and see how that changes the timing of your 3 Absolvers. (Spoiler: your Absolvers will be built much faster, and you won't be floating so much alloy.)
What is CONTROL key for? Economy and tech related upgrades for townhalls. What is SHIFT key for? Misc building related upgrades. (Omnivores) What is 2 key for? It will be for Pyre camps. Currently not implemented.
@code { protected override void OnInitialized() { base.OnInitialized(); EconomyService.Calculate(BuildOrderService, TimingService, 0); KeyService.Subscribe(HandleClick); DataCollectionService.SendEvent( DataCollectionKeys.PageInitialized, new Dictionary { { "page", "build-calculator" } } ); } void IDisposable.Dispose() { KeyService.Unsubscribe(HandleClick); } private void OnResetClicked() { ToastService.AddToast(new ToastModel { SeverityType = SeverityType.Success, Message = "Build order has been cleared.", Title = "Reset" }); BuildOrderService.Reset(); } private void HandleClick() { var hotkey = KeyService.GetHotkey(); if (hotkey == "") { return; } if (hotkey == "`") { BuildOrderService.RemoveLast(); EconomyService.Calculate(BuildOrderService, TimingService, BuildOrderService.GetLastRequestInterval()); return; } var hotkeyGroup = KeyService.GetHotkeyGroup(); var isHoldSpace = KeyService.IsHoldingSpace(); var faction = FilterService.GetFaction(); var immortal = FilterService.GetImmortal(); var entity = EntityModel.GetFrom(hotkey!, hotkeyGroup, isHoldSpace, faction, immortal); if (entity == null) { return; } if (BuildOrderService.Add(entity, EconomyService)) { EconomyService.Calculate(BuildOrderService, TimingService, BuildOrderService.GetLastRequestInterval()); } } }