A UI Razor component that renders a perk icon for the game. It computes visual state (rotation, scale, opacity, progress, rarity tint, cooldown, highlights) and handles mouse interactions to show hover state and to allow click/right-click addon/removal perks via PerkClickAdd/PerkClickRemove.
@namespace Sandbox
@using Sandbox;
@using Sandbox.UI;
@using System;
@inherits Panel
@attribute [StyleSheet("PerkIcon.razor.scss")]
@{
var player = Manager.Instance.LocalPlayer;
var rot = Angle + Perk.IconAngleOffset;
var scale = Perk.IconScale;
const float levelUpAnimDuration = 0.5f;
var levelUpScale = Perk.RealTimeSinceLevelUp < levelUpAnimDuration
? Utils.Map( Perk.RealTimeSinceLevelUp, 0f, levelUpAnimDuration, 1.75f, 1.0f, EasingType.QuadOut )
: 1.0f;
}
<root style="transform: rotate(@(rot)deg) scale(@(scale * levelUpScale));">
@{
// float opacity = (SS2Game.Current.IsGameOver || SS2Game.Current.SelectedPlayer != null) ? 4f : Utils.Map(Item.TimeSinceLevelUp, 0f, 3f, 4f, 1f);
float opacity = Utils.Map( Math.Min( Perk.RealTimeSinceLevelUp, Perk.RealTimeSinceLevelDown ), 0f, 3f, 4f, 1f);
<!-- todo: cache these -->
var attrib = TypeLibrary.GetType(Perk.GetType()).GetAttribute<PerkAttribute>();
var rarity = attrib.Rarity;
var curse = attrib.Curse;
var highlightColor = PerkManager.GetCardRarityColor(rarity, curse, alpha: 0.7f);
var rarityBgTint = PerkManager.GetCardRarityColor(rarity, curse);
var width = Math.Clamp(Perk.Level / (float)Perk.MaxLevel, 0f, 1f) * 100f;
var maxLevel = PerkManager.GetMaxLevelForRarity(rarity);
}
<panel class="rarity" style="opacity: @opacity; background-color: @highlightColor.Rgba; background-image-tint:@rarityBgTint.Rgba;"></panel>
@if (!curse && maxLevel > 1)
{
// @if (Perk.Level > (IsChoice ? 1 : 0))
// {
<panel class="progress" style="width:100%; background-color:@(new Color(0f, 0f, 0f, IsChoice ? 0.3f : 0.6f).Rgba); z-index: 1;"></panel>
// }
<panel class="progress" style="width:@(width)%; background-color:@highlightColor.Rgba; z-index: 2;"></panel>
}
<panel class="icon" style="background-image: url(@(Perk.GetImagePath( Perk.GetType() ))); background-color:@rarityBgTint.Rgba; opacity: @opacity;" />
@if (Perk.Level > Perk.MaxLevel)
{
<div class="maxed">X</div>
}
@if ( !IsChoice && Perk.DisplayCooldown > 0f) // && !Manager.Instance.IsGameOver
{
<div class="cooldown" style="width:@(Math.Clamp(Perk.DisplayCooldown, 0f, 1f) * 100f)%; opacity:@(Utils.Map(Parent.Opacity, 0.3f, 1f, 1.3f, 0.75f)); background-color:@(Perk.DisplayCooldownColor.Rgba);"></div>
}
@if ( !string.IsNullOrEmpty(Perk.DisplayText)) //&& !Manager.Instance.IsGameOver && SS2Game.Current.SelectedPlayer == null)
{
<label class="display_text" style="color:@(Perk.DisplayTextColor.Rgba); opacity:@Perk.DisplayTextOpacity">@Perk.DisplayText</label>
}
@if (Banished)
{
<div class="banish">X</div>
}
@if (Perk.RealTimeSinceHighlight < Perk.HighlightDuration)
{
<div class="highlight" style="opacity:@(Utils.Map( Perk.RealTimeSinceHighlight, 0f, Perk.HighlightDuration, Perk.HighlightOpacity, 0f, EasingType.SineOut)); background-color:@(Perk.HighlightColor.Rgba);"></div>
}
@if(Perk.RealTimeSinceLevelDown < 3f)
{
<div class="deleveled" style="opacity:@(Utils.Map( Perk.RealTimeSinceLevelDown, 0f, 3f, 4f, 0f, EasingType.QuadOut));"></div>
}
</root>
@code
{
public Perk Perk { get; set; }
public bool NoTips { get; set; } = false;
public bool Banished;
public float Angle { get; set; }
public float Scale { get; set; }
public bool IsChoice { get; set; }
protected override void OnMouseOver(MousePanelEvent e)
{
if (e.Target != this || NoTips || Perk == null)
return;
Manager.Instance.HoveredPerkType = TypeLibrary.GetType( Perk.GetType() );
Manager.Instance.HoveredPerkPanel = this;
Manager.Instance.HoveredPerkLevel = Perk.Level;
Manager.Instance.IsHoveredPerkBanished = Banished;
Manager.Instance.IsHoveredPerkAChoice = IsChoice;
Manager.Instance.IsHoveredPerkHidden = false;
Manager.Instance.HoveredPlayer = null;
Manager.Instance.HoveredPlayerIcon = null;
}
protected override void OnMouseOut(MousePanelEvent e)
{
if ( Manager.Instance.HoveredPerkPanel != this ) return;
Manager.Instance.HoveredPerkType = null;
Manager.Instance.HoveredPerkPanel = null;
Manager.Instance.IsHoveredPerkBanished = false;
}
protected override void OnAfterTreeRender ( bool firstTime )
{
base.OnAfterTreeRender( firstTime );
if ( !IsVisible && Manager.Instance.HoveredPerkPanel == this )
{
Manager.Instance.HoveredPerkType = null;
Manager.Instance.HoveredPerkPanel = null;
Manager.Instance.IsHoveredPerkBanished = false;
}
}
protected override int BuildHash()
{
var fadeHash = Math.Min(Perk.RealTimeSinceLevelUp, Perk.RealTimeSinceLevelDown) < 3f ? RealTime.Now : 0f;
var highlightHash = Perk.RealTimeSinceHighlight.Relative < Perk.HighlightDuration ? Perk.RealTimeSinceHighlight.Relative : 0f;
var cooldownHash = Perk.DisplayCooldown > 0f ? HashCode.Combine(Perk.DisplayCooldown, Parent.Opacity, Perk.DisplayCooldownColor) : 0f;
var textHash = !string.IsNullOrEmpty(Perk.DisplayText) ? HashCode.Combine(Perk.DisplayText, Perk.DisplayTextColor, Perk.DisplayTextOpacity) : 0f;
var transformHash = HashCode.Combine(Angle, Perk.IconAngleOffset, Perk.IconScale);
return HashCode.Combine(
Perk.Level,
fadeHash,
textHash,
Manager.Instance.IsGameOver,
cooldownHash,
highlightHash,
transformHash
);
}
protected override void OnClick(MousePanelEvent e)
{
// if non-local player is selected, do nothing
if (Manager.Instance.SelectedPlayer.IsValid())
return;
var player = Manager.Instance.LocalPlayer;
if ( !player.IsValid() )
return;
if( player.Stats[PlayerStat.ClickAddPerk] > 0f )
{
var perkType = TypeLibrary.GetType( typeof( PerkClickAdd ) );
if ( player.HasPerk( perkType ) )
{
var perk = player.GetPerk( perkType ) as PerkClickAdd;
if ( perk != null )
{
perk.Activate(TypeLibrary.GetType(Perk.GetType()));
Manager.Instance.HoveredPerkType = null;
Manager.Instance.IsHoveredPerkBanished = false;
e.StopPropagation();
}
}
}
}
protected override void OnRightClick(MousePanelEvent e)
{
// if non-local player is selected, do nothing
if (Manager.Instance.SelectedPlayer.IsValid())
return;
var player = Manager.Instance.LocalPlayer;
if ( !player.IsValid() )
return;
if( player.Stats[PlayerStat.ClickRemovePerk] > 0f )
{
var perkType = TypeLibrary.GetType( typeof( PerkClickRemove ) );
if ( player.HasPerk( perkType ) )
{
var perk = player.GetPerk( perkType ) as PerkClickRemove;
if ( perk != null )
{
perk.Activate(TypeLibrary.GetType(Perk.GetType()));
Manager.Instance.HoveredPerkType = null;
Manager.Instance.IsHoveredPerkBanished = false;
e.StopPropagation();
}
}
}
// player.LevelDownPerk(TypeLibrary.GetType(Perk.GetType()));
}
}