Implement many UX improvements, packages and their assets and a UI overhaul in collection
This commit is contained in:
@@ -28,7 +28,7 @@ MonoBehaviour:
|
||||
accentColor: {r: 0.9137255, g: 0.32941177, b: 0.1254902, a: 1}
|
||||
baseUptime: 60
|
||||
baseRam: 5
|
||||
baseCyclesPerTurn: 3
|
||||
baseCyclesPerTurn: 4
|
||||
exclusiveCards:
|
||||
- {fileID: 11400000, guid: 9347bcc42fb6834f1907a2c0b661ff95, type: 2}
|
||||
- {fileID: 11400000, guid: 1dbc28e480e52d97b9501262af30cc78, type: 2}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Apt
|
||||
id: pkg_ubuntu_apt
|
||||
displayName: apt
|
||||
slot: 2
|
||||
rarity: 5
|
||||
description: Each time you play your 3rd card in a TURN, add a random 0-cost card of your languages to hand; on Ubuntu also refund 1 Cycle.
|
||||
flavourText: There is always one more dependency.
|
||||
designNotes: Ubuntu 5-star Daemon. TURN third-card trigger. requiresSystem: card-generation + per-turn-card-count. On Ubuntu refunds 1 Cycle.
|
||||
intendedDistroId: ubuntu
|
||||
requiresSystem:
|
||||
- card-generation
|
||||
- per-turn-card-count
|
||||
offDistroEffect: {kind: 10, amount: 1, threshold: 3, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 10, amount: 1, threshold: 3, refundCycle: 1, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cef0ecd4cdaa4fd09c2c8578263acd20
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: AptFast
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_apt_fast
|
||||
displayName: apt-fast
|
||||
slot: 1
|
||||
rarity: 3
|
||||
description: Start of each WAVE, gain +1 Cycle that WAVE's first TURN.
|
||||
flavourText: Parallel downloads, parallel consequences.
|
||||
designNotes: Generic 3-star Runtime powerspike. First-turn WAVE cycle hook.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 18, amount: 1, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 18, amount: 1, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96d18432766243138d800f9f544bc934
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Auditd
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_auditd
|
||||
displayName: auditd
|
||||
slot: 2
|
||||
rarity: 3
|
||||
description: Start of each TURN, if you have no debuffs, gain 3 Shield.
|
||||
flavourText: Logs suspicious activity, including competence.
|
||||
designNotes: Generic 3-star Daemon powerspike. Uses status descriptor harmful query.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 23, amount: 3, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 23, amount: 3, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a8e4cfd86f554fa19198551a7d5ed8ab
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Ccache
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_ccache
|
||||
displayName: ccache
|
||||
slot: 1
|
||||
rarity: 3
|
||||
description: Every 4th card played in a WAVE costs 0.
|
||||
flavourText: Why compile twice when you can be smug once?
|
||||
designNotes: Generic 3-star Runtime powerspike. Existing nth-card WAVE free-cost hook.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 8, amount: 0, threshold: 4, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 8, amount: 0, threshold: 4, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f68f89f3d4554063a891c30b1c387692
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: CinnamonPackage
|
||||
id: pkg_mint_cinnamon
|
||||
displayName: Cinnamon
|
||||
slot: 1
|
||||
rarity: 4
|
||||
description: JavaScript cards deal +3 flat on Mint, +2 off-distro.
|
||||
flavourText: Comfortable, polished, and a little too smug.
|
||||
designNotes: Mint 4-star Runtime. Flat add through DamagePipeline additive step. On Mint +3; off-distro +2.
|
||||
intendedDistroId: mint
|
||||
requiresSystem:
|
||||
- damage-pipeline-additive
|
||||
offDistroEffect: {kind: 11, amount: 2, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 11, amount: 3, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5b13be9296e347459ed3659e1855a5d3
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Coreutils
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_coreutils
|
||||
displayName: coreutils
|
||||
slot: 0
|
||||
rarity: 1
|
||||
description: +2 max Uptime (COMBAT).
|
||||
flavourText: The box of tiny tools that somehow runs everything.
|
||||
designNotes: Generic 1-star Kernel baseline. COMBAT stat package. On/off distro identical.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 1, amount: 2, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 1, amount: 2, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7422da9aba294553a6009eb3c01498e1
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Cron
|
||||
id: pkg_cron
|
||||
displayName: cron
|
||||
slot: 2
|
||||
rarity: 1
|
||||
description: Every 3rd TURN, gain 2 Shield.
|
||||
flavourText: Eventually, it helps.
|
||||
designNotes: Generic 1-star Daemon. TURN counter shield. On/off distro identical.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 6, amount: 2, threshold: 3, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 6, amount: 2, threshold: 3, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0b6678d8a231464b8ff257ece3dcfeae
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Curl
|
||||
id: pkg_curl
|
||||
displayName: curl
|
||||
slot: 1
|
||||
rarity: 1
|
||||
description: Draw 1 extra card at the start of each WAVE.
|
||||
flavourText: It downloads help, mostly by accident.
|
||||
designNotes: Generic 1-star Runtime. WAVE start draw. On/off distro identical.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 3, amount: 1, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 3, amount: 1, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 415021c139b54ff1a6b9cc2e5aede209
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,19 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: DNF
|
||||
id: pkg_fedora_dnf
|
||||
displayName: DNF
|
||||
slot: 1
|
||||
rarity: 5
|
||||
description: On Fedora, Bleeding Edge applies to the 2nd card each TURN. Also builds a stacking +2 damage buff this WAVE.
|
||||
flavourText: Fast, sharp, occasionally on fire.
|
||||
designNotes: Fedora 5-star Runtime. Ties into Bleeding Edge crash logic; on Fedora enables 2nd-card passive discount+bonus. Off-distro only uses the WAVE stacking +2 damage buff hook.
|
||||
intendedDistroId: fedora
|
||||
requiresSystem:
|
||||
- fedora-passive-hook
|
||||
- per-wave-damage-buff
|
||||
offDistroEffect: {kind: 14, amount: 2, threshold: 1, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 14, amount: 2, threshold: 1, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 1}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f47028f76c0843629789bf128bae4c3d
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Dbus
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_dbus
|
||||
displayName: dbus
|
||||
slot: 2
|
||||
rarity: 1
|
||||
description: First time you play a queued (InterpreterQueue) card each WAVE, gain 2 Shield.
|
||||
flavourText: Messages everywhere, consensus nowhere.
|
||||
designNotes: Generic 1-star Daemon. InterpreterQueue play hook.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 21, amount: 2, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 21, amount: 2, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e90cac6fdbde448a9eb7432889a0ec39
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Docker
|
||||
id: pkg_docker
|
||||
displayName: docker
|
||||
slot: 1
|
||||
rarity: 3
|
||||
description: At the start of each WAVE, add a random 0-cost basic card of the distro's languages to hand.
|
||||
flavourText: Works on my daemon.
|
||||
designNotes: Generic 3-star Runtime powerspike. WAVE start generation. requiresSystem: card-generation; uses existing generated-card pool when available, TODO logged if not.
|
||||
intendedDistroId:
|
||||
requiresSystem:
|
||||
- card-generation
|
||||
offDistroEffect: {kind: 4, amount: 1, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 4, amount: 1, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a392e5d09c864940bde926a68f4681a7
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Ext4
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_ext4
|
||||
displayName: ext4
|
||||
slot: 0
|
||||
rarity: 2
|
||||
description: +4 max Uptime (COMBAT).
|
||||
flavourText: Journaling your mistakes so recovery has something to read.
|
||||
designNotes: Generic 2-star Kernel. COMBAT stat package.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 1, amount: 4, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 1, amount: 4, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 309a914d85d544d4bd2e19b35d40768e
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Firewalld
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_firewalld
|
||||
displayName: firewalld
|
||||
slot: 2
|
||||
rarity: 2
|
||||
description: The first debuff applied to you each WAVE is reduced by 1 stack.
|
||||
flavourText: Blocks everything except the one port you forgot about.
|
||||
designNotes: Generic 2-star Daemon. TODO status prevention/rewrite hook missing.
|
||||
intendedDistroId:
|
||||
requiresSystem: [status-apply-prevention-hook]
|
||||
offDistroEffect: {kind: 0, amount: 0, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 0, amount: 0, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f09c5c4fed8547a7ade6e4c1129acf08
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Git
|
||||
id: pkg_git
|
||||
displayName: git
|
||||
slot: 1
|
||||
rarity: 2
|
||||
description: The first card played each WAVE costs 1 less.
|
||||
flavourText: Everyone blames the branch.
|
||||
designNotes: Generic 2-star Runtime. WAVE first-card economy. On/off distro identical.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 5, amount: 1, threshold: 1, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 5, amount: 1, threshold: 1, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 36e380dd7864488a9544eff6d0aa15d5
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Glibc
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_glibc
|
||||
displayName: glibc
|
||||
slot: 0
|
||||
rarity: 1
|
||||
description: +2 max Uptime (COMBAT).
|
||||
flavourText: Everything links against it, including your bad decisions.
|
||||
designNotes: Generic 1-star Kernel. COMBAT stat package. Upgrade scaling increases amount at runtime.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 1, amount: 2, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 1, amount: 2, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 03b4a29f7baa4a4c8cc5945a508b64a5
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Htop
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_htop
|
||||
displayName: htop
|
||||
slot: 0
|
||||
rarity: 2
|
||||
description: +5 max Uptime (COMBAT).
|
||||
flavourText: Green bars make the panic feel managed.
|
||||
designNotes: Generic 2-star Kernel. COMBAT stat package. On/off distro identical.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 1, amount: 5, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 1, amount: 5, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b3e47005ebdf42788204e5b5677f9002
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Less
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_less
|
||||
displayName: less
|
||||
slot: 1
|
||||
rarity: 1
|
||||
description: Once per WAVE, the first card drawn is free to play (0 cost) that TURN.
|
||||
flavourText: Less is more, except when it is just a pager.
|
||||
designNotes: Generic 1-star Runtime. TODO free-cast/draw-tag hook missing.
|
||||
intendedDistroId:
|
||||
requiresSystem: [free-cast-drawn-card-hook]
|
||||
offDistroEffect: {kind: 0, amount: 0, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 0, amount: 0, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 76af631396664958a398073c6021a626
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Logrotate
|
||||
id: pkg_logrotate
|
||||
displayName: logrotate
|
||||
slot: 2
|
||||
rarity: 2
|
||||
description: When you exhaust a card, gain 1 Shield.
|
||||
flavourText: Deletes the evidence, keeps the casing.
|
||||
designNotes: Generic 2-star Daemon. Exhaust hook; current authored exhaust path is dnf autoremove.
|
||||
intendedDistroId:
|
||||
requiresSystem:
|
||||
- exhaust-hook
|
||||
offDistroEffect: {kind: 7, amount: 1, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 7, amount: 1, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0f2a212cc70d422189f26c0314853ef4
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Lvm
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_lvm
|
||||
displayName: lvm
|
||||
slot: 0
|
||||
rarity: 3
|
||||
description: +8 max Uptime (COMBAT).
|
||||
flavourText: Logical volumes, illogical confidence.
|
||||
designNotes: Generic 3-star Kernel powerspike. COMBAT stat package.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 1, amount: 8, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 1, amount: 8, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f30e0284fa5a45aaa7507089a31aaf88
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Make
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_make
|
||||
displayName: make
|
||||
slot: 1
|
||||
rarity: 2
|
||||
description: The first Native card each WAVE deals +3.
|
||||
flavourText: Tab-sensitive violence.
|
||||
designNotes: Generic 2-star Runtime. Routes through existing flat effect bonus before first Native card resolves.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 20, amount: 3, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 20, amount: 3, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed56f679bb7b4db9ad7884bfeb7f1660
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Nano
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_nano
|
||||
displayName: nano
|
||||
slot: 1
|
||||
rarity: 1
|
||||
description: The first card played each WAVE costs 1 less.
|
||||
flavourText: Exit instructions included, panic reduced.
|
||||
designNotes: Generic 1-star Runtime. Existing first-card-per-WAVE cost hook.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 5, amount: 1, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 5, amount: 1, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 47286d5a87334b1fa303a583a9b1085e
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Nginx
|
||||
id: pkg_nginx
|
||||
displayName: nginx
|
||||
slot: 2
|
||||
rarity: 3
|
||||
description: Every 3rd card played in a WAVE costs 0.
|
||||
flavourText: Reverse proxies your budget.
|
||||
designNotes: Generic 3-star Daemon powerspike. WAVE card counter cost override.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 8, amount: 0, threshold: 3, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 8, amount: 0, threshold: 3, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e4cb1d11f3dd44878111ce3b5f89ee8c
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Ntp
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_ntp
|
||||
displayName: ntp
|
||||
slot: 0
|
||||
rarity: 2
|
||||
description: +3 max Uptime (COMBAT); first TURN of each WAVE, gain 2 Shield.
|
||||
flavourText: Corrects clock drift and, briefly, life choices.
|
||||
designNotes: Generic 2-star Kernel. Uses MaxUptime now; first-turn shield TODO until multi-effect packages exist.
|
||||
intendedDistroId:
|
||||
requiresSystem: [multi-effect-package]
|
||||
offDistroEffect: {kind: 1, amount: 3, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 1, amount: 3, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c9c4f393b7a4dad874f50d02984d4d5
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: OpenSSL
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_openssl
|
||||
displayName: openssl
|
||||
slot: 0
|
||||
rarity: 1
|
||||
description: +1 max Uptime (COMBAT), +1 Shield at WAVE start.
|
||||
flavourText: The lock icon is mostly vibes, but the vibes are encrypted.
|
||||
designNotes: Generic 1-star Kernel. Uses MaxUptime now; WAVE shield portion TODO until multi-effect packages exist.
|
||||
intendedDistroId:
|
||||
requiresSystem: [multi-effect-package]
|
||||
offDistroEffect: {kind: 1, amount: 1, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 1, amount: 1, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2320e53b9b8a4f5184025ddba1581f65
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,46 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 04c3b1510a7d45f3aba1ee24fe0cbc12, type: 3}
|
||||
m_Name: PackageDatabase
|
||||
allPackages:
|
||||
- {fileID: 11400000, guid: 7422da9aba294553a6009eb3c01498e1, type: 2}
|
||||
- {fileID: 11400000, guid: b3e47005ebdf42788204e5b5677f9002, type: 2}
|
||||
- {fileID: 11400000, guid: 7b77920d46a0434ab4e772339293d991, type: 2}
|
||||
- {fileID: 11400000, guid: 415021c139b54ff1a6b9cc2e5aede209, type: 2}
|
||||
- {fileID: 11400000, guid: 36e380dd7864488a9544eff6d0aa15d5, type: 2}
|
||||
- {fileID: 11400000, guid: a392e5d09c864940bde926a68f4681a7, type: 2}
|
||||
- {fileID: 11400000, guid: 0b6678d8a231464b8ff257ece3dcfeae, type: 2}
|
||||
- {fileID: 11400000, guid: 0f2a212cc70d422189f26c0314853ef4, type: 2}
|
||||
- {fileID: 11400000, guid: e4cb1d11f3dd44878111ce3b5f89ee8c, type: 2}
|
||||
- {fileID: 11400000, guid: ccaa32454a304e1f96d6d340b9c1900e, type: 2}
|
||||
- {fileID: 11400000, guid: cef0ecd4cdaa4fd09c2c8578263acd20, type: 2}
|
||||
- {fileID: 11400000, guid: 5b13be9296e347459ed3659e1855a5d3, type: 2}
|
||||
- {fileID: 11400000, guid: 07554ac885824a6e8e49d7d39cf2fa30, type: 2}
|
||||
- {fileID: 11400000, guid: c9b1e99838c74709aafe6d659b41f231, type: 2}
|
||||
- {fileID: 11400000, guid: f47028f76c0843629789bf128bae4c3d, type: 2}
|
||||
- {fileID: 11400000, guid: 03b4a29f7baa4a4c8cc5945a508b64a5, type: 2}
|
||||
- {fileID: 11400000, guid: 40d2efb5aa8d4b85a4bdc7b3cb7781d8, type: 2}
|
||||
- {fileID: 11400000, guid: 2320e53b9b8a4f5184025ddba1581f65, type: 2}
|
||||
- {fileID: 11400000, guid: 309a914d85d544d4bd2e19b35d40768e, type: 2}
|
||||
- {fileID: 11400000, guid: a48fbfda32824a7cb127318c93602420, type: 2}
|
||||
- {fileID: 11400000, guid: 5c9c4f393b7a4dad874f50d02984d4d5, type: 2}
|
||||
- {fileID: 11400000, guid: 0a11dac6bc6d435192a262eb1d8ac685, type: 2}
|
||||
- {fileID: 11400000, guid: f30e0284fa5a45aaa7507089a31aaf88, type: 2}
|
||||
- {fileID: 11400000, guid: 19d4c144fb5c4ae3b0bccb4b048aaa96, type: 2}
|
||||
- {fileID: 11400000, guid: 47286d5a87334b1fa303a583a9b1085e, type: 2}
|
||||
- {fileID: 11400000, guid: 76af631396664958a398073c6021a626, type: 2}
|
||||
- {fileID: 11400000, guid: a3b1582341434a8981c802f8d7da2420, type: 2}
|
||||
- {fileID: 11400000, guid: b47b1186672c45e19012b4e74c8b0b93, type: 2}
|
||||
- {fileID: 11400000, guid: ed56f679bb7b4db9ad7884bfeb7f1660, type: 2}
|
||||
- {fileID: 11400000, guid: 96d18432766243138d800f9f544bc934, type: 2}
|
||||
- {fileID: 11400000, guid: f68f89f3d4554063a891c30b1c387692, type: 2}
|
||||
- {fileID: 11400000, guid: 302d3da8597941ea99c6d507fa9d3d28, type: 2}
|
||||
- {fileID: 11400000, guid: 177e5f43f6544549bf12e02ec05ec833, type: 2}
|
||||
- {fileID: 11400000, guid: e90cac6fdbde448a9eb7432889a0ec39, type: 2}
|
||||
- {fileID: 11400000, guid: f3174349716e4db6a7ffed8205f2a541, type: 2}
|
||||
- {fileID: 11400000, guid: f09c5c4fed8547a7ade6e4c1129acf08, type: 2}
|
||||
- {fileID: 11400000, guid: 159fca0abb7249e1be485aaac5f83fbe, type: 2}
|
||||
- {fileID: 11400000, guid: ac481beaf7e6453d82a439d54c2fb2f3, type: 2}
|
||||
- {fileID: 11400000, guid: a8e4cfd86f554fa19198551a7d5ed8ab, type: 2}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: efca08b3991e42e5b1e03878507496a6
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Polkit
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_polkit
|
||||
displayName: polkit
|
||||
slot: 2
|
||||
rarity: 2
|
||||
description: First time you gain Shield each TURN, gain +2 extra.
|
||||
flavourText: Permission denied, but with a helpful dialog nobody reads.
|
||||
designNotes: Generic 2-star Daemon. Existing first shield each TURN bonus hook.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 13, amount: 2, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 13, amount: 2, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 159fca0abb7249e1be485aaac5f83fbe
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Rsync
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_rsync
|
||||
displayName: rsync
|
||||
slot: 1
|
||||
rarity: 2
|
||||
description: At WAVE start, draw 1 extra card.
|
||||
flavourText: Efficiently copies hope from the deck into your hand.
|
||||
designNotes: Generic 2-star Runtime. WAVE draw hook.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 3, amount: 1, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 3, amount: 1, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b47b1186672c45e19012b4e74c8b0b93
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: SELinuxPackage
|
||||
id: pkg_fedora_selinux
|
||||
displayName: SELinux
|
||||
slot: 2
|
||||
rarity: 4
|
||||
description: First time you gain Shield each TURN, gain +5 extra on Fedora, +3 off-distro.
|
||||
flavourText: It denied the damage and filed a report.
|
||||
designNotes: Fedora 4-star Daemon. TURN first-shield trigger. On Fedora +5; off-distro +3.
|
||||
intendedDistroId: fedora
|
||||
requiresSystem:
|
||||
- shield-gain-hook
|
||||
offDistroEffect: {kind: 13, amount: 3, threshold: 1, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 13, amount: 5, threshold: 1, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c9b1e99838c74709aafe6d659b41f231
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: SnapStore
|
||||
id: pkg_ubuntu_snap_store
|
||||
displayName: Snap Store
|
||||
slot: 1
|
||||
rarity: 4
|
||||
description: First cards played each TURN cost 1 less; first 2 on Ubuntu, first 1 off-distro.
|
||||
flavourText: Starts instantly after a brief geological pause.
|
||||
designNotes: Ubuntu 4-star Runtime. TURN card-count cost discount. On Ubuntu threshold 2; off-distro threshold 1.
|
||||
intendedDistroId: ubuntu
|
||||
requiresSystem:
|
||||
- per-turn-card-count
|
||||
offDistroEffect: {kind: 9, amount: 1, threshold: 1, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 9, amount: 1, threshold: 2, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ccaa32454a304e1f96d6d340b9c1900e
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Sshd
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_sshd
|
||||
displayName: sshd
|
||||
slot: 2
|
||||
rarity: 2
|
||||
description: Every 3rd TURN, gain 3 Shield.
|
||||
flavourText: Open port, closed heart.
|
||||
designNotes: Generic 2-star Daemon. Existing nth-TURN shield hook.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 6, amount: 3, threshold: 3, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 6, amount: 3, threshold: 3, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f3174349716e4db6a7ffed8205f2a541
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Swapfile
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_swapfile
|
||||
displayName: swapfile
|
||||
slot: 0
|
||||
rarity: 2
|
||||
description: +1 max RAM (COMBAT).
|
||||
flavourText: RAM, but with the emotional latency of a spinning disk.
|
||||
designNotes: Generic 2-star Kernel. COMBAT RAM stat package.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 19, amount: 1, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 19, amount: 1, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a48fbfda32824a7cb127318c93602420
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Syslog
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_syslog
|
||||
displayName: syslog
|
||||
slot: 2
|
||||
rarity: 1
|
||||
description: When you exhaust a card, gain 1 Shield.
|
||||
flavourText: Writes down the problem, then pretends that helped.
|
||||
designNotes: Generic 1-star Daemon. Existing exhaust shield hook.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 7, amount: 1, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 7, amount: 1, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 302d3da8597941ea99c6d507fa9d3d28
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: SystemdCore
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_systemd_core
|
||||
displayName: systemd-core
|
||||
slot: 0
|
||||
rarity: 3
|
||||
description: +1 max Cycles (COMBAT).
|
||||
flavourText: Yes, it manages that too.
|
||||
designNotes: Generic 3-star Kernel powerspike. COMBAT max Cycle package. On/off distro identical.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 2, amount: 1, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 2, amount: 1, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7b77920d46a0434ab4e772339293d991
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: SystemdTimer
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_systemd_timer
|
||||
displayName: systemd-timer
|
||||
slot: 2
|
||||
rarity: 3
|
||||
description: Every 3rd card played in a WAVE, gain 1 Cycle.
|
||||
flavourText: Cron with a committee and better unit files.
|
||||
designNotes: Generic 3-star Daemon powerspike. Nth-card WAVE cycle hook.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 24, amount: 1, threshold: 3, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 24, amount: 1, threshold: 3, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ac481beaf7e6453d82a439d54c2fb2f3
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,19 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: TimeshiftPackage
|
||||
id: pkg_mint_timeshift
|
||||
displayName: Timeshift
|
||||
slot: 0
|
||||
rarity: 5
|
||||
description: First time each WAVE Uptime would drop below a threshold, restore to it; 50% + cleanse on Mint, 30% off-distro.
|
||||
flavourText: Undo button for bad life choices.
|
||||
designNotes: Mint 5-star Kernel. WAVE damage/heal hook through DamagePipeline event; status cleanse on Mint only.
|
||||
intendedDistroId: mint
|
||||
requiresSystem:
|
||||
- damage-pipeline-hook
|
||||
- status-cleanse
|
||||
offDistroEffect: {kind: 12, amount: 0, threshold: 30, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 12, amount: 0, threshold: 50, refundCycle: 0, cleanseDebuffs: 1, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 07554ac885824a6e8e49d7d39cf2fa30
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Udev
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_udev
|
||||
displayName: udev
|
||||
slot: 2
|
||||
rarity: 1
|
||||
description: Every 4th TURN, draw 1 card.
|
||||
flavourText: A device appeared, so naturally you drew paperwork.
|
||||
designNotes: Generic 1-star Daemon. TURN draw hook.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 22, amount: 1, threshold: 4, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 22, amount: 1, threshold: 4, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 177e5f43f6544549bf12e02ec05ec833
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Vim
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_vim
|
||||
displayName: vim
|
||||
slot: 1
|
||||
rarity: 2
|
||||
description: First card played each TURN costs 1 less.
|
||||
flavourText: Modal editing for modal spending.
|
||||
designNotes: Generic 2-star Runtime. Existing first-card-per-TURN cost hook.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 9, amount: 1, threshold: 1, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 9, amount: 1, threshold: 1, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a3b1582341434a8981c802f8d7da2420
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Wget
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_wget
|
||||
displayName: wget
|
||||
slot: 1
|
||||
rarity: 1
|
||||
description: Draw 1 extra card on the first TURN of the first WAVE.
|
||||
flavourText: Downloads one more thing before anyone reads the flags.
|
||||
designNotes: Generic 1-star Runtime. First WAVE opening draw hook.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 17, amount: 1, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 17, amount: 1, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 19d4c144fb5c4ae3b0bccb4b048aaa96
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Zlib
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_zlib
|
||||
displayName: zlib
|
||||
slot: 0
|
||||
rarity: 1
|
||||
description: Start each WAVE with 3 Shield.
|
||||
flavourText: Compresses incoming panic into a smaller panic.
|
||||
designNotes: Generic 1-star Kernel. WAVE shield hook.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 15, amount: 3, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 15, amount: 3, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 40d2efb5aa8d4b85a4bdc7b3cb7781d8
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
%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: 48447d3db18343398488d3064324147d, type: 3}
|
||||
m_Name: Zram
|
||||
m_EditorClassIdentifier:
|
||||
id: pkg_zram
|
||||
displayName: zram
|
||||
slot: 0
|
||||
rarity: 3
|
||||
description: +1 max Cycles (COMBAT).
|
||||
flavourText: Compress the pain until it becomes throughput.
|
||||
designNotes: Generic 3-star Kernel powerspike. COMBAT cycle stat package.
|
||||
intendedDistroId:
|
||||
requiresSystem: []
|
||||
offDistroEffect: {kind: 2, amount: 1, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
onDistroEffect: {kind: 2, amount: 1, threshold: 0, refundCycle: 0, cleanseDebuffs: 0, enableFedoraSecondCardPassive: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a11dac6bc6d435192a262eb1d8ac685
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -274,5 +274,6 @@ MonoBehaviour:
|
||||
motdBody: unstable userspace detected; keep a rollback shell open.
|
||||
distroDatabase: {fileID: 11400000, guid: 4d88ca5446fa4d80b2fbd4b12697cb7c, type: 2}
|
||||
cardDatabase: {fileID: 11400000, guid: 1632132e32bfc31e8a293140f5908aa3, type: 2}
|
||||
packageDatabase: {fileID: 11400000, guid: efca08b3991e42e5b1e03878507496a6, type: 2}
|
||||
languageDeckDatabase: {fileID: 11400000, guid: a7d20000000000000000000000000001, type: 2}
|
||||
featuredUnitPanel: {}
|
||||
|
||||
@@ -84,8 +84,7 @@ namespace KernelPanic.Combat
|
||||
return;
|
||||
}
|
||||
|
||||
context.Source.Shield += amount;
|
||||
context.CombatManager.ReportEffectResult($"gained {amount} shield");
|
||||
context.CombatManager.GrantPlayerShield(amount, "card");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,8 +109,7 @@ namespace KernelPanic.Combat
|
||||
return;
|
||||
}
|
||||
|
||||
context.Source.Shield += amount;
|
||||
context.CombatManager.ReportEffectResult($"gained {amount} shield");
|
||||
context.CombatManager.GrantPlayerShield(amount, "card");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,8 +500,7 @@ namespace KernelPanic.Combat
|
||||
continue;
|
||||
}
|
||||
|
||||
context.Source.Shield += overkill;
|
||||
context.CombatManager.ReportEffectResult($"overkill -> {overkill} shield");
|
||||
context.CombatManager.GrantPlayerShield(overkill, "overkill");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -572,6 +569,7 @@ namespace KernelPanic.Combat
|
||||
if (context.HandController.Remove(junk))
|
||||
{
|
||||
context.DeckController.Exhaust(junk);
|
||||
context.CombatManager.HandleCardExhausted(junk);
|
||||
int cycleGain = UpgradeMath.ScaleAmount(_cycleGain, context.Card);
|
||||
context.Source.Cycles += cycleGain;
|
||||
context.CombatManager.ReportEffectResult($"autoremove exhausted {GetCardName(junk)}: +{cycleGain} cycle");
|
||||
|
||||
@@ -41,6 +41,12 @@ namespace KernelPanic.Combat
|
||||
private int fedoraCardsDiscountedThisTurn;
|
||||
private int fedoraCrashChance = 10;
|
||||
private int cardsPlayedThisTurn;
|
||||
private int cardsPlayedThisWave;
|
||||
private int turnNumberThisWave;
|
||||
private bool packageShieldBonusTriggeredThisTurn;
|
||||
private bool packageTimeshiftTriggeredThisWave;
|
||||
private bool packageInterpreterQueueShieldTriggeredThisWave;
|
||||
private bool packageNativeDamageTriggeredThisWave;
|
||||
private int javaCardsPlayedThisCombat;
|
||||
private int javaCardsDiscountThisTurn;
|
||||
private int rawhideBonusCharges;
|
||||
@@ -72,6 +78,16 @@ namespace KernelPanic.Combat
|
||||
runManager = GetComponent<RunManager>();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
GameEvents.DamageDealt += HandlePackageDamageDealt;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
GameEvents.DamageDealt -= HandlePackageDamageDealt;
|
||||
}
|
||||
|
||||
public void StartCombat()
|
||||
{
|
||||
if (runConfig == null)
|
||||
@@ -197,6 +213,7 @@ namespace KernelPanic.Combat
|
||||
ResolutionTrack track = card.Definition.ResolutionTrack;
|
||||
card.MarkPlayedThisTurn(cardsPlayedThisTurn == 0);
|
||||
cardsPlayedThisTurn++;
|
||||
cardsPlayedThisWave++;
|
||||
if (card.Definition.Language == Language.Java)
|
||||
{
|
||||
javaCardsPlayedThisCombat++;
|
||||
@@ -256,6 +273,7 @@ namespace KernelPanic.Combat
|
||||
}
|
||||
|
||||
playerState.DamageMultiplierPercent = 100;
|
||||
ApplyPackageCardPlayedEffects(card);
|
||||
|
||||
pendingTargetCard = null;
|
||||
TryApplyUbuntuEmptyHandRefill();
|
||||
@@ -281,6 +299,7 @@ namespace KernelPanic.Combat
|
||||
cost -= javaCardsPlayedThisCombat + javaCardsDiscountThisTurn;
|
||||
}
|
||||
|
||||
cost = ApplyPackageCostRules(card, cost);
|
||||
return Mathf.Max(0, cost);
|
||||
}
|
||||
|
||||
@@ -360,6 +379,16 @@ namespace KernelPanic.Combat
|
||||
ReportEffectResult($"next {charges} enemy attack(s) halved");
|
||||
}
|
||||
|
||||
public void HandleCardExhausted(CardInstance card)
|
||||
{
|
||||
if (card == null || !HasPackageEffect(PackageEffectKind.ExhaustShield, out PackageEffectData effect))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GrantPlayerShield(Mathf.Max(0, effect.Amount), "logrotate");
|
||||
}
|
||||
|
||||
public void ScheduleUpdateManagerRepeat(int damageAmount)
|
||||
{
|
||||
delayedEffects.Add(DelayedCombatEffect.UpdateManagerRepeat(damageAmount, 2));
|
||||
@@ -536,6 +565,12 @@ namespace KernelPanic.Combat
|
||||
fedoraCrashChance = 10;
|
||||
fedoraCardsDiscountedThisTurn = 0;
|
||||
cardsPlayedThisTurn = 0;
|
||||
cardsPlayedThisWave = 0;
|
||||
turnNumberThisWave = 0;
|
||||
packageShieldBonusTriggeredThisTurn = false;
|
||||
packageTimeshiftTriggeredThisWave = false;
|
||||
packageInterpreterQueueShieldTriggeredThisWave = false;
|
||||
packageNativeDamageTriggeredThisWave = false;
|
||||
javaCardsPlayedThisCombat = 0;
|
||||
javaCardsDiscountThisTurn = 0;
|
||||
rawhideBonusCharges = 0;
|
||||
@@ -545,6 +580,7 @@ namespace KernelPanic.Combat
|
||||
RandomRoll.Seed(runConfig.RunSeed);
|
||||
playerState = new CombatantState(runManager.EffectiveMaxUptime(), runManager.EffectiveRam(), runManager.EffectiveMaxCycles());
|
||||
ApplyVersionState(playerState);
|
||||
ApplyPackageState(playerState);
|
||||
yield return StartWaveSequenced(preservePlayerUptime: false);
|
||||
Log($"booted {runConfig.Distro.DisplayName} with {runManager.RunDeck.Count} cards");
|
||||
StateChanged?.Invoke();
|
||||
@@ -557,6 +593,7 @@ namespace KernelPanic.Combat
|
||||
{
|
||||
playerState = new CombatantState(runManager.EffectiveMaxUptime(), runManager.EffectiveRam(), runManager.EffectiveMaxCycles());
|
||||
ApplyVersionState(playerState);
|
||||
ApplyPackageState(playerState);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -570,11 +607,16 @@ namespace KernelPanic.Combat
|
||||
playerState.IsDefeated = false;
|
||||
playerState.MutableStatuses.Clear();
|
||||
ApplyVersionState(playerState);
|
||||
ApplyPackageState(playerState);
|
||||
}
|
||||
|
||||
handController = new HandController(playerState.Ram);
|
||||
selectedEnemyIndex = -1;
|
||||
pendingTargetCard = null;
|
||||
cardsPlayedThisWave = 0;
|
||||
turnNumberThisWave = 0;
|
||||
packageShieldBonusTriggeredThisTurn = false;
|
||||
packageTimeshiftTriggeredThisWave = false;
|
||||
|
||||
List<CardInstance> startingCards = new();
|
||||
for (int i = 0; i < runManager.RunDeck.Count; i++)
|
||||
@@ -594,6 +636,7 @@ namespace KernelPanic.Combat
|
||||
PickEnemyIntents();
|
||||
StateChanged?.Invoke();
|
||||
yield return DrawOpeningHandSequenced();
|
||||
ApplyPackageWaveStartEffects();
|
||||
skipNextAllocateDraw = true;
|
||||
}
|
||||
|
||||
@@ -607,7 +650,10 @@ namespace KernelPanic.Combat
|
||||
playerState.Cycles = playerState.MaxCycles;
|
||||
fedoraCardsDiscountedThisTurn = 0;
|
||||
cardsPlayedThisTurn = 0;
|
||||
turnNumberThisWave++;
|
||||
packageShieldBonusTriggeredThisTurn = false;
|
||||
javaCardsDiscountThisTurn = 0;
|
||||
ApplyPackageTurnStartEffects();
|
||||
if (nextTurnCycleBonus > 0)
|
||||
{
|
||||
playerState.Cycles += nextTurnCycleBonus;
|
||||
@@ -852,7 +898,7 @@ namespace KernelPanic.Combat
|
||||
return false;
|
||||
}
|
||||
|
||||
int limit = runConfig.DistroVersion >= 5 ? 2 : 1;
|
||||
int limit = runConfig.DistroVersion >= 5 || HasOnDistroPackageEffect(PackageEffectKind.DnfFedoraPassive, out PackageEffectData dnfEffect) && dnfEffect.EnableFedoraSecondCardPassive ? 2 : 1;
|
||||
return fedoraCardsDiscountedThisTurn < limit;
|
||||
}
|
||||
|
||||
@@ -870,6 +916,360 @@ namespace KernelPanic.Combat
|
||||
}
|
||||
}
|
||||
|
||||
private int ApplyPackageCostRules(CardInstance card, int cost)
|
||||
{
|
||||
if (card == null || cost <= 0)
|
||||
{
|
||||
return cost;
|
||||
}
|
||||
|
||||
IReadOnlyList<PackageInstance> packages = runConfig?.EquippedPackages;
|
||||
if (packages == null)
|
||||
{
|
||||
return cost;
|
||||
}
|
||||
|
||||
int nextTurnCard = cardsPlayedThisTurn + 1;
|
||||
int nextWaveCard = cardsPlayedThisWave + 1;
|
||||
for (int i = 0; i < packages.Count; i++)
|
||||
{
|
||||
PackageInstance package = packages[i];
|
||||
if (package?.Definition == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
PackageEffectData effect = package.EffectFor(runConfig?.Distro?.Id);
|
||||
switch (effect.Kind)
|
||||
{
|
||||
case PackageEffectKind.FirstCardEachWaveCostReduction:
|
||||
if (nextWaveCard == 1)
|
||||
{
|
||||
cost -= Mathf.Max(0, effect.Amount);
|
||||
}
|
||||
break;
|
||||
case PackageEffectKind.EveryNthCardEachWaveFree:
|
||||
if (effect.Threshold > 0 && nextWaveCard % effect.Threshold == 0)
|
||||
{
|
||||
cost = 0;
|
||||
}
|
||||
break;
|
||||
case PackageEffectKind.FirstCardsEachTurnCostReduction:
|
||||
if (nextTurnCard <= Mathf.Max(0, effect.Threshold))
|
||||
{
|
||||
cost -= Mathf.Max(0, effect.Amount);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return cost;
|
||||
}
|
||||
|
||||
private void ApplyPackageState(CombatantState state)
|
||||
{
|
||||
if (state == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
state.JavaScriptFlatDamageBonus = 0;
|
||||
IReadOnlyList<PackageInstance> packages = runConfig?.EquippedPackages;
|
||||
if (packages == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < packages.Count; i++)
|
||||
{
|
||||
PackageEffectData effect = packages[i] == null ? default : packages[i].EffectFor(runConfig?.Distro?.Id);
|
||||
if (effect.Kind == PackageEffectKind.JavaScriptFlatDamage)
|
||||
{
|
||||
state.JavaScriptFlatDamageBonus += Mathf.Max(0, effect.Amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyPackageWaveStartEffects()
|
||||
{
|
||||
IReadOnlyList<PackageInstance> packages = runConfig?.EquippedPackages;
|
||||
if (packages == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < packages.Count; i++)
|
||||
{
|
||||
PackageInstance package = packages[i];
|
||||
if (package?.Definition == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
PackageEffectData effect = package.EffectFor(runConfig?.Distro?.Id);
|
||||
switch (effect.Kind)
|
||||
{
|
||||
case PackageEffectKind.WaveDraw:
|
||||
StartCoroutine(DrawCardsToHandSequenced(Mathf.Max(0, effect.Amount), package.Definition.DisplayName));
|
||||
break;
|
||||
case PackageEffectKind.WaveStartShield:
|
||||
GrantPlayerShield(Mathf.Max(0, effect.Amount), package.Definition.DisplayName);
|
||||
break;
|
||||
case PackageEffectKind.FirstTurnEachWaveShield:
|
||||
if (turnNumberThisWave == 0)
|
||||
{
|
||||
GrantPlayerShield(Mathf.Max(0, effect.Amount), package.Definition.DisplayName);
|
||||
}
|
||||
break;
|
||||
case PackageEffectKind.FirstTurnFirstWaveDraw:
|
||||
if (CurrentWaveNumber == 1 && turnNumberThisWave == 0)
|
||||
{
|
||||
StartCoroutine(DrawCardsToHandSequenced(Mathf.Max(0, effect.Amount), package.Definition.DisplayName));
|
||||
}
|
||||
break;
|
||||
case PackageEffectKind.WaveGenerateBasicCard:
|
||||
GeneratePackageLanguageCard(package.Definition.DisplayName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyPackageTurnStartEffects()
|
||||
{
|
||||
if (HasPackageEffect(PackageEffectKind.EveryNthTurnShield, out PackageEffectData effect)
|
||||
&& effect.Threshold > 0
|
||||
&& turnNumberThisWave % effect.Threshold == 0)
|
||||
{
|
||||
GrantPlayerShield(Mathf.Max(0, effect.Amount), "cron");
|
||||
}
|
||||
|
||||
if (HasPackageEffect(PackageEffectKind.EveryNthTurnDraw, out effect)
|
||||
&& effect.Threshold > 0
|
||||
&& turnNumberThisWave % effect.Threshold == 0)
|
||||
{
|
||||
StartCoroutine(DrawCardsToHandSequenced(Mathf.Max(0, effect.Amount), "udev"));
|
||||
}
|
||||
|
||||
if (turnNumberThisWave == 1
|
||||
&& HasPackageEffect(PackageEffectKind.FirstTurnEachWaveCycle, out effect)
|
||||
&& effect.Amount > 0)
|
||||
{
|
||||
playerState.Cycles += effect.Amount;
|
||||
Log($"apt-fast: gained {effect.Amount} Cycle");
|
||||
}
|
||||
|
||||
if (HasPackageEffect(PackageEffectKind.StartTurnNoDebuffShield, out effect)
|
||||
&& !HasHarmfulStatus(playerState))
|
||||
{
|
||||
GrantPlayerShield(Mathf.Max(0, effect.Amount), "auditd");
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyPackageCardPlayedEffects(CardInstance card)
|
||||
{
|
||||
if (card == null || playerState == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (HasPackageEffect(PackageEffectKind.ThirdCardEachTurnGenerate, out PackageEffectData aptEffect)
|
||||
&& cardsPlayedThisTurn == Mathf.Max(1, aptEffect.Threshold))
|
||||
{
|
||||
GeneratePackageLanguageCard("apt");
|
||||
if (aptEffect.RefundCycle)
|
||||
{
|
||||
playerState.Cycles += 1;
|
||||
Log("apt refunded 1 Cycle");
|
||||
}
|
||||
}
|
||||
|
||||
if (HasPackageEffect(PackageEffectKind.DnfFedoraPassive, out PackageEffectData dnfEffect)
|
||||
&& cardsPlayedThisTurn == 1
|
||||
&& dnfEffect.Amount > 0)
|
||||
{
|
||||
playerState.FlatEffectBonus += dnfEffect.Amount;
|
||||
Log($"DNF wave buff +{dnfEffect.Amount} damage");
|
||||
}
|
||||
|
||||
if (!packageInterpreterQueueShieldTriggeredThisWave
|
||||
&& card.Definition.ResolutionTrack == ResolutionTrack.InterpreterQueue
|
||||
&& HasPackageEffect(PackageEffectKind.FirstInterpreterQueueCardEachWaveShield, out PackageEffectData queueEffect))
|
||||
{
|
||||
packageInterpreterQueueShieldTriggeredThisWave = true;
|
||||
GrantPlayerShield(Mathf.Max(0, queueEffect.Amount), "dbus");
|
||||
}
|
||||
|
||||
if (!packageNativeDamageTriggeredThisWave
|
||||
&& card.Definition.ResolutionTrack == ResolutionTrack.Native
|
||||
&& HasPackageEffect(PackageEffectKind.FirstNativeCardEachWaveFlatDamage, out PackageEffectData nativeEffect)
|
||||
&& nativeEffect.Amount > 0)
|
||||
{
|
||||
packageNativeDamageTriggeredThisWave = true;
|
||||
playerState.FlatEffectBonus += nativeEffect.Amount;
|
||||
Log($"make: first Native card +{nativeEffect.Amount} damage");
|
||||
}
|
||||
|
||||
if (HasPackageEffect(PackageEffectKind.EveryNthCardEachWaveCycle, out PackageEffectData cycleEffect)
|
||||
&& cycleEffect.Threshold > 0
|
||||
&& cardsPlayedThisWave % cycleEffect.Threshold == 0
|
||||
&& cycleEffect.Amount > 0)
|
||||
{
|
||||
playerState.Cycles += cycleEffect.Amount;
|
||||
Log($"systemd-timer: gained {cycleEffect.Amount} Cycle");
|
||||
}
|
||||
}
|
||||
|
||||
public void GrantPlayerShield(int amount, string label)
|
||||
{
|
||||
if (playerState == null || amount <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int total = amount;
|
||||
if (!packageShieldBonusTriggeredThisTurn
|
||||
&& HasPackageEffect(PackageEffectKind.FirstShieldEachTurnBonus, out PackageEffectData effect))
|
||||
{
|
||||
int bonus = Mathf.Max(0, effect.Amount);
|
||||
if (bonus > 0)
|
||||
{
|
||||
total += bonus;
|
||||
packageShieldBonusTriggeredThisTurn = true;
|
||||
Log($"SELinux shield +{bonus}");
|
||||
}
|
||||
}
|
||||
|
||||
playerState.Shield += total;
|
||||
if (!string.IsNullOrWhiteSpace(label))
|
||||
{
|
||||
Log($"{label}: gained {total} Shield");
|
||||
}
|
||||
}
|
||||
|
||||
private void GeneratePackageLanguageCard(string label)
|
||||
{
|
||||
if (handController == null || handController.RemainingRam <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Language language = RandomRoll.RollRange(0, 1, new RollContext(playerState)) == 0
|
||||
? runConfig.PrimaryLanguage
|
||||
: runConfig.SecondaryLanguage;
|
||||
|
||||
if (!TryCreateGeneratedCard(language, Rarity.Common, out CardInstance generated))
|
||||
{
|
||||
Log($"{label}: TODO card-generation pool unavailable");
|
||||
return;
|
||||
}
|
||||
|
||||
if (handController.Add(generated))
|
||||
{
|
||||
Log($"{label}: generated {GetCardName(generated)} at 0c");
|
||||
StateChanged?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
private void HandlePackageDamageDealt(DamageDealtEvent payload)
|
||||
{
|
||||
if (payload.Target != playerState
|
||||
|| payload.UptimeDamage <= 0
|
||||
|| packageTimeshiftTriggeredThisWave
|
||||
|| !HasPackageEffect(PackageEffectKind.WaveThresholdRestore, out PackageEffectData effect))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int thresholdPercent = Mathf.Clamp(effect.Threshold, 1, 100);
|
||||
int restoreTarget = Mathf.CeilToInt(playerState.MaxUptime * (thresholdPercent / 100f));
|
||||
if (playerState.CurrentUptime >= restoreTarget)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
packageTimeshiftTriggeredThisWave = true;
|
||||
playerState.CurrentUptime = restoreTarget;
|
||||
if (effect.CleanseDebuffs)
|
||||
{
|
||||
statusEffects.CleanseHarmful(playerState);
|
||||
}
|
||||
|
||||
Log($"Timeshift restored uptime to {thresholdPercent}%");
|
||||
StateChanged?.Invoke();
|
||||
}
|
||||
|
||||
private bool HasOnDistroPackageEffect(PackageEffectKind kind, out PackageEffectData effect)
|
||||
{
|
||||
effect = default;
|
||||
IReadOnlyList<PackageInstance> packages = runConfig?.EquippedPackages;
|
||||
if (packages == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < packages.Count; i++)
|
||||
{
|
||||
PackageInstance package = packages[i];
|
||||
if (package?.Definition == null || !package.Definition.IsIntendedFor(runConfig?.Distro?.Id))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
effect = package.EffectFor(runConfig?.Distro?.Id);
|
||||
if (effect.Kind == kind)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool HasPackageEffect(PackageEffectKind kind, out PackageEffectData effect)
|
||||
{
|
||||
effect = default;
|
||||
IReadOnlyList<PackageInstance> packages = runConfig?.EquippedPackages;
|
||||
if (packages == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < packages.Count; i++)
|
||||
{
|
||||
PackageInstance package = packages[i];
|
||||
if (package?.Definition == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
effect = package.EffectFor(runConfig?.Distro?.Id);
|
||||
if (effect.Kind == kind)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool HasHarmfulStatus(CombatantState state)
|
||||
{
|
||||
if (state == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < state.Statuses.Count; i++)
|
||||
{
|
||||
if (!StatusEffectController.GetDescriptor(state.Statuses[i].Type).IsBeneficial)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool IsCrashImmune(CardInstance card)
|
||||
{
|
||||
string id = card?.Definition?.Id;
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace KernelPanic.Combat
|
||||
public bool IgnoreDamageMultipliers { get; set; }
|
||||
public bool AllowFlatDamageBuffs { get; set; }
|
||||
public int FlatEffectBonus { get; set; }
|
||||
public int JavaScriptFlatDamageBonus { get; set; }
|
||||
public int DamageMultiplierPercent { get; set; } = 100;
|
||||
public int IncomingAttackHalfCharges { get; set; }
|
||||
public IReadOnlyList<StatusInstance> Statuses => _statuses;
|
||||
|
||||
@@ -64,6 +64,7 @@ namespace KernelPanic.Combat
|
||||
}
|
||||
|
||||
int amount = Mathf.Max(0, request.Amount);
|
||||
amount = ApplyFlatAdditions(amount, request);
|
||||
amount = ApplyMultipliers(amount, request);
|
||||
amount = ApplyCrit(amount, request, out bool wasCritical);
|
||||
amount = ApplyResistancesAndWeaknesses(amount, request);
|
||||
@@ -95,6 +96,16 @@ namespace KernelPanic.Combat
|
||||
return Mathf.RoundToInt(amount * (multiplier / 100f));
|
||||
}
|
||||
|
||||
private static int ApplyFlatAdditions(int amount, DamageRequest request)
|
||||
{
|
||||
if (request.Source != null && request.Language == Language.JavaScript)
|
||||
{
|
||||
amount += Mathf.Max(0, request.Source.JavaScriptFlatDamageBonus);
|
||||
}
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
private static int ApplyCrit(int amount, DamageRequest request, out bool wasCritical)
|
||||
{
|
||||
wasCritical = false;
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace KernelPanic.Data
|
||||
{
|
||||
public sealed class PackageDatabase : ScriptableObject
|
||||
{
|
||||
[SerializeField] private List<PackageDefinition> allPackages = new();
|
||||
|
||||
public IReadOnlyList<PackageDefinition> AllPackages => allPackages;
|
||||
|
||||
public PackageDefinition FindById(string id)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(id))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int i = 0; i < allPackages.Count; i++)
|
||||
{
|
||||
PackageDefinition package = allPackages[i];
|
||||
if (package != null && string.Equals(package.Id, id, System.StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return package;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public PackageDefinition FindByRarity(int rarity, int index)
|
||||
{
|
||||
int safeRarity = Mathf.Clamp(rarity, 1, 5);
|
||||
int matchIndex = 0;
|
||||
for (int i = 0; i < allPackages.Count; i++)
|
||||
{
|
||||
PackageDefinition package = allPackages[i];
|
||||
if (package == null || package.Rarity != safeRarity)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (matchIndex == index)
|
||||
{
|
||||
return package;
|
||||
}
|
||||
|
||||
matchIndex++;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public int CountByRarity(int rarity)
|
||||
{
|
||||
int safeRarity = Mathf.Clamp(rarity, 1, 5);
|
||||
int count = 0;
|
||||
for (int i = 0; i < allPackages.Count; i++)
|
||||
{
|
||||
if (allPackages[i] != null && allPackages[i].Rarity == safeRarity)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace KernelPanic.Data
|
||||
{
|
||||
public enum PackageSlot
|
||||
{
|
||||
Kernel,
|
||||
Runtime,
|
||||
Daemon
|
||||
}
|
||||
|
||||
public enum PackageEffectKind
|
||||
{
|
||||
None = 0,
|
||||
MaxUptime = 1,
|
||||
MaxCycles = 2,
|
||||
WaveDraw = 3,
|
||||
WaveGenerateBasicCard = 4,
|
||||
FirstCardEachWaveCostReduction = 5,
|
||||
EveryNthTurnShield = 6,
|
||||
ExhaustShield = 7,
|
||||
EveryNthCardEachWaveFree = 8,
|
||||
FirstCardsEachTurnCostReduction = 9,
|
||||
ThirdCardEachTurnGenerate = 10,
|
||||
JavaScriptFlatDamage = 11,
|
||||
WaveThresholdRestore = 12,
|
||||
FirstShieldEachTurnBonus = 13,
|
||||
DnfFedoraPassive = 14,
|
||||
WaveStartShield = 15,
|
||||
FirstTurnEachWaveShield = 16,
|
||||
FirstTurnFirstWaveDraw = 17,
|
||||
FirstTurnEachWaveCycle = 18,
|
||||
MaxRam = 19,
|
||||
FirstNativeCardEachWaveFlatDamage = 20,
|
||||
FirstInterpreterQueueCardEachWaveShield = 21,
|
||||
EveryNthTurnDraw = 22,
|
||||
StartTurnNoDebuffShield = 23,
|
||||
EveryNthCardEachWaveCycle = 24
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct PackageEffectData
|
||||
{
|
||||
[SerializeField] private PackageEffectKind kind;
|
||||
[SerializeField] private int amount;
|
||||
[SerializeField] private int threshold;
|
||||
[SerializeField] private bool refundCycle;
|
||||
[SerializeField] private bool cleanseDebuffs;
|
||||
[SerializeField] private bool enableFedoraSecondCardPassive;
|
||||
|
||||
public PackageEffectData(PackageEffectKind kind, int amount, int threshold, bool refundCycle, bool cleanseDebuffs, bool enableFedoraSecondCardPassive)
|
||||
{
|
||||
this.kind = kind;
|
||||
this.amount = amount;
|
||||
this.threshold = threshold;
|
||||
this.refundCycle = refundCycle;
|
||||
this.cleanseDebuffs = cleanseDebuffs;
|
||||
this.enableFedoraSecondCardPassive = enableFedoraSecondCardPassive;
|
||||
}
|
||||
|
||||
public PackageEffectKind Kind => kind;
|
||||
public int Amount => amount;
|
||||
public int Threshold => threshold;
|
||||
public bool RefundCycle => refundCycle;
|
||||
public bool CleanseDebuffs => cleanseDebuffs;
|
||||
public bool EnableFedoraSecondCardPassive => enableFedoraSecondCardPassive;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines persistent meta packages equipped into distro Kernel/Runtime/Daemon slots.
|
||||
/// Package loadouts are meta progression and carry into every run for that distro.
|
||||
/// Card loadouts remain run setup only.
|
||||
/// </summary>
|
||||
public sealed class PackageDefinition : ScriptableObject
|
||||
{
|
||||
[SerializeField] private string id;
|
||||
[SerializeField] private string displayName;
|
||||
[SerializeField] private PackageSlot slot;
|
||||
[SerializeField, Range(1, 5)] private int rarity = 1;
|
||||
[SerializeField, TextArea] private string description;
|
||||
[SerializeField] private string flavourText;
|
||||
[SerializeField, TextArea] private string designNotes;
|
||||
[SerializeField] private string intendedDistroId;
|
||||
[SerializeField] private List<string> requiresSystem = new();
|
||||
[SerializeField] private PackageEffectData offDistroEffect;
|
||||
[SerializeField] private PackageEffectData onDistroEffect;
|
||||
|
||||
public string Id => id;
|
||||
public string DisplayName => displayName;
|
||||
public PackageSlot Slot => slot;
|
||||
public int Rarity => Mathf.Clamp(rarity, 1, 5);
|
||||
public string Description => description;
|
||||
public string FlavourText => flavourText;
|
||||
public string FlavorText => flavourText;
|
||||
public string DesignNotes => designNotes;
|
||||
public string IntendedDistroId => intendedDistroId;
|
||||
public IReadOnlyList<string> RequiresSystem => requiresSystem;
|
||||
public PackageEffectData OffDistroEffect => offDistroEffect;
|
||||
public PackageEffectData OnDistroEffect => onDistroEffect;
|
||||
|
||||
public bool IsIntendedFor(string distroId)
|
||||
{
|
||||
return !string.IsNullOrWhiteSpace(intendedDistroId)
|
||||
&& string.Equals(intendedDistroId, distroId, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public PackageEffectData EffectFor(string distroId)
|
||||
{
|
||||
return IsIntendedFor(distroId) ? onDistroEffect : offDistroEffect;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public sealed class PackageInstance
|
||||
{
|
||||
public PackageInstance(PackageDefinition definition, int upgradeLevel)
|
||||
{
|
||||
Definition = definition;
|
||||
UpgradeLevel = Mathf.Clamp(upgradeLevel, 0, KernelPanic.Meta.PackageTuning.MaxPackageLevel);
|
||||
}
|
||||
|
||||
public PackageDefinition Definition { get; }
|
||||
public int UpgradeLevel { get; }
|
||||
|
||||
public PackageEffectData EffectFor(string distroId)
|
||||
{
|
||||
PackageEffectData effect = Definition == null ? default : Definition.EffectFor(distroId);
|
||||
return PackageEffectScaling.Scale(effect, UpgradeLevel);
|
||||
}
|
||||
}
|
||||
|
||||
public static class PackageEffectScaling
|
||||
{
|
||||
public static PackageEffectData Scale(PackageEffectData effect, int upgradeLevel)
|
||||
{
|
||||
int level = Mathf.Clamp(upgradeLevel, 0, KernelPanic.Meta.PackageTuning.MaxPackageLevel);
|
||||
if (level <= 0 || effect.Kind == PackageEffectKind.None)
|
||||
{
|
||||
return effect;
|
||||
}
|
||||
|
||||
int amount = effect.Amount + GetAmountPerLevel(effect.Kind, effect.Amount) * level;
|
||||
return new PackageEffectData(effect.Kind, amount, effect.Threshold, effect.RefundCycle, effect.CleanseDebuffs, effect.EnableFedoraSecondCardPassive);
|
||||
}
|
||||
|
||||
private static int GetAmountPerLevel(PackageEffectKind kind, int baseAmount)
|
||||
{
|
||||
return kind switch
|
||||
{
|
||||
PackageEffectKind.MaxUptime => Mathf.Max(1, Mathf.CeilToInt(Mathf.Max(1, baseAmount) * 0.5f)),
|
||||
PackageEffectKind.MaxCycles => 1,
|
||||
PackageEffectKind.MaxRam => 1,
|
||||
PackageEffectKind.WaveDraw => 1,
|
||||
PackageEffectKind.FirstTurnFirstWaveDraw => 1,
|
||||
PackageEffectKind.FirstTurnEachWaveCycle => 1,
|
||||
PackageEffectKind.FirstCardsEachTurnCostReduction => 1,
|
||||
PackageEffectKind.FirstCardEachWaveCostReduction => 1,
|
||||
PackageEffectKind.FirstNativeCardEachWaveFlatDamage => 1,
|
||||
PackageEffectKind.JavaScriptFlatDamage => 1,
|
||||
_ => 1
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,12 @@ namespace KernelPanic.Meta
|
||||
/// </summary>
|
||||
public enum GachaCurrencyType
|
||||
{
|
||||
StandardPull,
|
||||
LimitedPull
|
||||
StandardPull
|
||||
}
|
||||
|
||||
public enum PullPaymentSource
|
||||
{
|
||||
Commits,
|
||||
Entropy
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@ namespace KernelPanic.Meta
|
||||
public static bool HasPendingPull => pendingPull != null;
|
||||
public static bool HasCompletedPull => completedPull != null;
|
||||
|
||||
public static void SetPending(string bannerId, int pullCount, int entropyTokenCount, DistroDatabase distroDatabase, string focusUnitId)
|
||||
public static void SetPending(string bannerId, int pullCount, int entropyTokenCount, DistroDatabase distroDatabase, PackageDatabase packageDatabase, string focusUnitId)
|
||||
{
|
||||
pendingPull = new PendingGachaPull(bannerId, pullCount, entropyTokenCount, distroDatabase, focusUnitId);
|
||||
pendingPull = new PendingGachaPull(bannerId, pullCount, entropyTokenCount, distroDatabase, packageDatabase, focusUnitId);
|
||||
completedPull = null;
|
||||
}
|
||||
|
||||
@@ -44,12 +44,13 @@ namespace KernelPanic.Meta
|
||||
|
||||
public sealed class PendingGachaPull
|
||||
{
|
||||
public PendingGachaPull(string bannerId, int pullCount, int entropyTokenCount, DistroDatabase distroDatabase, string focusUnitId)
|
||||
public PendingGachaPull(string bannerId, int pullCount, int entropyTokenCount, DistroDatabase distroDatabase, PackageDatabase packageDatabase, string focusUnitId)
|
||||
{
|
||||
BannerId = string.IsNullOrWhiteSpace(bannerId) ? GachaService.BeginnerBannerId : bannerId;
|
||||
PullCount = Math.Max(1, pullCount);
|
||||
EntropyTokenCount = Math.Max(0, entropyTokenCount);
|
||||
DistroDatabase = distroDatabase;
|
||||
PackageDatabase = packageDatabase;
|
||||
FocusUnitId = focusUnitId;
|
||||
}
|
||||
|
||||
@@ -57,6 +58,7 @@ namespace KernelPanic.Meta
|
||||
public int PullCount { get; }
|
||||
public int EntropyTokenCount { get; }
|
||||
public DistroDatabase DistroDatabase { get; }
|
||||
public PackageDatabase PackageDatabase { get; }
|
||||
public string FocusUnitId { get; }
|
||||
}
|
||||
|
||||
@@ -131,7 +133,7 @@ namespace KernelPanic.Meta
|
||||
public bool PityTriggered { get; }
|
||||
public bool IsCharacter => RewardType == GachaRewardType.Distro || RewardType == GachaRewardType.FutureStandardFiveStarDistro;
|
||||
|
||||
public string TypeText => IsCharacter ? "character" : "equipment";
|
||||
public string TypeText => IsCharacter ? "character" : "package";
|
||||
|
||||
public string StatusText
|
||||
{
|
||||
@@ -173,7 +175,7 @@ namespace KernelPanic.Meta
|
||||
return "unknown result";
|
||||
}
|
||||
|
||||
if (rewardType != GachaRewardType.Equipment)
|
||||
if (rewardType != GachaRewardType.Package)
|
||||
{
|
||||
return displayName;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace KernelPanic.Meta
|
||||
/// </summary>
|
||||
public enum GachaRewardType
|
||||
{
|
||||
Equipment,
|
||||
Package,
|
||||
Distro,
|
||||
FutureStandardFiveStarDistro
|
||||
}
|
||||
|
||||
@@ -14,11 +14,12 @@ namespace KernelPanic.Meta
|
||||
public const string LimitedBannerId = "limited";
|
||||
public const int BeginnerMaxPulls = 50;
|
||||
public const int BeginnerSinglePullCost = 1;
|
||||
public const int BeginnerTenPullCost = 8;
|
||||
public const int BeginnerTenPullCost = 10;
|
||||
public const int FourStarHardPity = 10;
|
||||
public const int FiveStarSoftPityStart = 66;
|
||||
public const int FiveStarHardPity = 80;
|
||||
public const int EntropyPerPullToken = 100;
|
||||
public const int EntropyPerCommit = 100;
|
||||
public const int RootCreditsToEntropy = 1;
|
||||
public const int TestRootCreditsBalance = 10000;
|
||||
|
||||
private const double FourStarBaseChance = 0.12d;
|
||||
@@ -41,11 +42,10 @@ namespace KernelPanic.Meta
|
||||
{
|
||||
this._random = random ?? new Random();
|
||||
_currencyBalances[GachaCurrencyType.StandardPull] = 0;
|
||||
_currencyBalances[GachaCurrencyType.LimitedPull] = 0;
|
||||
}
|
||||
|
||||
public int PullTokens => GetCurrencyBalance(GachaCurrencyType.StandardPull);
|
||||
public int LimitedPullTokens => GetCurrencyBalance(GachaCurrencyType.LimitedPull);
|
||||
public int Commits => PullTokens;
|
||||
public int RootCredits { get; private set; }
|
||||
public IReadOnlyList<DistroDefinition> BannerPool => _bannerPool;
|
||||
public GachaBannerState BeginnerState => _beginnerState;
|
||||
@@ -62,9 +62,8 @@ namespace KernelPanic.Meta
|
||||
}
|
||||
|
||||
data.EnsureLists();
|
||||
RootCredits = Math.Max(TestRootCreditsBalance, data.rootCredits);
|
||||
SetCurrencyBalanceSilently(GachaCurrencyType.StandardPull, data.standardPullCurrency);
|
||||
SetCurrencyBalanceSilently(GachaCurrencyType.LimitedPull, data.limitedPullCurrency);
|
||||
RootCredits = Math.Max(0, data.rootCredits);
|
||||
SetCurrencyBalanceSilently(GachaCurrencyType.StandardPull, data.commitsBalance);
|
||||
_beginnerState = data.beginnerBannerState ?? new GachaBannerState(BeginnerBannerId);
|
||||
_beginnerState.bannerId = BeginnerBannerId;
|
||||
_beginnerState.EnsureLists();
|
||||
@@ -87,8 +86,7 @@ namespace KernelPanic.Meta
|
||||
|
||||
data.EnsureLists();
|
||||
data.rootCredits = RootCredits;
|
||||
data.standardPullCurrency = GetCurrencyBalance(GachaCurrencyType.StandardPull);
|
||||
data.limitedPullCurrency = GetCurrencyBalance(GachaCurrencyType.LimitedPull);
|
||||
data.commitsBalance = GetCurrencyBalance(GachaCurrencyType.StandardPull);
|
||||
data.beginnerBannerState = CloneState(_beginnerState);
|
||||
}
|
||||
|
||||
@@ -125,6 +123,11 @@ namespace KernelPanic.Meta
|
||||
}
|
||||
|
||||
public bool ConvertRootCreditsToEntropy(EntropyWallet wallet, int amount, out string failureReason)
|
||||
{
|
||||
return BuyEntropy(wallet, amount, out failureReason);
|
||||
}
|
||||
|
||||
public bool BuyEntropy(EntropyWallet wallet, int rootCredits, out string failureReason)
|
||||
{
|
||||
if (wallet == null)
|
||||
{
|
||||
@@ -132,20 +135,20 @@ namespace KernelPanic.Meta
|
||||
return false;
|
||||
}
|
||||
|
||||
if (amount <= 0)
|
||||
if (rootCredits <= 0)
|
||||
{
|
||||
failureReason = "no root-credits selected";
|
||||
failureReason = "no Root Credits selected";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (RootCredits < amount)
|
||||
if (RootCredits < rootCredits)
|
||||
{
|
||||
failureReason = $"need {amount} root-credits";
|
||||
failureReason = $"need {rootCredits} Root Credits";
|
||||
return false;
|
||||
}
|
||||
|
||||
RootCredits -= amount;
|
||||
wallet.Add(amount);
|
||||
RootCredits -= rootCredits;
|
||||
wallet.Add(rootCredits * RootCreditsToEntropy);
|
||||
failureReason = null;
|
||||
Changed?.Invoke();
|
||||
return true;
|
||||
@@ -187,6 +190,11 @@ namespace KernelPanic.Meta
|
||||
}
|
||||
|
||||
public bool CanPullBeginner(int pullCount, out string failureReason)
|
||||
{
|
||||
return CanAffordPull(pullCount, null, PullPaymentSource.Commits, out failureReason);
|
||||
}
|
||||
|
||||
public bool CanAffordPull(int pullCount, EntropyWallet wallet, PullPaymentSource source, out string failureReason)
|
||||
{
|
||||
if (pullCount != 1 && pullCount != 10)
|
||||
{
|
||||
@@ -208,49 +216,73 @@ namespace KernelPanic.Meta
|
||||
}
|
||||
|
||||
int cost = GetBeginnerPullCost(pullCount);
|
||||
if (GetCurrencyBalance(GachaCurrencyType.StandardPull) < cost)
|
||||
if (source == PullPaymentSource.Commits && GetCurrencyBalance(GachaCurrencyType.StandardPull) < cost)
|
||||
{
|
||||
failureReason = $"need {cost} {FormatCurrencyName(GachaCurrencyType.StandardPull)}";
|
||||
return false;
|
||||
}
|
||||
|
||||
int entropyCost = cost * EntropyPerCommit;
|
||||
if (source == PullPaymentSource.Entropy && (wallet == null || wallet.Balance < entropyCost))
|
||||
{
|
||||
failureReason = $"need {entropyCost} Entropy";
|
||||
return false;
|
||||
}
|
||||
|
||||
failureReason = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool PayForPull(int pullCount, EntropyWallet wallet, PullPaymentSource source, out int commitsSpent, out int entropySpent, out string failureReason)
|
||||
{
|
||||
commitsSpent = 0;
|
||||
entropySpent = 0;
|
||||
if (!CanAffordPull(pullCount, wallet, source, out failureReason))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int cost = GetBeginnerPullCost(pullCount);
|
||||
if (source == PullPaymentSource.Commits)
|
||||
{
|
||||
commitsSpent = cost;
|
||||
SetCurrencyBalanceSilently(GachaCurrencyType.StandardPull, GetCurrencyBalance(GachaCurrencyType.StandardPull) - commitsSpent);
|
||||
}
|
||||
else
|
||||
{
|
||||
entropySpent = cost * EntropyPerCommit;
|
||||
wallet.Spend(entropySpent);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int GetMissingPullTokens(GachaCurrencyType currencyType, int pullCost)
|
||||
{
|
||||
return Math.Max(0, pullCost - GetCurrencyBalance(currencyType));
|
||||
}
|
||||
|
||||
public bool CanCoverMissingPullTokensWithEntropy(EntropyWallet wallet, int missingPullTokens)
|
||||
{
|
||||
return missingPullTokens <= 0 || (wallet != null && wallet.Balance >= missingPullTokens * EntropyPerPullToken);
|
||||
}
|
||||
|
||||
public GachaPullResult PerformBeginnerPull(int pullCount)
|
||||
{
|
||||
return PerformBeginnerPull(pullCount, null, 0);
|
||||
return PerformBeginnerPull(pullCount, null, PullPaymentSource.Commits);
|
||||
}
|
||||
|
||||
public GachaPullResult PerformBeginnerPull(int pullCount, EntropyWallet wallet, int entropyTokenCount)
|
||||
{
|
||||
if (!CanPullBeginnerWithEntropy(pullCount, wallet, entropyTokenCount, out string failureReason))
|
||||
PullPaymentSource source = entropyTokenCount > 0 ? PullPaymentSource.Entropy : PullPaymentSource.Commits;
|
||||
return PerformBeginnerPull(pullCount, wallet, source);
|
||||
}
|
||||
|
||||
public GachaPullResult PerformBeginnerPull(int pullCount, EntropyWallet wallet, PullPaymentSource source)
|
||||
{
|
||||
if (!CanAffordPull(pullCount, wallet, source, out string failureReason))
|
||||
{
|
||||
return GachaPullResult.Failed(BeginnerBannerId, failureReason);
|
||||
}
|
||||
|
||||
int cost = GetBeginnerPullCost(pullCount);
|
||||
int tokenSpend = cost - entropyTokenCount;
|
||||
if (tokenSpend > 0)
|
||||
if (!PayForPull(pullCount, wallet, source, out int commitSpend, out int entropySpent, out failureReason))
|
||||
{
|
||||
SetCurrencyBalanceSilently(GachaCurrencyType.StandardPull, GetCurrencyBalance(GachaCurrencyType.StandardPull) - tokenSpend);
|
||||
}
|
||||
|
||||
int entropySpent = entropyTokenCount * EntropyPerPullToken;
|
||||
if (entropySpent > 0)
|
||||
{
|
||||
wallet.Spend(entropySpent);
|
||||
return GachaPullResult.Failed(BeginnerBannerId, failureReason);
|
||||
}
|
||||
|
||||
List<GachaReward> rewards = new();
|
||||
@@ -266,14 +298,13 @@ namespace KernelPanic.Meta
|
||||
}
|
||||
|
||||
Changed?.Invoke();
|
||||
return new GachaPullResult(true, BeginnerBannerId, GachaCurrencyType.StandardPull, tokenSpend, entropySpent, rewards, null);
|
||||
return new GachaPullResult(true, BeginnerBannerId, GachaCurrencyType.StandardPull, commitSpend, entropySpent, rewards, null);
|
||||
}
|
||||
|
||||
public static string FormatCurrencyName(GachaCurrencyType currencyType)
|
||||
{
|
||||
return currencyType switch
|
||||
{
|
||||
GachaCurrencyType.LimitedPull => "Root Credits",
|
||||
_ => "Commits"
|
||||
};
|
||||
}
|
||||
@@ -335,7 +366,7 @@ namespace KernelPanic.Meta
|
||||
if (!hitFourStarOrCharacter)
|
||||
{
|
||||
_beginnerState.pityCounter++;
|
||||
return GachaReward.Equipment(3, "3-star equipment", false, false);
|
||||
return GachaReward.Package(3, "3-star package", false, false);
|
||||
}
|
||||
|
||||
_beginnerState.pityCounter = 0;
|
||||
@@ -345,7 +376,7 @@ namespace KernelPanic.Meta
|
||||
return GachaReward.DistroReward(distro, 4, pityTriggered, false);
|
||||
}
|
||||
|
||||
return GachaReward.Equipment(4, "4-star equipment", pityTriggered, false);
|
||||
return GachaReward.Package(4, "4-star package", pityTriggered, false);
|
||||
}
|
||||
|
||||
private bool TryRollFiveStar(GachaBannerState state, out bool pityTriggered)
|
||||
@@ -379,7 +410,7 @@ namespace KernelPanic.Meta
|
||||
{
|
||||
if (_bannerPool.Count == 0 || _random.NextDouble() >= DistroChanceOnFeaturedTier)
|
||||
{
|
||||
return GachaReward.Equipment(5, "5-star equipment", pityTriggered, false);
|
||||
return GachaReward.Package(5, "5-star package", pityTriggered, false);
|
||||
}
|
||||
|
||||
DistroDefinition distro = _bannerPool.Count == 0 ? null : _bannerPool[_random.Next(_bannerPool.Count)];
|
||||
@@ -420,7 +451,7 @@ namespace KernelPanic.Meta
|
||||
|
||||
distro ??= _bannerPool.Count == 0 ? null : _bannerPool[Math.Min(guaranteeIndex, _bannerPool.Count - 1)];
|
||||
return distro == null
|
||||
? GachaReward.Equipment(4, "4-star equipment", true, true)
|
||||
? GachaReward.Package(4, "4-star package", true, true)
|
||||
: GachaReward.DistroReward(distro, 4, true, true, reason);
|
||||
}
|
||||
|
||||
@@ -448,52 +479,6 @@ namespace KernelPanic.Meta
|
||||
_currencyBalances[currencyType] = Math.Max(0, amount);
|
||||
}
|
||||
|
||||
private bool CanPullBeginnerWithEntropy(int pullCount, EntropyWallet wallet, int entropyTokenCount, out string failureReason)
|
||||
{
|
||||
if (pullCount != 1 && pullCount != 10)
|
||||
{
|
||||
failureReason = "only single and ten pulls are supported";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsBeginnerBannerAvailable)
|
||||
{
|
||||
failureReason = "beginner banner unavailable";
|
||||
return false;
|
||||
}
|
||||
|
||||
int remainingPulls = BeginnerMaxPulls - _beginnerState.totalPulls;
|
||||
if (pullCount > remainingPulls)
|
||||
{
|
||||
failureReason = $"only {remainingPulls} beginner pull(s) remain";
|
||||
return false;
|
||||
}
|
||||
|
||||
int cost = GetBeginnerPullCost(pullCount);
|
||||
if (entropyTokenCount < 0 || entropyTokenCount > cost)
|
||||
{
|
||||
failureReason = "invalid entropy substitute amount";
|
||||
return false;
|
||||
}
|
||||
|
||||
int tokenSpend = cost - entropyTokenCount;
|
||||
if (GetCurrencyBalance(GachaCurrencyType.StandardPull) < tokenSpend)
|
||||
{
|
||||
failureReason = $"need {tokenSpend} {FormatCurrencyName(GachaCurrencyType.StandardPull)}";
|
||||
return false;
|
||||
}
|
||||
|
||||
int entropySpend = entropyTokenCount * EntropyPerPullToken;
|
||||
if (entropySpend > 0 && (wallet == null || wallet.Balance < entropySpend))
|
||||
{
|
||||
failureReason = $"need {entropySpend} entropy";
|
||||
return false;
|
||||
}
|
||||
|
||||
failureReason = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static GachaBannerState CloneState(GachaBannerState state)
|
||||
{
|
||||
state ??= new GachaBannerState(BeginnerBannerId);
|
||||
@@ -542,9 +527,9 @@ namespace KernelPanic.Meta
|
||||
public bool Guaranteed { get; }
|
||||
public string GuaranteeReason { get; }
|
||||
|
||||
public static GachaReward Equipment(int starRating, string displayName, bool pityTriggered, bool guaranteed)
|
||||
public static GachaReward Package(int starRating, string displayName, bool pityTriggered, bool guaranteed)
|
||||
{
|
||||
return new GachaReward(GachaRewardType.Equipment, starRating, displayName, null, pityTriggered, guaranteed, null);
|
||||
return new GachaReward(GachaRewardType.Package, starRating, displayName, null, pityTriggered, guaranteed, null);
|
||||
}
|
||||
|
||||
public static GachaReward DistroReward(DistroDefinition distro, int starRating, bool pityTriggered, bool guaranteed, string guaranteeReason = null)
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using KernelPanic.Data;
|
||||
|
||||
namespace KernelPanic.Meta
|
||||
{
|
||||
public enum PackageLoadoutFailureReason
|
||||
{
|
||||
None,
|
||||
WrongSlot,
|
||||
NotOwned,
|
||||
SlotOccupied,
|
||||
NotEquipped
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pure meta model for persistent package slots. Unlike CardLoadout, this is not
|
||||
/// run-only: equipped package ids are saved per distro and reused in every run.
|
||||
/// </summary>
|
||||
public sealed class PackageLoadout
|
||||
{
|
||||
private readonly PlayerCollection _collection;
|
||||
private readonly PackageDatabase _database;
|
||||
private readonly Dictionary<string, Dictionary<PackageSlot, string>> _equippedByDistro = new(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public PackageLoadout(PlayerCollection collection, PackageDatabase database)
|
||||
{
|
||||
_collection = collection;
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public IReadOnlyDictionary<PackageSlot, string> GetEquippedPackageIds(string distroId)
|
||||
{
|
||||
return !string.IsNullOrWhiteSpace(distroId) && _equippedByDistro.TryGetValue(distroId, out Dictionary<PackageSlot, string> equipped)
|
||||
? equipped
|
||||
: Empty;
|
||||
}
|
||||
|
||||
public PackageDefinition GetEquippedPackage(string distroId, PackageSlot slot)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(distroId)
|
||||
|| !_equippedByDistro.TryGetValue(distroId, out Dictionary<PackageSlot, string> equipped)
|
||||
|| !equipped.TryGetValue(slot, out string packageId))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return _database == null ? null : _database.FindById(packageId);
|
||||
}
|
||||
|
||||
public IReadOnlyList<PackageDefinition> GetEquippedPackages(string distroId)
|
||||
{
|
||||
List<PackageDefinition> packages = new();
|
||||
AddIfEquipped(distroId, PackageSlot.Kernel, packages);
|
||||
AddIfEquipped(distroId, PackageSlot.Runtime, packages);
|
||||
AddIfEquipped(distroId, PackageSlot.Daemon, packages);
|
||||
return packages;
|
||||
}
|
||||
|
||||
public IReadOnlyList<PackageInstance> GetEquippedPackageInstances(string distroId)
|
||||
{
|
||||
List<PackageInstance> packages = new();
|
||||
AddInstanceIfEquipped(distroId, PackageSlot.Kernel, packages);
|
||||
AddInstanceIfEquipped(distroId, PackageSlot.Runtime, packages);
|
||||
AddInstanceIfEquipped(distroId, PackageSlot.Daemon, packages);
|
||||
return packages;
|
||||
}
|
||||
|
||||
public bool IsEquipped(string packageId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(packageId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<string, Dictionary<PackageSlot, string>> distro in _equippedByDistro)
|
||||
{
|
||||
foreach (KeyValuePair<PackageSlot, string> slot in distro.Value)
|
||||
{
|
||||
if (string.Equals(slot.Value, packageId, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryEquip(string distroId, PackageSlot slot, string packageId, out PackageLoadoutFailureReason reason)
|
||||
{
|
||||
PackageDefinition package = _database == null ? null : _database.FindById(packageId);
|
||||
if (package == null || _collection == null || !_collection.IsPackageOwned(package.Id))
|
||||
{
|
||||
reason = PackageLoadoutFailureReason.NotOwned;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (package.Slot != slot)
|
||||
{
|
||||
reason = PackageLoadoutFailureReason.WrongSlot;
|
||||
return false;
|
||||
}
|
||||
|
||||
Dictionary<PackageSlot, string> equipped = EnsureDistro(distroId);
|
||||
if (equipped.TryGetValue(slot, out string current) && !string.Equals(current, package.Id, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
reason = PackageLoadoutFailureReason.SlotOccupied;
|
||||
return false;
|
||||
}
|
||||
|
||||
equipped[slot] = package.Id;
|
||||
reason = PackageLoadoutFailureReason.None;
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryUnequip(string distroId, PackageSlot slot, out PackageLoadoutFailureReason reason)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(distroId)
|
||||
|| !_equippedByDistro.TryGetValue(distroId, out Dictionary<PackageSlot, string> equipped)
|
||||
|| !equipped.Remove(slot))
|
||||
{
|
||||
reason = PackageLoadoutFailureReason.NotEquipped;
|
||||
return false;
|
||||
}
|
||||
|
||||
reason = PackageLoadoutFailureReason.None;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Load(string distroId, IEnumerable<PackageLoadoutSlotSaveEntry> slots)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(distroId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Dictionary<PackageSlot, string> equipped = EnsureDistro(distroId);
|
||||
equipped.Clear();
|
||||
foreach (PackageLoadoutSlotSaveEntry slotEntry in slots ?? Array.Empty<PackageLoadoutSlotSaveEntry>())
|
||||
{
|
||||
PackageDefinition package = _database == null ? null : _database.FindById(slotEntry?.packageId);
|
||||
if (package == null || !_collection.IsPackageOwned(package.Id) || package.Slot != slotEntry.slot)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
equipped[package.Slot] = package.Id;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_equippedByDistro.Clear();
|
||||
}
|
||||
|
||||
private void AddIfEquipped(string distroId, PackageSlot slot, List<PackageDefinition> packages)
|
||||
{
|
||||
PackageDefinition package = GetEquippedPackage(distroId, slot);
|
||||
if (package != null)
|
||||
{
|
||||
packages.Add(package);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddInstanceIfEquipped(string distroId, PackageSlot slot, List<PackageInstance> packages)
|
||||
{
|
||||
PackageDefinition definition = GetEquippedPackage(distroId, slot);
|
||||
OwnedPackageInstance owned = definition == null ? null : _collection.GetOwnedPackage(definition.Id);
|
||||
if (owned != null)
|
||||
{
|
||||
packages.Add(owned.ToRuntimeInstance());
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<PackageSlot, string> EnsureDistro(string distroId)
|
||||
{
|
||||
string key = string.IsNullOrWhiteSpace(distroId) ? string.Empty : distroId;
|
||||
if (!_equippedByDistro.TryGetValue(key, out Dictionary<PackageSlot, string> equipped))
|
||||
{
|
||||
equipped = new Dictionary<PackageSlot, string>();
|
||||
_equippedByDistro[key] = equipped;
|
||||
}
|
||||
|
||||
return equipped;
|
||||
}
|
||||
|
||||
private static readonly IReadOnlyDictionary<PackageSlot, string> Empty = new Dictionary<PackageSlot, string>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using KernelPanic.Data;
|
||||
|
||||
namespace KernelPanic.Meta
|
||||
{
|
||||
public enum PackageScrapFailureReason
|
||||
{
|
||||
None,
|
||||
NotOwned,
|
||||
Equipped
|
||||
}
|
||||
|
||||
public readonly struct PackageScrapResult
|
||||
{
|
||||
public PackageScrapResult(bool success, PackageScrapFailureReason failureReason, int cacheGranted, int bandwidthRefunded)
|
||||
{
|
||||
Success = success;
|
||||
FailureReason = failureReason;
|
||||
CacheGranted = cacheGranted;
|
||||
BandwidthRefunded = bandwidthRefunded;
|
||||
}
|
||||
|
||||
public bool Success { get; }
|
||||
public PackageScrapFailureReason FailureReason { get; }
|
||||
public int CacheGranted { get; }
|
||||
public int BandwidthRefunded { get; }
|
||||
}
|
||||
|
||||
public static class PackageScrapper
|
||||
{
|
||||
public static PackageScrapResult Scrap(PlayerCollection collection, PackageLoadout loadout, SaveData wallet, string packageId)
|
||||
{
|
||||
if (collection == null || wallet == null || string.IsNullOrWhiteSpace(packageId))
|
||||
{
|
||||
return new PackageScrapResult(false, PackageScrapFailureReason.NotOwned, 0, 0);
|
||||
}
|
||||
|
||||
OwnedPackageInstance package = collection.GetOwnedPackage(packageId);
|
||||
if (package == null)
|
||||
{
|
||||
return new PackageScrapResult(false, PackageScrapFailureReason.NotOwned, 0, 0);
|
||||
}
|
||||
|
||||
if (loadout != null && loadout.IsEquipped(packageId))
|
||||
{
|
||||
return new PackageScrapResult(false, PackageScrapFailureReason.Equipped, 0, 0);
|
||||
}
|
||||
|
||||
PackageDefinition definition = package.Definition;
|
||||
int rarity = definition == null ? 1 : definition.Rarity;
|
||||
int cache = PackageTuning.GetCacheForRarity(rarity) + PackageTuning.GetRefundedInvestedCache(package.UpgradeLevel, rarity);
|
||||
int bandwidth = PackageTuning.GetRefundedInvestedBandwidth(package.UpgradeLevel, rarity);
|
||||
|
||||
if (!collection.RemovePackage(packageId))
|
||||
{
|
||||
return new PackageScrapResult(false, PackageScrapFailureReason.NotOwned, 0, 0);
|
||||
}
|
||||
|
||||
wallet.cacheBalance += Math.Max(0, cache);
|
||||
wallet.bandwidthBalance += Math.Max(0, bandwidth);
|
||||
return new PackageScrapResult(true, PackageScrapFailureReason.None, cache, bandwidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace KernelPanic.Meta
|
||||
{
|
||||
public static class PackageTuning
|
||||
{
|
||||
public const int MaxPackageLevel = 5;
|
||||
public const float RefundFraction = 1f;
|
||||
public const float RarityCostMultiplier = 1f;
|
||||
|
||||
private static readonly int[] CachePerRarityValues = { 5, 12, 30, 80, 200 };
|
||||
private static readonly int[] UpgradeCacheCostValues = { 10, 25, 50, 90, 150 };
|
||||
private static readonly int[] UpgradeBandwidthCostValues = { 20, 50, 100, 180, 300 };
|
||||
|
||||
public static int GetCacheForRarity(int rarity)
|
||||
{
|
||||
return CachePerRarityValues[Mathf.Clamp(rarity, 1, CachePerRarityValues.Length) - 1];
|
||||
}
|
||||
|
||||
public static int GetUpgradeCacheCost(int nextLevel, int rarity)
|
||||
{
|
||||
return ApplyRarityMultiplier(UpgradeCacheCostValues[Mathf.Clamp(nextLevel, 1, UpgradeCacheCostValues.Length) - 1], rarity);
|
||||
}
|
||||
|
||||
public static int GetUpgradeBandwidthCost(int nextLevel, int rarity)
|
||||
{
|
||||
return ApplyRarityMultiplier(UpgradeBandwidthCostValues[Mathf.Clamp(nextLevel, 1, UpgradeBandwidthCostValues.Length) - 1], rarity);
|
||||
}
|
||||
|
||||
public static int GetInvestedCache(int level, int rarity)
|
||||
{
|
||||
int total = 0;
|
||||
for (int nextLevel = 1; nextLevel <= Mathf.Clamp(level, 0, MaxPackageLevel); nextLevel++)
|
||||
{
|
||||
total += GetUpgradeCacheCost(nextLevel, rarity);
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
public static int GetInvestedBandwidth(int level, int rarity)
|
||||
{
|
||||
int total = 0;
|
||||
for (int nextLevel = 1; nextLevel <= Mathf.Clamp(level, 0, MaxPackageLevel); nextLevel++)
|
||||
{
|
||||
total += GetUpgradeBandwidthCost(nextLevel, rarity);
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
public static int GetRefundedInvestedCache(int level, int rarity)
|
||||
{
|
||||
return Mathf.RoundToInt(GetInvestedCache(level, rarity) * RefundFraction);
|
||||
}
|
||||
|
||||
public static int GetRefundedInvestedBandwidth(int level, int rarity)
|
||||
{
|
||||
return Mathf.RoundToInt(GetInvestedBandwidth(level, rarity) * RefundFraction);
|
||||
}
|
||||
|
||||
private static int ApplyRarityMultiplier(int baseCost, int rarity)
|
||||
{
|
||||
float multiplier = RarityCostMultiplier <= 0f ? 1f : RarityCostMultiplier;
|
||||
return Math.Max(0, Mathf.RoundToInt(baseCost * multiplier));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using KernelPanic.Data;
|
||||
|
||||
namespace KernelPanic.Meta
|
||||
{
|
||||
public enum PackageUpgradeFailureReason
|
||||
{
|
||||
None,
|
||||
NotOwned,
|
||||
MaxLevel,
|
||||
InsufficientCache,
|
||||
InsufficientBandwidth
|
||||
}
|
||||
|
||||
public readonly struct PackageUpgradeResult
|
||||
{
|
||||
public PackageUpgradeResult(bool success, PackageUpgradeFailureReason failureReason, int cacheCost, int bandwidthCost, int newLevel)
|
||||
{
|
||||
Success = success;
|
||||
FailureReason = failureReason;
|
||||
CacheCost = cacheCost;
|
||||
BandwidthCost = bandwidthCost;
|
||||
NewLevel = newLevel;
|
||||
}
|
||||
|
||||
public bool Success { get; }
|
||||
public PackageUpgradeFailureReason FailureReason { get; }
|
||||
public int CacheCost { get; }
|
||||
public int BandwidthCost { get; }
|
||||
public int NewLevel { get; }
|
||||
}
|
||||
|
||||
public static class PackageUpgrader
|
||||
{
|
||||
public static event Action<OwnedPackageInstance> Upgraded;
|
||||
|
||||
public static PackageUpgradeResult TryUpgrade(OwnedPackageInstance packageInstance, SaveData wallet)
|
||||
{
|
||||
if (packageInstance == null || wallet == null)
|
||||
{
|
||||
return new PackageUpgradeResult(false, PackageUpgradeFailureReason.NotOwned, 0, 0, 0);
|
||||
}
|
||||
|
||||
int currentLevel = Math.Max(0, packageInstance.UpgradeLevel);
|
||||
if (currentLevel >= PackageTuning.MaxPackageLevel)
|
||||
{
|
||||
return new PackageUpgradeResult(false, PackageUpgradeFailureReason.MaxLevel, 0, 0, currentLevel);
|
||||
}
|
||||
|
||||
int nextLevel = currentLevel + 1;
|
||||
PackageDefinition definition = packageInstance.Definition;
|
||||
int rarity = definition == null ? 1 : definition.Rarity;
|
||||
int cacheCost = PackageTuning.GetUpgradeCacheCost(nextLevel, rarity);
|
||||
int bandwidthCost = PackageTuning.GetUpgradeBandwidthCost(nextLevel, rarity);
|
||||
if (wallet.cacheBalance < cacheCost)
|
||||
{
|
||||
return new PackageUpgradeResult(false, PackageUpgradeFailureReason.InsufficientCache, cacheCost, bandwidthCost, currentLevel);
|
||||
}
|
||||
|
||||
if (wallet.bandwidthBalance < bandwidthCost)
|
||||
{
|
||||
return new PackageUpgradeResult(false, PackageUpgradeFailureReason.InsufficientBandwidth, cacheCost, bandwidthCost, currentLevel);
|
||||
}
|
||||
|
||||
wallet.cacheBalance -= cacheCost;
|
||||
wallet.bandwidthBalance -= bandwidthCost;
|
||||
packageInstance.SetUpgradeLevel(nextLevel);
|
||||
Upgraded?.Invoke(packageInstance);
|
||||
return new PackageUpgradeResult(true, PackageUpgradeFailureReason.None, cacheCost, bandwidthCost, nextLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,11 +10,14 @@ namespace KernelPanic.Meta
|
||||
public sealed class PlayerCollection
|
||||
{
|
||||
private readonly List<DistroDefinition> _ownedUnits = new();
|
||||
private readonly List<OwnedPackageInstance> _ownedPackages = new();
|
||||
private readonly Dictionary<string, int> _versions = new(StringComparer.OrdinalIgnoreCase);
|
||||
private int _featuredIndex;
|
||||
|
||||
// TODO: Populate owned units from SaveService during bootstrap.
|
||||
public IReadOnlyList<DistroDefinition> OwnedUnits => _ownedUnits;
|
||||
public IReadOnlyList<OwnedPackageInstance> OwnedPackageInstances => _ownedPackages;
|
||||
public IReadOnlyList<PackageDefinition> OwnedPackages => BuildOwnedPackageDefinitions();
|
||||
public DistroDefinition FeaturedUnit => _ownedUnits.Count == 0 ? null : _ownedUnits[Math.Clamp(_featuredIndex, 0, _ownedUnits.Count - 1)];
|
||||
|
||||
public event Action Changed;
|
||||
@@ -34,6 +37,35 @@ namespace KernelPanic.Meta
|
||||
Add(unit, version, false);
|
||||
}
|
||||
|
||||
public void AddPackage(PackageDefinition package)
|
||||
{
|
||||
AddPackage(package, 0, true);
|
||||
}
|
||||
|
||||
public void AddPackageSilently(PackageDefinition package)
|
||||
{
|
||||
AddPackage(package, 0, false);
|
||||
}
|
||||
|
||||
public void AddPackageSilently(PackageDefinition package, int upgradeLevel)
|
||||
{
|
||||
AddPackage(package, upgradeLevel, false);
|
||||
}
|
||||
|
||||
private void AddPackage(PackageDefinition package, int upgradeLevel, bool notify)
|
||||
{
|
||||
if (package == null || IsPackageOwned(package.Id))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_ownedPackages.Add(new OwnedPackageInstance(package, upgradeLevel));
|
||||
if (notify)
|
||||
{
|
||||
Changed?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
private void Add(DistroDefinition unit, int version, bool notify)
|
||||
{
|
||||
if (unit == null)
|
||||
@@ -82,6 +114,60 @@ namespace KernelPanic.Meta
|
||||
return count;
|
||||
}
|
||||
|
||||
public bool IsPackageOwned(string packageId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(packageId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < _ownedPackages.Count; i++)
|
||||
{
|
||||
OwnedPackageInstance package = _ownedPackages[i];
|
||||
if (package != null && string.Equals(package.PackageId, packageId, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public OwnedPackageInstance GetOwnedPackage(string packageId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(packageId))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int i = 0; i < _ownedPackages.Count; i++)
|
||||
{
|
||||
OwnedPackageInstance package = _ownedPackages[i];
|
||||
if (package != null && string.Equals(package.PackageId, packageId, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return package;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool RemovePackage(string packageId)
|
||||
{
|
||||
for (int i = _ownedPackages.Count - 1; i >= 0; i--)
|
||||
{
|
||||
OwnedPackageInstance package = _ownedPackages[i];
|
||||
if (package != null && string.Equals(package.PackageId, packageId, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_ownedPackages.RemoveAt(i);
|
||||
Changed?.Invoke();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public int GetVersion(string unitId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(unitId))
|
||||
@@ -131,5 +217,42 @@ namespace KernelPanic.Meta
|
||||
|
||||
_featuredIndex = (_featuredIndex + 1) % _ownedUnits.Count;
|
||||
}
|
||||
|
||||
private IReadOnlyList<PackageDefinition> BuildOwnedPackageDefinitions()
|
||||
{
|
||||
List<PackageDefinition> definitions = new();
|
||||
for (int i = 0; i < _ownedPackages.Count; i++)
|
||||
{
|
||||
if (_ownedPackages[i]?.Definition != null)
|
||||
{
|
||||
definitions.Add(_ownedPackages[i].Definition);
|
||||
}
|
||||
}
|
||||
|
||||
return definitions;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class OwnedPackageInstance
|
||||
{
|
||||
public OwnedPackageInstance(PackageDefinition definition, int upgradeLevel)
|
||||
{
|
||||
Definition = definition;
|
||||
UpgradeLevel = Math.Max(0, Math.Min(PackageTuning.MaxPackageLevel, upgradeLevel));
|
||||
}
|
||||
|
||||
public PackageDefinition Definition { get; }
|
||||
public string PackageId => Definition == null ? string.Empty : Definition.Id;
|
||||
public int UpgradeLevel { get; private set; }
|
||||
|
||||
public PackageInstance ToRuntimeInstance()
|
||||
{
|
||||
return new PackageInstance(Definition, UpgradeLevel);
|
||||
}
|
||||
|
||||
public void SetUpgradeLevel(int level)
|
||||
{
|
||||
UpgradeLevel = Math.Max(0, Math.Min(PackageTuning.MaxPackageLevel, level));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace KernelPanic.Meta
|
||||
owned.merges = Math.Max(0, owned.merges) + merges;
|
||||
if (GachaTuning.DupeConsolationBandwidth > 0)
|
||||
{
|
||||
context.SaveData.standardPullCurrency += GachaTuning.DupeConsolationBandwidth;
|
||||
context.SaveData.bandwidthBalance += GachaTuning.DupeConsolationBandwidth;
|
||||
}
|
||||
|
||||
context.Collection?.AddSilently(unit, version);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using KernelPanic.Data;
|
||||
using UnityEngine;
|
||||
|
||||
namespace KernelPanic.Meta
|
||||
@@ -60,16 +61,28 @@ namespace KernelPanic.Meta
|
||||
public bool starterChosen;
|
||||
public int entropyBalance;
|
||||
public int rootCredits = GachaService.TestRootCreditsBalance;
|
||||
public int commitsBalance;
|
||||
public int bandwidthBalance;
|
||||
// Legacy conflated balance. Older builds used this for both Commits and Bandwidth.
|
||||
// Migration preserves it as Bandwidth and starts Commits at 0 because the source is ambiguous.
|
||||
public int standardPullCurrency;
|
||||
// Legacy pull-token field kept only so older saves deserialize cleanly.
|
||||
public int limitedPullCurrency;
|
||||
public int cacheBalance;
|
||||
public int packageMerges;
|
||||
// Legacy global balance kept only so older saves deserialize cleanly.
|
||||
// New duplicate-pull merges live on OwnedUnitSaveEntry.merges.
|
||||
public int merges;
|
||||
public List<OwnedUnitSaveEntry> ownedUnits = new();
|
||||
public List<OwnedPackageSaveEntry> ownedPackages = new();
|
||||
public List<string> ownedPackageIds = new();
|
||||
public List<PackageLoadoutSaveEntry> packageLoadouts = new();
|
||||
public List<string> ownedUnitIds = new();
|
||||
public List<string> bannerPoolIds = new();
|
||||
public GachaBannerState beginnerBannerState = new(GachaService.BeginnerBannerId);
|
||||
public LastRunLoadoutSaveEntry lastRunLoadout = new();
|
||||
public string lastRunDistroId;
|
||||
public List<DistroBestWaveSaveEntry> distroBestWaves = new();
|
||||
|
||||
public static SaveData CreateDefault()
|
||||
{
|
||||
@@ -79,19 +92,56 @@ namespace KernelPanic.Meta
|
||||
public void EnsureLists()
|
||||
{
|
||||
ownedUnits ??= new List<OwnedUnitSaveEntry>();
|
||||
ownedPackages ??= new List<OwnedPackageSaveEntry>();
|
||||
ownedPackageIds ??= new List<string>();
|
||||
packageLoadouts ??= new List<PackageLoadoutSaveEntry>();
|
||||
ownedUnitIds ??= new List<string>();
|
||||
bannerPoolIds ??= new List<string>();
|
||||
distroBestWaves ??= new List<DistroBestWaveSaveEntry>();
|
||||
beginnerBannerState ??= new GachaBannerState(GachaService.BeginnerBannerId);
|
||||
beginnerBannerState.bannerId = GachaService.BeginnerBannerId;
|
||||
beginnerBannerState.EnsureLists();
|
||||
lastRunLoadout ??= new LastRunLoadoutSaveEntry();
|
||||
lastRunLoadout.EnsureLists();
|
||||
if (string.IsNullOrWhiteSpace(lastRunDistroId) && !string.IsNullOrWhiteSpace(lastRunLoadout.distroId))
|
||||
{
|
||||
lastRunDistroId = lastRunLoadout.distroId;
|
||||
}
|
||||
|
||||
MigrateLegacyConflatedCurrency();
|
||||
entropyBalance = Math.Max(0, entropyBalance);
|
||||
rootCredits = Math.Max(0, rootCredits);
|
||||
commitsBalance = Math.Max(0, commitsBalance);
|
||||
bandwidthBalance = Math.Max(0, bandwidthBalance);
|
||||
merges = Math.Max(0, merges);
|
||||
packageMerges = Math.Max(0, packageMerges);
|
||||
cacheBalance = Math.Max(0, cacheBalance);
|
||||
MigrateLegacyOwnedUnitIds();
|
||||
MigrateLegacyOwnedPackageIds();
|
||||
NormalizeOwnedUnits();
|
||||
NormalizeOwnedPackages();
|
||||
NormalizePackageLoadouts();
|
||||
NormalizeDistroBestWaves();
|
||||
MigrateLegacyGlobalMerges();
|
||||
}
|
||||
|
||||
private void MigrateLegacyConflatedCurrency()
|
||||
{
|
||||
if (standardPullCurrency <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (bandwidthBalance <= 0)
|
||||
{
|
||||
bandwidthBalance = Math.Max(0, standardPullCurrency);
|
||||
Debug.Log("Migrated legacy standardPullCurrency to Bandwidth. Commits defaulted to 0 because the old field conflated pull tokens and upgrade currency.");
|
||||
}
|
||||
|
||||
standardPullCurrency = 0;
|
||||
limitedPullCurrency = 0;
|
||||
}
|
||||
|
||||
public OwnedUnitSaveEntry FindOwnedUnit(string id)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(id))
|
||||
@@ -176,6 +226,133 @@ namespace KernelPanic.Meta
|
||||
}
|
||||
}
|
||||
|
||||
private void NormalizeOwnedPackages()
|
||||
{
|
||||
HashSet<string> seen = new(StringComparer.OrdinalIgnoreCase);
|
||||
for (int i = ownedPackages.Count - 1; i >= 0; i--)
|
||||
{
|
||||
OwnedPackageSaveEntry entry = ownedPackages[i];
|
||||
if (entry == null || string.IsNullOrWhiteSpace(entry.id) || !seen.Add(entry.id))
|
||||
{
|
||||
ownedPackages.RemoveAt(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
entry.upgradeLevel = Math.Max(0, Math.Min(PackageTuning.MaxPackageLevel, entry.upgradeLevel));
|
||||
}
|
||||
|
||||
ownedPackageIds.Clear();
|
||||
for (int i = 0; i < ownedPackages.Count; i++)
|
||||
{
|
||||
ownedPackageIds.Add(ownedPackages[i].id);
|
||||
}
|
||||
}
|
||||
|
||||
public int GetBestWave(string distroId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(distroId))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
EnsureLists();
|
||||
for (int i = 0; i < distroBestWaves.Count; i++)
|
||||
{
|
||||
DistroBestWaveSaveEntry entry = distroBestWaves[i];
|
||||
if (entry != null && string.Equals(entry.distroId, distroId, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return Math.Max(0, entry.bestWave);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void RecordRunStats(string distroId, int waveReached)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(distroId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureLists();
|
||||
lastRunDistroId = distroId;
|
||||
lastRunLoadout ??= new LastRunLoadoutSaveEntry();
|
||||
lastRunLoadout.distroId = distroId;
|
||||
int safeWave = Math.Max(0, waveReached);
|
||||
for (int i = 0; i < distroBestWaves.Count; i++)
|
||||
{
|
||||
DistroBestWaveSaveEntry entry = distroBestWaves[i];
|
||||
if (entry != null && string.Equals(entry.distroId, distroId, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
entry.bestWave = Math.Max(entry.bestWave, safeWave);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
distroBestWaves.Add(new DistroBestWaveSaveEntry { distroId = distroId, bestWave = safeWave });
|
||||
}
|
||||
|
||||
private void NormalizeDistroBestWaves()
|
||||
{
|
||||
HashSet<string> seen = new(StringComparer.OrdinalIgnoreCase);
|
||||
for (int i = distroBestWaves.Count - 1; i >= 0; i--)
|
||||
{
|
||||
DistroBestWaveSaveEntry entry = distroBestWaves[i];
|
||||
if (entry == null || string.IsNullOrWhiteSpace(entry.distroId) || !seen.Add(entry.distroId))
|
||||
{
|
||||
distroBestWaves.RemoveAt(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
entry.bestWave = Math.Max(0, entry.bestWave);
|
||||
}
|
||||
}
|
||||
|
||||
private void MigrateLegacyOwnedPackageIds()
|
||||
{
|
||||
for (int i = 0; i < ownedPackageIds.Count; i++)
|
||||
{
|
||||
string id = ownedPackageIds[i];
|
||||
if (string.IsNullOrWhiteSpace(id) || HasOwnedPackageEntry(id))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ownedPackages.Add(new OwnedPackageSaveEntry { id = id, upgradeLevel = 0 });
|
||||
}
|
||||
}
|
||||
|
||||
private bool HasOwnedPackageEntry(string id)
|
||||
{
|
||||
for (int i = 0; i < ownedPackages.Count; i++)
|
||||
{
|
||||
OwnedPackageSaveEntry entry = ownedPackages[i];
|
||||
if (entry != null && string.Equals(entry.id, id, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void NormalizePackageLoadouts()
|
||||
{
|
||||
HashSet<string> seenDistros = new(StringComparer.OrdinalIgnoreCase);
|
||||
for (int i = packageLoadouts.Count - 1; i >= 0; i--)
|
||||
{
|
||||
PackageLoadoutSaveEntry entry = packageLoadouts[i];
|
||||
if (entry == null || string.IsNullOrWhiteSpace(entry.distroId) || !seenDistros.Add(entry.distroId))
|
||||
{
|
||||
packageLoadouts.RemoveAt(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
entry.EnsureLists();
|
||||
}
|
||||
}
|
||||
|
||||
private void MigrateLegacyGlobalMerges()
|
||||
{
|
||||
if (merges <= 0 || ownedUnits.Count == 0)
|
||||
@@ -223,6 +400,13 @@ namespace KernelPanic.Meta
|
||||
public int merges;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public sealed class OwnedPackageSaveEntry
|
||||
{
|
||||
public string id;
|
||||
public int upgradeLevel;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public sealed class LastRunLoadoutSaveEntry
|
||||
{
|
||||
@@ -234,4 +418,39 @@ namespace KernelPanic.Meta
|
||||
cardIds ??= new List<string>();
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public sealed class DistroBestWaveSaveEntry
|
||||
{
|
||||
public string distroId;
|
||||
public int bestWave;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public sealed class PackageLoadoutSaveEntry
|
||||
{
|
||||
public string distroId;
|
||||
public List<PackageLoadoutSlotSaveEntry> slots = new();
|
||||
|
||||
public void EnsureLists()
|
||||
{
|
||||
slots ??= new List<PackageLoadoutSlotSaveEntry>();
|
||||
HashSet<PackageSlot> seen = new();
|
||||
for (int i = slots.Count - 1; i >= 0; i--)
|
||||
{
|
||||
PackageLoadoutSlotSaveEntry slot = slots[i];
|
||||
if (slot == null || string.IsNullOrWhiteSpace(slot.packageId) || !seen.Add(slot.slot))
|
||||
{
|
||||
slots.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public sealed class PackageLoadoutSlotSaveEntry
|
||||
{
|
||||
public PackageSlot slot;
|
||||
public string packageId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using KernelPanic.Core;
|
||||
using KernelPanic.Data;
|
||||
|
||||
@@ -10,21 +11,32 @@ namespace KernelPanic.Run
|
||||
public sealed class RunConfig
|
||||
{
|
||||
public RunConfig(DistroDefinition distro, Language primaryLanguage, Language secondaryLanguage, IReadOnlyList<CardDefinition> startingDeck)
|
||||
: this(distro, primaryLanguage, secondaryLanguage, startingDeck, 0, 1)
|
||||
: this(distro, primaryLanguage, secondaryLanguage, startingDeck, Array.Empty<PackageDefinition>(), 0, 1)
|
||||
{
|
||||
}
|
||||
|
||||
public RunConfig(DistroDefinition distro, Language primaryLanguage, Language secondaryLanguage, IReadOnlyList<CardDefinition> startingDeck, int runSeed)
|
||||
: this(distro, primaryLanguage, secondaryLanguage, startingDeck, runSeed, 1)
|
||||
: this(distro, primaryLanguage, secondaryLanguage, startingDeck, Array.Empty<PackageDefinition>(), runSeed, 1)
|
||||
{
|
||||
}
|
||||
|
||||
public RunConfig(DistroDefinition distro, Language primaryLanguage, Language secondaryLanguage, IReadOnlyList<CardDefinition> startingDeck, int runSeed, int distroVersion)
|
||||
: this(distro, primaryLanguage, secondaryLanguage, startingDeck, Array.Empty<PackageDefinition>(), runSeed, distroVersion)
|
||||
{
|
||||
}
|
||||
|
||||
public RunConfig(DistroDefinition distro, Language primaryLanguage, Language secondaryLanguage, IReadOnlyList<CardDefinition> startingDeck, IReadOnlyList<PackageDefinition> equippedPackages, int runSeed, int distroVersion)
|
||||
: this(distro, primaryLanguage, secondaryLanguage, startingDeck, ToInstances(equippedPackages), runSeed, distroVersion)
|
||||
{
|
||||
}
|
||||
|
||||
public RunConfig(DistroDefinition distro, Language primaryLanguage, Language secondaryLanguage, IReadOnlyList<CardDefinition> startingDeck, IReadOnlyList<PackageInstance> equippedPackages, int runSeed, int distroVersion)
|
||||
{
|
||||
Distro = distro;
|
||||
PrimaryLanguage = primaryLanguage;
|
||||
SecondaryLanguage = secondaryLanguage;
|
||||
StartingDeck = startingDeck;
|
||||
EquippedPackages = equippedPackages ?? Array.Empty<PackageInstance>();
|
||||
RunSeed = runSeed;
|
||||
DistroVersion = UnityEngine.Mathf.Clamp(distroVersion, 1, KernelPanic.Meta.GachaTuning.MaxVersion);
|
||||
}
|
||||
@@ -33,7 +45,27 @@ namespace KernelPanic.Run
|
||||
public Language PrimaryLanguage { get; }
|
||||
public Language SecondaryLanguage { get; }
|
||||
public IReadOnlyList<CardDefinition> StartingDeck { get; }
|
||||
public IReadOnlyList<PackageInstance> EquippedPackages { get; }
|
||||
public int RunSeed { get; }
|
||||
public int DistroVersion { get; }
|
||||
|
||||
private static IReadOnlyList<PackageInstance> ToInstances(IReadOnlyList<PackageDefinition> packages)
|
||||
{
|
||||
if (packages == null)
|
||||
{
|
||||
return Array.Empty<PackageInstance>();
|
||||
}
|
||||
|
||||
List<PackageInstance> instances = new();
|
||||
for (int i = 0; i < packages.Count; i++)
|
||||
{
|
||||
if (packages[i] != null)
|
||||
{
|
||||
instances.Add(new PackageInstance(packages[i], 0));
|
||||
}
|
||||
}
|
||||
|
||||
return instances;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user