using System.Text; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using Outnumbered.Engine; namespace Outnumbered; // The survival between-wave card DRAFT overlay — the 3-card world-text render. // The draft's input + screen dispatch (ShopScreen.CardDraft, ExecuteOption, the menu-key handling) stays in Shop.cs; this // partial owns only the panel rendering (create / update / build-text). All state is the shared ShopSession + Config.Shop. public sealed partial class OutnumberedPlugin { // A single survival-draft card panel — centre-justified, chunkier background so each reads as its own "card". private CPointWorldText? CreateCardPanel() { var s = Config.Shop; return WorldText.Create(s.FontSize, s.WorldUnitsPerPx, s.FontName, System.Drawing.Color.FromArgb(255, s.ColorR, s.ColorG, s.ColorB), s.DrawBackground, 0.35f, PointWorldTextJustifyHorizontal_t.POINT_WORLD_TEXT_JUSTIFY_HORIZONTAL_CENTER); } // The survival between-wave draft: up to 3 cards side by side (centre card at RightOffset, the others ± CardSpread). private void UpdateDraftPanels(CCSPlayerController p, ShopSession s, Vector eye, Vector fwd, Vector right, Vector up, QAngle ang) { var cfg = Config.Shop; var draw = Draft is { } sd ? sd.CurrentDraw(p) : new(); int n = Math.Min(draw.Count, s.Cards.Length); // cards actually shown (1..3) for (int i = 0; i < s.Cards.Length; i++) { if (i >= n) // fewer than 3 cards left (pool nearly exhausted) -> drop the spare panel { WorldText.Destroy(ref s.Cards[i]); s.CardText[i] = null; continue; } if (s.Cards[i] is null || !s.Cards[i]!.IsValid) { s.Cards[i] = CreateCardPanel(); s.CardText[i] = null; } var card = s.Cards[i]; if (card is null) continue; string txt = BuildCardPanel(p, draw[i].key, GrenadeMenuKeys[i]); // grenade keys 6/7/8 (-> [HE]/[Flash]/[Smoke] labels) if (s.CardText[i] != txt) { WorldText.SetText(card, txt); s.CardText[i] = txt; } float x = (i - (n - 1) / 2f) * cfg.CardSpread; // centre the row regardless of card count (1/2/3) WorldText.Place(card, eye + fwd * cfg.ForwardOffset + right * (cfg.RightOffset + x) + up * cfg.UpOffset, ang); } } // One card's text: the key to press, the card name + count, and the current -> next value so you know what you get. private string BuildCardPanel(CCSPlayerController p, string key, char menuKey) { if (Draft is not { } sd || sd.CardInfo(p, key) is not { } v) return " "; string u = v.Flat ? "" : "%"; var sb = new StringBuilder(); sb.Append($"[ {KeyItemLabel(menuKey)} ]\n"); sb.Append($"{v.Name} [{v.Have}/{v.Cap}]\n"); if (v.Detail is not null) sb.Append(v.Detail); // effect cards: a single descriptive line else { sb.Append($"Now: +{v.Now:0}{u}\n"); sb.Append($"Next: +{v.Next:0}{u}"); } // stat cards: current -> next return sb.ToString(); } }