ported from perforce
This commit is contained in:
349
DonkeysAndDroids.Godot/Tooltip.cs
Normal file
349
DonkeysAndDroids.Godot/Tooltip.cs
Normal file
@@ -0,0 +1,349 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using Godot;
|
||||
using RobotAndDonkey.Game.Board;
|
||||
using RobotAndDonkey.Game.Cards;
|
||||
using RobotAndDonkey.Game.Data;
|
||||
using RobotAndDonkey.Game.GameState;
|
||||
using RobotAndDonkey.Game.Modifiers;
|
||||
using RobotAndDonkey.Game.Pois;
|
||||
|
||||
public partial class Tooltip : Control
|
||||
{
|
||||
public override void _Ready()
|
||||
{
|
||||
Instance = this;
|
||||
|
||||
m_Label = GetNode<RichTextLabel>("RichText");
|
||||
m_Label.BbcodeEnabled = true;
|
||||
m_Label.AutowrapMode = TextServer.AutowrapMode.Word;
|
||||
m_Label.ScrollActive = true;
|
||||
}
|
||||
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
UpdateGamepadScroll((float)delta);
|
||||
}
|
||||
|
||||
private void UpdateGamepadScroll(float delta)
|
||||
{
|
||||
if (m_Label == null || !Visible)
|
||||
return;
|
||||
|
||||
var axis = Input.GetActionStrength("tooltip_scroll_down") - Input.GetActionStrength("tooltip_scroll_up");
|
||||
|
||||
if (Mathf.Abs(axis) < 0.1f)
|
||||
return;
|
||||
|
||||
var vbar = m_Label.GetVScrollBar();
|
||||
if (vbar == null)
|
||||
return;
|
||||
|
||||
vbar.Value += axis * GamepadScrollSpeed * delta;
|
||||
}
|
||||
|
||||
public void Describe(Cell cell)
|
||||
{
|
||||
Begin();
|
||||
AppendCell(cell);
|
||||
Commit();
|
||||
}
|
||||
|
||||
public void Describe(Card card)
|
||||
{
|
||||
Begin();
|
||||
AppendCard(card);
|
||||
Commit();
|
||||
}
|
||||
|
||||
private void Begin()
|
||||
{
|
||||
m_Builder.Clear();
|
||||
}
|
||||
|
||||
private void Commit()
|
||||
{
|
||||
if (m_Label == null)
|
||||
return;
|
||||
|
||||
m_Label.Text = m_Builder.ToString();
|
||||
m_Label.ScrollToLine(0);
|
||||
}
|
||||
|
||||
private static string WrapColor(string text, string colorHex)
|
||||
{
|
||||
return $"[color={colorHex}]{text}[/color]";
|
||||
}
|
||||
|
||||
private void AppendTitle(string title, string subtitle = null)
|
||||
{
|
||||
m_Builder.Append(WrapColor($"[b]{title}[/b]", ColorTitle));
|
||||
|
||||
if (!string.IsNullOrEmpty(subtitle))
|
||||
{
|
||||
m_Builder.Append(' ');
|
||||
m_Builder.Append(WrapColor(subtitle, ColorSubtitle));
|
||||
}
|
||||
|
||||
m_Builder.Append('\n');
|
||||
}
|
||||
|
||||
private void AppendSectionHeader(string title)
|
||||
{
|
||||
m_Builder.Append('\n');
|
||||
m_Builder.Append(WrapColor($"[b]{title}[/b]", ColorHeader));
|
||||
m_Builder.Append('\n');
|
||||
}
|
||||
|
||||
private void AppendKeyValue(string key, string value)
|
||||
{
|
||||
m_Builder.Append(WrapColor($"{key}: ", ColorLabel)).Append(WrapColor(value, ColorText)).Append('\n');
|
||||
}
|
||||
|
||||
private void AppendBlankLine()
|
||||
{
|
||||
m_Builder.Append('\n');
|
||||
}
|
||||
|
||||
private void AppendCell(Cell cell)
|
||||
{
|
||||
var subtitle = cell.Hex.ToString();
|
||||
AppendTitle("Cell", subtitle);
|
||||
|
||||
var surfaceColor = GetCellColor(cell.Type);
|
||||
AppendKeyValue("Surface", WrapColor(cell.Type.ToString(), surfaceColor));
|
||||
m_Builder.Append(WrapColor(GetCellDescription(cell.Type), ColorText));
|
||||
m_Builder.Append('\n');
|
||||
|
||||
if (cell.Poi != null)
|
||||
{
|
||||
Main.Instance.Music.Play(cell.Poi);
|
||||
AppendPoi(cell.Poi);
|
||||
}
|
||||
else
|
||||
{
|
||||
Main.Instance.Music.Play(cell.Type);
|
||||
}
|
||||
|
||||
AppendModifiers("Cell", cell);
|
||||
}
|
||||
|
||||
public static string GetCellDescription(ECellType cellType)
|
||||
{
|
||||
return cellType switch
|
||||
{
|
||||
ECellType.Grass => "Plain and simple terrain, suitable for most tasks.",
|
||||
ECellType.Dry => $"Resting replenishes {WrapColor($"{Balancing.Instance.DryRestEnergyMalus} less energy", ColorBad)} and interacting costs {WrapColor($"{Balancing.Instance.DryInteractEnergyMalus} more energy", ColorBad)}.",
|
||||
ECellType.Fertile => $"Replenish {WrapColor($"{Balancing.Instance.FertileRestEnergyReplenish} more energy", ColorGood)} while resting here.",
|
||||
ECellType.Mud => $"Movement is very difficult and costs {WrapColor($"{Balancing.Instance.MudMoveEnergyCost} more energy", ColorBad)}.",
|
||||
ECellType.Blocked => "Can't walk here, try jumping or flying.",
|
||||
ECellType.Rocky => "When entering, programs have a high risk of race conditions.",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(cellType), cellType, null)
|
||||
};
|
||||
}
|
||||
|
||||
private string GetCellColor(ECellType type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
ECellType.Grass => "#9ccc65",
|
||||
ECellType.Dry => "#ffcc80",
|
||||
ECellType.Fertile => "#a5d6a7",
|
||||
ECellType.Mud => "#8d6e63",
|
||||
ECellType.Blocked => "#b0bec5",
|
||||
ECellType.Rocky => "#b39ddb",
|
||||
_ => ColorText
|
||||
};
|
||||
}
|
||||
|
||||
private void AppendPoi(Poi poi)
|
||||
{
|
||||
switch (poi)
|
||||
{
|
||||
case Avatar:
|
||||
AppendRobot(Main.Instance.CoreLoop.Robot);
|
||||
break;
|
||||
|
||||
case Shed shed:
|
||||
{
|
||||
var summary = $"Requested {shed.Requested}\n" + $"Received {shed.Received}\n" + $"Remaining {shed.Remaining}";
|
||||
AppendPoiBlock("Shed", summary, poi);
|
||||
break;
|
||||
}
|
||||
|
||||
case Crate crate:
|
||||
AppendPoiBlock("Crate", $"Contains {crate.Amount} goods", poi);
|
||||
break;
|
||||
|
||||
case Tower tower:
|
||||
AppendPoiBlock("Tower", tower.Active ? WrapColor("Active", ColorBad) : WrapColor("Disabled", ColorGood), poi);
|
||||
break;
|
||||
|
||||
case Donkey:
|
||||
AppendPoiBlock("Donkey", string.Empty, poi);
|
||||
break;
|
||||
|
||||
default:
|
||||
AppendPoiBlock(poi.GetType().Name, string.Empty, poi);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void AppendPoiBlock(string title, string body, Poi poi)
|
||||
{
|
||||
AppendSectionHeader(title);
|
||||
m_Builder.Append("[indent]\n");
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(body))
|
||||
{
|
||||
m_Builder.Append(WrapColor(body, ColorText));
|
||||
m_Builder.Append("\n\n");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(poi.Tooltip))
|
||||
{
|
||||
m_Builder.Append(WrapColor(poi.Tooltip, ColorText));
|
||||
m_Builder.Append('\n');
|
||||
|
||||
var tooltipModifiers = poi.TooltipModifiers;
|
||||
if (tooltipModifiers.Length > 0)
|
||||
{
|
||||
AppendSectionHeader("Related:");
|
||||
foreach (var modifier in tooltipModifiers)
|
||||
AppendModifier(modifier);
|
||||
}
|
||||
}
|
||||
|
||||
m_Builder.Append("[/indent]\n");
|
||||
}
|
||||
|
||||
private void AppendRobot(RobotAndDonkey.Game.Robots.Robot robot)
|
||||
{
|
||||
AppendSectionHeader(Main.Instance.CoreLoop.Robot.Type.ToString());
|
||||
m_Builder.Append("[indent]\n");
|
||||
|
||||
AppendKeyValue("Programs", robot.ProgramCount.ToString());
|
||||
AppendCurrency(robot.Currency);
|
||||
|
||||
AppendModifiers("Robot", robot);
|
||||
|
||||
m_Builder.Append("[/indent]\n");
|
||||
}
|
||||
|
||||
private void AppendCurrency(Currency currency)
|
||||
{
|
||||
AppendKeyValue("Remaining energy", currency.Energy.ToString());
|
||||
AppendKeyValue("Good carried", $"{currency.Carry}/{currency.MaxCarry}");
|
||||
AppendKeyValue("Completed deliveries", currency.Delivery.ToString());
|
||||
AppendKeyValue("Tape length", currency.TapeLength.ToString());
|
||||
AppendKeyValue("Hand size", currency.HandSize.ToString());
|
||||
}
|
||||
|
||||
private void AppendCard(Card card)
|
||||
{
|
||||
var rarityColor = GetRarityColor(card.Rarity);
|
||||
var rarityText = WrapColor(card.Rarity.ToString(), rarityColor);
|
||||
var subtitle = $"\n{rarityText} {card.CardType}";
|
||||
|
||||
AppendTitle(card.Name, subtitle);
|
||||
|
||||
AppendSectionHeader("Costs");
|
||||
m_Builder.Append("[indent]\n");
|
||||
AppendKeyValue("Shop", card.ShopCost.ToString());
|
||||
AppendKeyValue("Play", card.PlayCost.ToString());
|
||||
m_Builder.Append("[/indent]\n");
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(card.ToolTip))
|
||||
{
|
||||
AppendSectionHeader("Effect");
|
||||
m_Builder.Append("[indent]\n");
|
||||
m_Builder.Append(WrapColor(card.ToolTip, ColorText));
|
||||
m_Builder.Append('\n');
|
||||
|
||||
var tooltipModifiers = card.TooltipModifiers;
|
||||
if (tooltipModifiers.Length > 0)
|
||||
{
|
||||
AppendSectionHeader("Related:");
|
||||
foreach (var modifier in tooltipModifiers)
|
||||
AppendModifier(modifier);
|
||||
}
|
||||
|
||||
m_Builder.Append("[/indent]\n");
|
||||
}
|
||||
|
||||
AppendModifiers("Card", card);
|
||||
}
|
||||
|
||||
private string GetRarityColor(ERarity rarity)
|
||||
{
|
||||
return rarity switch
|
||||
{
|
||||
ERarity.Common => "#FFFFFF",
|
||||
ERarity.Magic => "#4CFF4C",
|
||||
ERarity.Uncommon => "#4C99FF",
|
||||
ERarity.Rare => "#CC4CFF",
|
||||
ERarity.Legendary => "#FF8033",
|
||||
_ => ColorText
|
||||
};
|
||||
}
|
||||
|
||||
private void AppendModifiers(string entityName, Entity entity)
|
||||
{
|
||||
if (entity.Modifiers.Count == 0)
|
||||
return;
|
||||
|
||||
AppendSectionHeader($"{entityName} modifiers");
|
||||
m_Builder.Append("[indent]\n");
|
||||
foreach (var modifier in entity.Modifiers)
|
||||
AppendModifier(modifier);
|
||||
m_Builder.Append("[/indent]\n");
|
||||
}
|
||||
|
||||
private void AppendModifier(Modifier modifier)
|
||||
{
|
||||
var debuffed = modifier.DebuffSources.Count > 0;
|
||||
var header = $"{modifier.Id} [{modifier.Duration}]";
|
||||
|
||||
if (debuffed)
|
||||
{
|
||||
m_Builder.Append(WrapColor($"[s]{header}[/s]", ColorMuted));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Builder.Append(WrapColor(header, ColorModifier));
|
||||
}
|
||||
|
||||
m_Builder.Append('\n');
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(modifier.ToolTip))
|
||||
{
|
||||
m_Builder.Append(WrapColor(modifier.ToolTip, ColorText));
|
||||
m_Builder.Append('\n');
|
||||
}
|
||||
|
||||
if (debuffed)
|
||||
{
|
||||
m_Builder.Append(WrapColor(" (Debuffed)", ColorMuted));
|
||||
m_Builder.Append('\n');
|
||||
}
|
||||
}
|
||||
|
||||
public static Tooltip Instance { get; private set; }
|
||||
|
||||
private const string ColorTitle = "#ffd65c";
|
||||
private const string ColorSubtitle = "#aaaaaa";
|
||||
private const string ColorHeader = "#a5d6ff";
|
||||
private const string ColorLabel = "#cccccc";
|
||||
private const string ColorText = "#ffffff";
|
||||
private const string ColorGood = "#a5d6a7";
|
||||
private const string ColorBad = "#ef9a9a";
|
||||
private const string ColorMuted = "#9e9e9e";
|
||||
private const string ColorModifier = "#ffcc80";
|
||||
|
||||
private readonly StringBuilder m_Builder = new();
|
||||
|
||||
[Export]
|
||||
public float GamepadScrollSpeed = 800f;
|
||||
|
||||
private RichTextLabel m_Label;
|
||||
}
|
||||
Reference in New Issue
Block a user