Implement more UX and cards for other distros
This commit is contained in:
@@ -19,3 +19,13 @@ MonoBehaviour:
|
||||
- {fileID: 11400000, guid: 3d57857f3f30419c8be4c44914c5abbe, type: 2}
|
||||
- {fileID: 11400000, guid: 4cae271a0f4146c59aab74e4c9d6d0f8, type: 2}
|
||||
- {fileID: 11400000, guid: 5fef058a72b54b4aa2b2dd8f4d08bfe5, type: 2}
|
||||
- {fileID: 11400000, guid: feda0000000000000000000000000001, type: 2}
|
||||
- {fileID: 11400000, guid: feda0000000000000000000000000002, type: 2}
|
||||
- {fileID: 11400000, guid: feda0000000000000000000000000003, type: 2}
|
||||
- {fileID: 11400000, guid: feda0000000000000000000000000004, type: 2}
|
||||
- {fileID: 11400000, guid: feda0000000000000000000000000005, type: 2}
|
||||
- {fileID: 11400000, guid: c1a50000000000000000000000000001, type: 2}
|
||||
- {fileID: 11400000, guid: c1a50000000000000000000000000002, type: 2}
|
||||
- {fileID: 11400000, guid: c1a50000000000000000000000000003, type: 2}
|
||||
- {fileID: 11400000, guid: c1a50000000000000000000000000004, type: 2}
|
||||
- {fileID: 11400000, guid: c1a50000000000000000000000000005, type: 2}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5178747fac4dbfc448ff15d8a687e03c, type: 3}
|
||||
m_Name: BorrowChecker
|
||||
m_EditorClassIdentifier:
|
||||
id: fedora_borrow_checker
|
||||
displayName: borrow checker
|
||||
description: gain 8 shield. if this is the first card played this turn, gain 8 more.
|
||||
flavorText: no aliasing, no panic.
|
||||
language: 2
|
||||
rarity: 0
|
||||
cycleCost: 1
|
||||
resolutionTrack: 0
|
||||
distroExclusive: 1
|
||||
isToken: 0
|
||||
designNotes: defensive first-card payoff; should benefit from Bleeding Edge cost discount but not damage multiplier.
|
||||
upgradeTarget: {fileID: 0}
|
||||
effects: []
|
||||
@@ -0,0 +1,27 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5178747fac4dbfc448ff15d8a687e03c, type: 3}
|
||||
m_Name: CargoBuildRelease
|
||||
m_EditorClassIdentifier:
|
||||
id: fedora_cargo_build
|
||||
displayName: cargo build --release
|
||||
description: deal 10. never misses. overkill becomes shield.
|
||||
flavorText: optimized, audited, shipped hot.
|
||||
language: 2
|
||||
rarity: 0
|
||||
cycleCost: 1
|
||||
resolutionTrack: 0
|
||||
distroExclusive: 1
|
||||
isToken: 0
|
||||
designNotes: crash-immune Fedora finisher; Rust guaranteed hit; convert excess damage into shield after lethal calculation.
|
||||
upgradeTarget: {fileID: 0}
|
||||
effects: []
|
||||
@@ -0,0 +1,27 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5178747fac4dbfc448ff15d8a687e03c, type: 3}
|
||||
m_Name: DnfUpdate
|
||||
m_EditorClassIdentifier:
|
||||
id: fedora_dnf_update
|
||||
displayName: dnf update
|
||||
description: deal 9. costs 1 less per java card played this combat (min 0).
|
||||
flavorText: today everything gets newer.
|
||||
language: 8
|
||||
rarity: 0
|
||||
cycleCost: 2
|
||||
resolutionTrack: 0
|
||||
distroExclusive: 1
|
||||
isToken: 0
|
||||
designNotes: Java ramp card; cost reduction counts prior Java cards played this combat and clamps at 0.
|
||||
upgradeTarget: {fileID: 0}
|
||||
effects: []
|
||||
@@ -0,0 +1,27 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5178747fac4dbfc448ff15d8a687e03c, type: 3}
|
||||
m_Name: Rawhide
|
||||
m_EditorClassIdentifier:
|
||||
id: fedora_rawhide
|
||||
displayName: rawhide
|
||||
description: draw 2. the next card you play this turn gains bleeding edge's discount and crash risk.
|
||||
flavorText: straight from tomorrow's mirror.
|
||||
language: 8
|
||||
rarity: 1
|
||||
cycleCost: 0
|
||||
resolutionTrack: 0
|
||||
distroExclusive: 1
|
||||
isToken: 0
|
||||
designNotes: Rare setup; grants next-card temporary Bleeding Edge discount plus crash-risk hook even if first-card window has passed.
|
||||
upgradeTarget: {fileID: 0}
|
||||
effects: []
|
||||
@@ -0,0 +1,27 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5178747fac4dbfc448ff15d8a687e03c, type: 3}
|
||||
m_Name: SELinuxEnforcing
|
||||
m_EditorClassIdentifier:
|
||||
id: fedora_selinux
|
||||
displayName: SELinux enforcing
|
||||
description: the next 2 enemy attacks deal half damage.
|
||||
flavorText: denied means denied.
|
||||
language: 2
|
||||
rarity: 1
|
||||
cycleCost: 2
|
||||
resolutionTrack: 0
|
||||
distroExclusive: 1
|
||||
isToken: 0
|
||||
designNotes: crash-immune Rare mitigation; apply two attack-damage-halving charges to incoming enemy attacks.
|
||||
upgradeTarget: {fileID: 0}
|
||||
effects: []
|
||||
@@ -0,0 +1,27 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5178747fac4dbfc448ff15d8a687e03c, type: 3}
|
||||
m_Name: Cinnamon
|
||||
m_EditorClassIdentifier:
|
||||
id: mint_cinnamon
|
||||
displayName: cinnamon
|
||||
description: "queue: gain 3 shield. draw 1."
|
||||
flavorText: a familiar desktop, a calmer turn.
|
||||
language: 3
|
||||
rarity: 0
|
||||
cycleCost: 0
|
||||
resolutionTrack: 1
|
||||
distroExclusive: 1
|
||||
isToken: 0
|
||||
designNotes: simple deterministic queue value; shield plus card replacement on resolve.
|
||||
upgradeTarget: {fileID: 0}
|
||||
effects: []
|
||||
@@ -0,0 +1,27 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5178747fac4dbfc448ff15d8a687e03c, type: 3}
|
||||
m_Name: FixBroken
|
||||
m_EditorClassIdentifier:
|
||||
id: mint_fix_broken
|
||||
displayName: apt --fix-broken
|
||||
description: deal exactly 8. remove one debuff from mint.
|
||||
flavorText: repair the package, keep moving.
|
||||
language: 4
|
||||
rarity: 0
|
||||
cycleCost: 1
|
||||
resolutionTrack: 0
|
||||
distroExclusive: 1
|
||||
isToken: 0
|
||||
designNotes: fixed JavaScript damage for Mint plus one self-cleanse; bypass spike-damage systems.
|
||||
upgradeTarget: {fileID: 0}
|
||||
effects: []
|
||||
@@ -0,0 +1,27 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5178747fac4dbfc448ff15d8a687e03c, type: 3}
|
||||
m_Name: Nemo
|
||||
m_EditorClassIdentifier:
|
||||
id: mint_nemo
|
||||
displayName: nemo
|
||||
description: deal exactly 6. if mint has any shield, deal exactly 6 again.
|
||||
flavorText: open folder, solve problem.
|
||||
language: 4
|
||||
rarity: 0
|
||||
cycleCost: 0
|
||||
resolutionTrack: 0
|
||||
distroExclusive: 1
|
||||
isToken: 0
|
||||
designNotes: fixed JavaScript damage; conditional second fixed hit if Mint currently has shield.
|
||||
upgradeTarget: {fileID: 0}
|
||||
effects: []
|
||||
@@ -0,0 +1,27 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5178747fac4dbfc448ff15d8a687e03c, type: 3}
|
||||
m_Name: TimeshiftSnapshot
|
||||
m_EditorClassIdentifier:
|
||||
id: mint_timeshift
|
||||
displayName: timeshift snapshot
|
||||
description: "queue: record uptime now. at end of your next turn, restore to it if lower."
|
||||
flavorText: save point created before touching anything scary.
|
||||
language: 3
|
||||
rarity: 1
|
||||
cycleCost: 1
|
||||
resolutionTrack: 1
|
||||
distroExclusive: 1
|
||||
isToken: 0
|
||||
designNotes: deterministic safety queue; record current uptime and restore at delayed checkpoint only if current uptime is lower.
|
||||
upgradeTarget: {fileID: 0}
|
||||
effects: []
|
||||
@@ -0,0 +1,27 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5178747fac4dbfc448ff15d8a687e03c, type: 3}
|
||||
m_Name: UpdateManager
|
||||
m_EditorClassIdentifier:
|
||||
id: mint_update_manager
|
||||
displayName: update manager
|
||||
description: "queue: deal exactly 5 to all enemies. repeats at the end of your next turn."
|
||||
flavorText: green checks all the way down.
|
||||
language: 3
|
||||
rarity: 1
|
||||
cycleCost: 1
|
||||
resolutionTrack: 1
|
||||
distroExclusive: 1
|
||||
isToken: 0
|
||||
designNotes: Rare deterministic queue aoe; schedules one identical delayed repeat at next-turn end.
|
||||
upgradeTarget: {fileID: 0}
|
||||
effects: []
|
||||
@@ -15,6 +15,7 @@ MonoBehaviour:
|
||||
id: ubuntu_ask_ubuntu
|
||||
displayName: ask ubuntu
|
||||
description: "queue: draw 2 cards."
|
||||
flavorText: somebody solved this in 2014.
|
||||
language: 3
|
||||
rarity: 0
|
||||
cycleCost: 0
|
||||
|
||||
@@ -15,6 +15,7 @@ MonoBehaviour:
|
||||
id: ubuntu_do_release_upgrade
|
||||
displayName: do-release-upgrade
|
||||
description: upgrade 1-3 random cards in your hand this combat.
|
||||
flavorText: this will probably be fine.
|
||||
language: 4
|
||||
rarity: 1
|
||||
cycleCost: 2
|
||||
|
||||
@@ -15,6 +15,7 @@ MonoBehaviour:
|
||||
id: ubuntu_snap_install
|
||||
displayName: snap install
|
||||
description: deal 6-14 damage. shuffle an ubuntu pro trial into your draw pile.
|
||||
flavorText: convenient, somehow heavier than expected.
|
||||
language: 4
|
||||
rarity: 0
|
||||
cycleCost: 0
|
||||
|
||||
@@ -15,6 +15,7 @@ MonoBehaviour:
|
||||
id: ubuntu_apt_install
|
||||
displayName: sudo apt install
|
||||
description: "queue: add a random common python card to your hand. it costs 0 this combat."
|
||||
flavorText: pull it from the repo and pretend it was always there.
|
||||
language: 3
|
||||
rarity: 0
|
||||
cycleCost: 1
|
||||
|
||||
@@ -15,6 +15,7 @@ MonoBehaviour:
|
||||
id: ubuntu_pro_trial
|
||||
displayName: ubuntu pro trial
|
||||
description: unplayable. exhausts at end of combat.
|
||||
flavorText: upgrade to unlock this feature.
|
||||
language: 3
|
||||
rarity: 0
|
||||
cycleCost: 0
|
||||
|
||||
@@ -15,6 +15,7 @@ MonoBehaviour:
|
||||
id: ubuntu_unattended_upgrades
|
||||
displayName: unattended-upgrades
|
||||
description: gain 4 shield now and at the end of your next 2 turns.
|
||||
flavorText: the machine fixes itself while you sleep.
|
||||
language: 3
|
||||
rarity: 0
|
||||
cycleCost: 1
|
||||
|
||||
@@ -16,11 +16,22 @@ MonoBehaviour:
|
||||
displayName: Fedora
|
||||
primaryLanguage: 2
|
||||
secondaryLanguage: 8
|
||||
passiveName: Bleeding Edge
|
||||
passive: {fileID: 11400000, guid: a1100000000000000000000000000002, type: 2}
|
||||
description: First to every new feature. Occasionally first to the bugs that come with it.
|
||||
playstyleSummary: high-tempo gambler. her first play each turn is pushed hard, but bleeding edge bites back. rust cards are her safety net.
|
||||
languageBlurbs:
|
||||
- lang: 2
|
||||
blurb: guaranteed damage that never misses; overkill turns to shield.
|
||||
- lang: 8
|
||||
blurb: expensive early, ramps cheaper the longer the fight runs.
|
||||
asciiArt: {fileID: 4900000, guid: f2373174b6954f2d9088d83d10e0d9e4, type: 3}
|
||||
accentColor: {r: 0.23529412, g: 0.43137255, b: 0.7058824, a: 1}
|
||||
baseUptime: 55
|
||||
baseRam: 5
|
||||
baseCyclesPerTurn: 3
|
||||
exclusiveCards: []
|
||||
exclusiveCards:
|
||||
- {fileID: 11400000, guid: feda0000000000000000000000000001, type: 2}
|
||||
- {fileID: 11400000, guid: feda0000000000000000000000000002, type: 2}
|
||||
- {fileID: 11400000, guid: feda0000000000000000000000000003, type: 2}
|
||||
- {fileID: 11400000, guid: feda0000000000000000000000000004, type: 2}
|
||||
- {fileID: 11400000, guid: feda0000000000000000000000000005, type: 2}
|
||||
|
||||
@@ -16,11 +16,22 @@ MonoBehaviour:
|
||||
displayName: Mint
|
||||
primaryLanguage: 3
|
||||
secondaryLanguage: 4
|
||||
passiveName: It Just Works
|
||||
passive: {fileID: 11400000, guid: a1100000000000000000000000000003, type: 2}
|
||||
description: Comfort incarnate. No surprises, no drama, ever.
|
||||
playstyleSummary: zero-variance comfort. every number lands at its ceiling, so you always know exactly what a turn does -- at the cost of a high-roll upside.
|
||||
languageBlurbs:
|
||||
- lang: 3
|
||||
blurb: cheap, flexible cards that resolve at end of turn.
|
||||
- lang: 4
|
||||
blurb: for mint, fixed and reliable -- no chaos, no ranges.
|
||||
asciiArt: {fileID: 4900000, guid: 412c9be402ec4d8c8510e71066ec22ff, type: 3}
|
||||
accentColor: {r: 0.5294118, g: 0.8117647, b: 0.24313726, a: 1}
|
||||
baseUptime: 65
|
||||
baseRam: 5
|
||||
baseCyclesPerTurn: 3
|
||||
exclusiveCards: []
|
||||
exclusiveCards:
|
||||
- {fileID: 11400000, guid: c1a50000000000000000000000000001, type: 2}
|
||||
- {fileID: 11400000, guid: c1a50000000000000000000000000002, type: 2}
|
||||
- {fileID: 11400000, guid: c1a50000000000000000000000000003, type: 2}
|
||||
- {fileID: 11400000, guid: c1a50000000000000000000000000004, type: 2}
|
||||
- {fileID: 11400000, guid: c1a50000000000000000000000000005, type: 2}
|
||||
|
||||
@@ -16,8 +16,14 @@ MonoBehaviour:
|
||||
displayName: Ubuntu
|
||||
primaryLanguage: 3
|
||||
secondaryLanguage: 4
|
||||
passiveName: Long Term Support
|
||||
passive: {fileID: 11400000, guid: a1100000000000000000000000000001, type: 2}
|
||||
description: The friendly one. Everything works out of the box, and she will not stop helping.
|
||||
playstyleSummary: an accessible engine that never runs dry -- cheap python cards and a passive that always finds you the right package.
|
||||
languageBlurbs:
|
||||
- lang: 3
|
||||
blurb: cheap, flexible cards that resolve at end of turn.
|
||||
- lang: 4
|
||||
blurb: instant hits with wild variance and odd side effects.
|
||||
asciiArt: {fileID: 4900000, guid: 975f1f5de289435eb81c91c3eddd31dc, type: 3}
|
||||
accentColor: {r: 0.9137255, g: 0.32941177, b: 0.1254902, a: 1}
|
||||
baseUptime: 60
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace KernelPanic.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Resolves persisted card ids to immutable card definitions.
|
||||
/// </summary>
|
||||
public sealed class CardDatabase : ScriptableObject
|
||||
{
|
||||
[SerializeField] private List<CardDefinition> allCards = new();
|
||||
|
||||
public IReadOnlyList<CardDefinition> AllCards => allCards;
|
||||
|
||||
public CardDefinition FindById(string id)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(id))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int i = 0; i < allCards.Count; i++)
|
||||
{
|
||||
CardDefinition card = allCards[i];
|
||||
if (card != null && string.Equals(card.Id, id, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return card;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ namespace KernelPanic.Data
|
||||
[SerializeField] private string id;
|
||||
[SerializeField] private string displayName;
|
||||
[SerializeField] private string description;
|
||||
[SerializeField] private string flavorText;
|
||||
[SerializeField] private Language language;
|
||||
[SerializeField] private Rarity rarity;
|
||||
[SerializeField] private int cycleCost;
|
||||
@@ -25,6 +26,7 @@ namespace KernelPanic.Data
|
||||
public string Id => id;
|
||||
public string DisplayName => displayName;
|
||||
public string Description => description;
|
||||
public string FlavorText => flavorText;
|
||||
public Language Language => language;
|
||||
public Rarity Rarity => rarity;
|
||||
public int CycleCost => cycleCost;
|
||||
|
||||
@@ -9,12 +9,24 @@ namespace KernelPanic.Data
|
||||
/// </summary>
|
||||
public sealed class DistroDefinition : ScriptableObject
|
||||
{
|
||||
[System.Serializable]
|
||||
public struct LanguageBlurb
|
||||
{
|
||||
[SerializeField] private Language lang;
|
||||
[SerializeField] private string blurb;
|
||||
|
||||
public Language Lang => lang;
|
||||
public string Blurb => blurb;
|
||||
}
|
||||
|
||||
[SerializeField] private string id;
|
||||
[SerializeField] private string displayName;
|
||||
[SerializeField] private Language primaryLanguage;
|
||||
[SerializeField] private Language secondaryLanguage;
|
||||
[SerializeField] private string passiveName;
|
||||
[SerializeField] private PassiveDefinition passive;
|
||||
[SerializeField, TextArea] private string description;
|
||||
[SerializeField, TextArea] private string playstyleSummary;
|
||||
[SerializeField] private List<LanguageBlurb> languageBlurbs = new();
|
||||
[SerializeField] private TextAsset asciiArt;
|
||||
[SerializeField] private Color accentColor = new(0.36f, 1f, 0.57f);
|
||||
[SerializeField] private int baseUptime;
|
||||
@@ -26,8 +38,10 @@ namespace KernelPanic.Data
|
||||
public string DisplayName => displayName;
|
||||
public Language PrimaryLanguage => primaryLanguage;
|
||||
public Language SecondaryLanguage => secondaryLanguage;
|
||||
public string PassiveName => passiveName;
|
||||
public PassiveDefinition Passive => passive;
|
||||
public string Description => description;
|
||||
public string PlaystyleSummary => playstyleSummary;
|
||||
public IReadOnlyList<LanguageBlurb> LanguageBlurbs => languageBlurbs;
|
||||
public TextAsset AsciiArt => asciiArt;
|
||||
public Color AccentColor => accentColor;
|
||||
public int BaseUptime => baseUptime;
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace KernelPanic.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines immutable passive rules and presentation text for a distro.
|
||||
/// </summary>
|
||||
public sealed class PassiveDefinition : ScriptableObject
|
||||
{
|
||||
[SerializeField] private string id;
|
||||
[SerializeField] private string displayName;
|
||||
[SerializeField, TextArea] private string rulesText;
|
||||
[SerializeField] private string flavorText;
|
||||
[SerializeField, TextArea] private string designNotes;
|
||||
|
||||
public string Id => id;
|
||||
public string Name => displayName;
|
||||
public string RulesText => rulesText;
|
||||
public string FlavorText => flavorText;
|
||||
public string DesignNotes => designNotes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using KernelPanic.Data;
|
||||
|
||||
namespace KernelPanic.Meta
|
||||
{
|
||||
public enum CardLoadoutFailureReason
|
||||
{
|
||||
None,
|
||||
Full,
|
||||
NotOwned,
|
||||
Token,
|
||||
Duplicate,
|
||||
NotEquipped
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tracks equipped exclusive cards per owned distro without persistence or logging.
|
||||
/// </summary>
|
||||
public sealed class CardLoadout
|
||||
{
|
||||
public const int MaxEquippedCards = 4;
|
||||
|
||||
private readonly IReadOnlyList<DistroDefinition> ownedUnits;
|
||||
private readonly Dictionary<string, List<string>> equippedByDistro = new(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public CardLoadout(IReadOnlyList<DistroDefinition> ownedUnits)
|
||||
{
|
||||
this.ownedUnits = ownedUnits ?? Array.Empty<DistroDefinition>();
|
||||
}
|
||||
|
||||
public IReadOnlyList<string> GetEquippedCardIds(string distroId)
|
||||
{
|
||||
return equippedByDistro.TryGetValue(distroId, out List<string> equipped)
|
||||
? equipped
|
||||
: Array.Empty<string>();
|
||||
}
|
||||
|
||||
public bool HasLoadout(string distroId)
|
||||
{
|
||||
return !string.IsNullOrWhiteSpace(distroId) && equippedByDistro.ContainsKey(distroId);
|
||||
}
|
||||
|
||||
public void EnsureLoadout(DistroDefinition distro)
|
||||
{
|
||||
if (distro == null || string.IsNullOrWhiteSpace(distro.Id) || HasLoadout(distro.Id))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
equippedByDistro[distro.Id] = new List<string>();
|
||||
}
|
||||
|
||||
public void ClearAll()
|
||||
{
|
||||
equippedByDistro.Clear();
|
||||
}
|
||||
|
||||
public void ClearLoadout(DistroDefinition distro)
|
||||
{
|
||||
if (distro == null || string.IsNullOrWhiteSpace(distro.Id))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
equippedByDistro[distro.Id] = new List<string>();
|
||||
}
|
||||
|
||||
public bool TryLoad(string distroId, IEnumerable<string> cardIds, out bool skippedInvalid)
|
||||
{
|
||||
skippedInvalid = false;
|
||||
DistroDefinition distro = FindOwnedDistro(distroId);
|
||||
if (distro == null)
|
||||
{
|
||||
skippedInvalid = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
List<string> equipped = new();
|
||||
foreach (string cardId in cardIds ?? Array.Empty<string>())
|
||||
{
|
||||
CardDefinition card = FindExclusiveCard(distro, cardId);
|
||||
if (card == null || card.IsToken || equipped.Contains(card.Id))
|
||||
{
|
||||
skippedInvalid = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (equipped.Count < MaxEquippedCards)
|
||||
{
|
||||
equipped.Add(card.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
skippedInvalid = true;
|
||||
}
|
||||
}
|
||||
|
||||
equippedByDistro[distro.Id] = equipped;
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryEquip(string distroId, string cardId, out CardLoadoutFailureReason reason)
|
||||
{
|
||||
DistroDefinition distro = FindOwnedDistro(distroId);
|
||||
if (distro == null)
|
||||
{
|
||||
reason = CardLoadoutFailureReason.NotOwned;
|
||||
return false;
|
||||
}
|
||||
|
||||
CardDefinition card = FindExclusiveCard(distro, cardId);
|
||||
if (card == null)
|
||||
{
|
||||
reason = CardLoadoutFailureReason.NotOwned;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (card.IsToken)
|
||||
{
|
||||
reason = CardLoadoutFailureReason.Token;
|
||||
return false;
|
||||
}
|
||||
|
||||
EnsureLoadout(distro);
|
||||
List<string> equipped = equippedByDistro[distro.Id];
|
||||
if (equipped.Contains(card.Id))
|
||||
{
|
||||
reason = CardLoadoutFailureReason.Duplicate;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (equipped.Count >= MaxEquippedCards)
|
||||
{
|
||||
reason = CardLoadoutFailureReason.Full;
|
||||
return false;
|
||||
}
|
||||
|
||||
equipped.Add(card.Id);
|
||||
reason = CardLoadoutFailureReason.None;
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryUnequip(string distroId, string cardId, out CardLoadoutFailureReason reason)
|
||||
{
|
||||
DistroDefinition distro = FindOwnedDistro(distroId);
|
||||
if (distro == null)
|
||||
{
|
||||
reason = CardLoadoutFailureReason.NotOwned;
|
||||
return false;
|
||||
}
|
||||
|
||||
EnsureLoadout(distro);
|
||||
List<string> equipped = equippedByDistro[distro.Id];
|
||||
if (!equipped.Remove(cardId))
|
||||
{
|
||||
reason = CardLoadoutFailureReason.NotEquipped;
|
||||
return false;
|
||||
}
|
||||
|
||||
reason = CardLoadoutFailureReason.None;
|
||||
return true;
|
||||
}
|
||||
|
||||
private DistroDefinition FindOwnedDistro(string distroId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(distroId))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ownedUnits.Count; i++)
|
||||
{
|
||||
DistroDefinition distro = ownedUnits[i];
|
||||
if (distro != null && string.Equals(distro.Id, distroId, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return distro;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static CardDefinition FindExclusiveCard(DistroDefinition distro, string cardId)
|
||||
{
|
||||
if (distro == null || string.IsNullOrWhiteSpace(cardId))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int i = 0; i < distro.ExclusiveCards.Count; i++)
|
||||
{
|
||||
CardDefinition card = distro.ExclusiveCards[i];
|
||||
if (card != null && string.Equals(card.Id, cardId, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return card;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -167,6 +167,7 @@ namespace KernelPanic.UI
|
||||
Label description = new(string.IsNullOrWhiteSpace(unit.Description) ? "--" : unit.Description);
|
||||
description.AddToClassList("collection-detail-description");
|
||||
detail.Add(description);
|
||||
AddPassiveDetails(detail, unit);
|
||||
|
||||
VisualElement readout = new();
|
||||
readout.AddToClassList("collection-detail-readout");
|
||||
@@ -183,7 +184,6 @@ namespace KernelPanic.UI
|
||||
details.AddToClassList("collection-detail-values");
|
||||
|
||||
details.Add(BuildDetailLine("lang", DistroPresentation.FormatLanguages(unit)));
|
||||
details.Add(BuildDetailLine("passive", string.IsNullOrWhiteSpace(unit.PassiveName) ? "--" : unit.PassiveName));
|
||||
details.Add(BuildDetailLine("uptime", unit.BaseUptime.ToString()));
|
||||
details.Add(BuildDetailLine("ram", unit.BaseRam.ToString()));
|
||||
details.Add(BuildDetailLine("cycles", unit.BaseCyclesPerTurn.ToString()));
|
||||
@@ -204,6 +204,12 @@ namespace KernelPanic.UI
|
||||
Label description = new(card == null || string.IsNullOrWhiteSpace(card.Description) ? "--" : card.Description);
|
||||
description.AddToClassList("collection-detail-description");
|
||||
detail.Add(description);
|
||||
if (card != null && !string.IsNullOrWhiteSpace(card.FlavorText))
|
||||
{
|
||||
Label flavor = new(card.FlavorText);
|
||||
flavor.AddToClassList("flavor-text");
|
||||
detail.Add(flavor);
|
||||
}
|
||||
|
||||
detail.Add(BuildDetailLine("owner", DistroPresentation.DisplayName(entry.Owner)));
|
||||
detail.Add(BuildDetailLine("lang", card == null ? "--" : card.Language.ToString()));
|
||||
@@ -227,6 +233,29 @@ namespace KernelPanic.UI
|
||||
return row;
|
||||
}
|
||||
|
||||
private static void AddPassiveDetails(VisualElement target, DistroDefinition unit)
|
||||
{
|
||||
if (unit.Passive == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Label passiveTitle = new(unit.Passive.Name);
|
||||
passiveTitle.AddToClassList("detail-section-title");
|
||||
target.Add(passiveTitle);
|
||||
|
||||
Label passiveRules = new(unit.Passive.RulesText);
|
||||
passiveRules.AddToClassList("collection-detail-description");
|
||||
target.Add(passiveRules);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(unit.Passive.FlavorText))
|
||||
{
|
||||
Label passiveFlavor = new(unit.Passive.FlavorText);
|
||||
passiveFlavor.AddToClassList("flavor-text");
|
||||
target.Add(passiveFlavor);
|
||||
}
|
||||
}
|
||||
|
||||
private static IReadOnlyList<CardEntry> BuildCardEntries(DistroDefinition featuredUnit)
|
||||
{
|
||||
List<CardEntry> entries = new();
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace KernelPanic.UI
|
||||
asciiFitter.SetArt(DistroArtPresenter.Render(asciiLabel, asciiPlaceholder, unit));
|
||||
unitNameLabel.text = DistroPresentation.DisplayName(unit);
|
||||
languagesLabel.text = DistroPresentation.FormatLanguages(unit);
|
||||
passiveLabel.text = string.IsNullOrWhiteSpace(unit.PassiveName) ? "--" : unit.PassiveName;
|
||||
passiveLabel.text = unit.Passive == null || string.IsNullOrWhiteSpace(unit.Passive.Name) ? "--" : unit.Passive.Name;
|
||||
bestWaveLabel.text = "--"; // TODO: Bind best-wave stats from SaveService when stats exist.
|
||||
SetAccent(ColorUtility.ToHtmlStringRGB(unit.AccentColor));
|
||||
}
|
||||
|
||||
@@ -206,16 +206,28 @@ namespace KernelPanic.UI
|
||||
{
|
||||
root.RegisterCallback<KeyDownEvent>(HandleKeyDown);
|
||||
root.RegisterCallback<PointerDownEvent>(HandlePointerDown);
|
||||
collectionUnitsButton.clicked += ShowCollectionUnits;
|
||||
collectionCardsButton.clicked += ShowCollectionCards;
|
||||
collectionUnitsButton.RegisterCallback<ClickEvent>(HandleCollectionUnitsTabClicked);
|
||||
collectionCardsButton.RegisterCallback<ClickEvent>(HandleCollectionCardsTabClicked);
|
||||
}
|
||||
|
||||
private void UnregisterCallbacks()
|
||||
{
|
||||
root.UnregisterCallback<KeyDownEvent>(HandleKeyDown);
|
||||
root.UnregisterCallback<PointerDownEvent>(HandlePointerDown);
|
||||
collectionUnitsButton.clicked -= ShowCollectionUnits;
|
||||
collectionCardsButton.clicked -= ShowCollectionCards;
|
||||
collectionUnitsButton.UnregisterCallback<ClickEvent>(HandleCollectionUnitsTabClicked);
|
||||
collectionCardsButton.UnregisterCallback<ClickEvent>(HandleCollectionCardsTabClicked);
|
||||
}
|
||||
|
||||
private void HandleCollectionUnitsTabClicked(ClickEvent evt)
|
||||
{
|
||||
ShowCollectionUnits();
|
||||
evt.StopPropagation();
|
||||
}
|
||||
|
||||
private void HandleCollectionCardsTabClicked(ClickEvent evt)
|
||||
{
|
||||
ShowCollectionCards();
|
||||
evt.StopPropagation();
|
||||
}
|
||||
|
||||
private void LoadMetaState()
|
||||
@@ -599,7 +611,8 @@ namespace KernelPanic.UI
|
||||
summary.Add(meta);
|
||||
|
||||
row.Add(summary);
|
||||
row.Add(new Label(string.IsNullOrWhiteSpace(unit.PassiveName) ? "passive: --" : $"passive: {unit.PassiveName}")
|
||||
string passiveTitle = unit.Passive == null || string.IsNullOrWhiteSpace(unit.Passive.Name) ? "--" : unit.Passive.Name;
|
||||
row.Add(new Label($"passive: {passiveTitle}")
|
||||
{
|
||||
name = $"RunSetupDescription{index}"
|
||||
});
|
||||
@@ -724,10 +737,46 @@ namespace KernelPanic.UI
|
||||
stats.AddToClassList("collection-detail-muted");
|
||||
copy.Add(stats);
|
||||
|
||||
AddDistroTeachingDetails(copy, unit);
|
||||
|
||||
readout.Add(copy);
|
||||
return readout;
|
||||
}
|
||||
|
||||
private static void AddDistroTeachingDetails(VisualElement target, DistroDefinition unit)
|
||||
{
|
||||
if (unit.Passive != null)
|
||||
{
|
||||
Label passiveTitle = new(unit.Passive.Name);
|
||||
passiveTitle.AddToClassList("detail-section-title");
|
||||
target.Add(passiveTitle);
|
||||
|
||||
Label passiveRules = new(unit.Passive.RulesText);
|
||||
passiveRules.AddToClassList("collection-detail-description");
|
||||
target.Add(passiveRules);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(unit.Passive.FlavorText))
|
||||
{
|
||||
Label passiveFlavor = new(unit.Passive.FlavorText);
|
||||
passiveFlavor.AddToClassList("flavor-text");
|
||||
target.Add(passiveFlavor);
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(unit.PlaystyleSummary))
|
||||
{
|
||||
Label playstyle = new(unit.PlaystyleSummary);
|
||||
playstyle.AddToClassList("collection-detail-description");
|
||||
target.Add(playstyle);
|
||||
}
|
||||
|
||||
for (int i = 0; i < unit.LanguageBlurbs.Count; i++)
|
||||
{
|
||||
DistroDefinition.LanguageBlurb blurb = unit.LanguageBlurbs[i];
|
||||
target.Add(BuildDetailLine(blurb.Lang.ToString(), blurb.Blurb));
|
||||
}
|
||||
}
|
||||
|
||||
private static VisualElement BuildDetailLine(string key, string value)
|
||||
{
|
||||
VisualElement row = new();
|
||||
@@ -767,6 +816,12 @@ namespace KernelPanic.UI
|
||||
row.ElementAt(1).AddToClassList("package-description");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(card.FlavorText))
|
||||
{
|
||||
row.Add(new Label(card.FlavorText) { name = "RunSetupCardFlavor" });
|
||||
row.ElementAt(row.childCount - 1).AddToClassList("package-flavor");
|
||||
}
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace KernelPanic.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// Binds shared command-style chrome used by terminal sub-screens.
|
||||
/// </summary>
|
||||
public sealed class ScreenFrameController
|
||||
{
|
||||
private Label titleLabel;
|
||||
private Label hintLabel;
|
||||
|
||||
public void Bind(VisualElement panel, string title, string hint, Action onBack)
|
||||
{
|
||||
titleLabel = panel.Q<Label>(className: "screen-frame-title");
|
||||
hintLabel = panel.Q<Label>(className: "screen-frame-hint");
|
||||
|
||||
if (titleLabel != null)
|
||||
{
|
||||
titleLabel.text = title;
|
||||
}
|
||||
|
||||
if (hintLabel != null)
|
||||
{
|
||||
hintLabel.text = hint;
|
||||
hintLabel.RegisterCallback<ClickEvent>(_ => onBack?.Invoke());
|
||||
}
|
||||
}
|
||||
|
||||
public void SetHint(string hint)
|
||||
{
|
||||
if (hintLabel != null)
|
||||
{
|
||||
hintLabel.text = hint;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetTitle(string title)
|
||||
{
|
||||
if (titleLabel != null)
|
||||
{
|
||||
titleLabel.text = title;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,8 @@
|
||||
</ui:VisualElement>
|
||||
<ui:VisualElement class="screen-frame-content">
|
||||
<ui:VisualElement class="collection-actions">
|
||||
<ui:Button name="CollectionUnitsButton" text="units" class="collection-tab" />
|
||||
<ui:Button name="CollectionCardsButton" text="cards" class="collection-tab" />
|
||||
<ui:Button name="CollectionUnitsButton" text="units" focusable="false" class="collection-tab" />
|
||||
<ui:Button name="CollectionCardsButton" text="cards" focusable="false" class="collection-tab" />
|
||||
</ui:VisualElement>
|
||||
<ui:VisualElement name="CollectionContent" class="collection-shell">
|
||||
<ui:ScrollView name="CollectionList" class="collection-list" />
|
||||
|
||||
@@ -635,6 +635,22 @@ Button {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.detail-section-title {
|
||||
color: var(--kp-primary);
|
||||
-unity-font-style: bold;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 4px;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.flavor-text,
|
||||
.package-flavor {
|
||||
color: var(--kp-muted);
|
||||
-unity-font-style: italic;
|
||||
white-space: normal;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.package-list {
|
||||
min-width: 0;
|
||||
flex-grow: 1;
|
||||
@@ -724,6 +740,11 @@ Button {
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.package-flavor {
|
||||
margin-left: 34px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.run-readout {
|
||||
min-height: 110px;
|
||||
max-height: 128px;
|
||||
|
||||
Reference in New Issue
Block a user