UI/ShopScreen.razor
@using System;
@using Sandbox;
@using Sandbox.UI;
@* Weaponsmith / armoury. The shopkeeper stands in the 3D shop; this is his board of wares. *@
<root class="screen @(Armoury ? "armoury" : "smith")">
<div class="bubble">@Speech</div>
<div class="parchment board">
@if ( Armoury )
{
<div class="slot-tabs">
@foreach ( var slot in Catalog.Slots )
{
var s = slot;
<div class="tab @(Slot == s ? "active" : "")" onclick=@(() => { Slot = s; Selected = -1; Page = 0; Speech = null; StateHasChanged(); })>@Catalog.SlotName( s )</div>
}
</div>
}
<div class="grid">
@foreach ( var it in PageItems )
{
var item = it;
<div class="item @(item.Locked ? "locked" : "") @(item.Owned ? "owned" : "") @(item.Worn ? "equipped" : "") @(Selected == item.Id ? "selected" : "")"
onclick=@(() => Pick( item.Id )) onmouseover=@(() => { Hover = item.Id; StateHasChanged(); }) onmouseout=@(() => { if ( Hover == item.Id ) { Hover = -2; StateHasChanged(); } })>
<div class="pic" style="background-image: url('@(Catalog.ItemArt( item.Src ))')"></div>
<div class="price">@(item.Owned ? (item.Worn ? "worn" : "owned") : $"{Gm.Price( item.Price )}g")</div>
@if ( Hover == item.Id )
{
<div class="hover-label">@item.Name</div>
}
</div>
}
</div>
<div class="pager">
@if ( Pages > 1 )
{
<div class="sas-arrow left" onclick=@(() => { Page = (Page + Pages - 1) % Pages; StateHasChanged(); })></div>
<div class="page">@($"{Page + 1} / {Pages}")</div>
<div class="sas-arrow right" onclick=@(() => { Page = (Page + 1) % Pages; StateHasChanged(); })></div>
}
@if ( Selected >= 0 )
{
<div class="btn" onclick=@Buy>@BuyLabel</div>
}
</div>
</div>
<div class="gold-bar"><div class="coin"></div>@P.Gold</div>
<div class="sas-round cross close" onclick=@(() => Gm.Go( GameScreen.Town ))><div class="mark"></div></div>
</root>
@code
{
public bool Armoury { get; set; }
record Item( int Id, int Src, string Name, int Price, bool Locked, bool Owned, bool Worn );
const int PerPage = 32;
GameManager Gm => GameManager.Instance;
Profile P => Profile.Current;
GearSlot Slot = GearSlot.Chest;
int Selected = -1;
int Hover = -2;
int Page;
string speech;
string Greeting => Armoury
? "Armour, eh? Pick a piece. If it's blue, you're not ready for it yet."
: "Weapons! Sharp ones, heavy ones. The blue ones need more strength than you've got.";
string Speech
{
get => speech ?? Greeting;
set => speech = value;
}
List<Item> Items => Armoury
? Catalog.Gear( Slot ).Select( g => new Item( g.Index, g.Src, g.Name, g.Price, P.Level < g.Level && !P.Owns( Slot, g.Index ), P.Owns( Slot, g.Index ), P.Gear[(int)Slot] == g.Index ) ).ToList()
: Catalog.Weapons.Skip( 1 ).Select( w => new Item( w.Id, w.Src, w.Name, w.Price, P.Strength < w.Strength && !P.OwnedWeapons.Contains( w.Id ), P.OwnedWeapons.Contains( w.Id ), P.Weapon == w.Id ) ).ToList();
int Pages => Math.Max( 1, (Items.Count + PerPage - 1) / PerPage );
IEnumerable<Item> PageItems => Items.Skip( Page * PerPage ).Take( PerPage );
string BuyLabel
{
get
{
if ( Armoury )
{
if ( P.Owns( Slot, Selected ) ) return P.Gear[(int)Slot] == Selected ? "take off" : "wear it";
return $"buy for {Gm.Price( Catalog.GearItem( Slot, Selected ).Price )} gold";
}
if ( P.OwnedWeapons.Contains( Selected ) ) return P.Weapon == Selected ? "already held" : "hold it";
return $"buy for {Gm.Price( Catalog.Weapons[Selected].Price )} gold";
}
}
void Pick( int id )
{
Selected = id;
if ( Armoury )
{
var g = Catalog.GearItem( Slot, id );
Speech = P.Level < g.Level && !P.Owns( Slot, id )
? $"{g.Name}\nRequired level {g.Level}\nThis item is not available."
: $"{g.Name}\n+{g.Points} armour\nYour price, {Gm.Price( g.Price )} gold.";
}
else
{
var w = Catalog.Weapons[id];
var ench = P.EnchantFor( id );
string magic = ench is null ? "" : $"\nEnchanted: +{Catalog.EnchantRange( ench.Tier ).Min}-{Catalog.EnchantRange( ench.Tier ).Max} {ench.Type.ToString().ToLower()}";
Speech = P.Strength < w.Strength && !P.OwnedWeapons.Contains( id )
? $"{w.Name}\n{w.Min} - {w.Max} damage\nNeeds {w.Strength} strength. Not for you yet."
: $"{w.Name}\n{w.Min} - {w.Max} damage (+{P.Strength * 2} from strength){magic}\nYour price, {Gm.Price( w.Price )} gold.";
}
StateHasChanged();
}
void Buy()
{
if ( Selected < 0 ) return;
Speech = Armoury ? Gm.BuyGear( Slot, Selected ) : Gm.BuyWeapon( Selected );
StateHasChanged();
}
protected override int BuildHash() => HashCode.Combine( Armoury, Slot, Selected, speech, Page, Hover, HashCode.Combine( P?.Gold, P?.Weapon, P?.Gear[(int)Slot] ) );
}