edc40f9008
- Touch controls: direct InputEventScreenTouch in shop_ui (bypass relay) - ItemDB: static preload list instead of DirAccess scan (export fix) - All 18 items with EN localisation (name_en, desc_en, category_en) - Ship playstyles: NOVA-1 shield, INFERNO ram, AURORA agile/tank - Quasar: SMBH visual, jet boost, merge, push, BH-eating - Atlas & UI text updated EN+DE Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
177 lines
5.6 KiB
GDScript
177 lines
5.6 KiB
GDScript
extends RefCounted
|
|
class_name ItemDB
|
|
|
|
# ─── Legacy-System (alter Shop / Enemy-Upgrades in game_world.gd) ──────────────
|
|
# Bleibt unverändert für Backward-Compat. Wird nur von game_world.gd für
|
|
# Enemy-Stat-Boosts ab Welle 10 verwendet.
|
|
|
|
enum Rarity { COMMON, UNCOMMON, RARE, EPIC }
|
|
|
|
const RARITY_WEIGHTS: Array = [60, 25, 12, 3]
|
|
|
|
const RARITY_COLORS: Dictionary = {
|
|
0: Color("#aaaaaa"), # COMMON
|
|
1: Color("#44ff88"), # UNCOMMON
|
|
2: Color("#4488ff"), # RARE
|
|
3: Color("#cc44ff") # EPIC
|
|
}
|
|
|
|
const RARITY_NAMES: Dictionary = {
|
|
0: "STANDARD",
|
|
1: "SELTEN",
|
|
2: "EPISCH",
|
|
3: "LEGENDÄR"
|
|
}
|
|
|
|
const ITEMS: Array = [
|
|
{
|
|
"id": "thrust_1", "name": "Schubverstärker", "rarity": 0, "cost": 50,
|
|
"desc": "+12% Geschwindigkeit",
|
|
"effects": { "speed_mult": 1.12 }
|
|
},
|
|
{
|
|
"id": "firerate_1", "name": "Schnellfeuer I", "rarity": 0, "cost": 50,
|
|
"desc": "+15% Feuerrate",
|
|
"effects": { "fire_rate_mult": 1.15 }
|
|
},
|
|
{
|
|
"id": "damage_1", "name": "Schwere Ladung I", "rarity": 0, "cost": 50,
|
|
"desc": "+15% Trefferzone",
|
|
"effects": { "damage_mult": 1.15 }
|
|
},
|
|
{
|
|
"id": "shield_1", "name": "Panzerplatte", "rarity": 0, "cost": 55,
|
|
"desc": "+1 Schutzladung",
|
|
"effects": { "shield_charges": 1 }
|
|
},
|
|
{
|
|
"id": "firerate_2", "name": "Schnellfeuer II", "rarity": 1, "cost": 90,
|
|
"desc": "+22% Feuerrate",
|
|
"effects": { "fire_rate_mult": 1.22 }
|
|
},
|
|
{
|
|
"id": "damage_2", "name": "Schwere Ladung II", "rarity": 1, "cost": 100,
|
|
"desc": "+22% Trefferzone +10% Projektilgeschwindigkeit",
|
|
"effects": { "damage_mult": 1.22, "bullet_speed_mult": 1.10 }
|
|
},
|
|
]
|
|
|
|
# Weighted random roll — Legacy-Shop (wird nicht mehr für Werkstatt verwendet)
|
|
static func roll_shop(count: int, _exclude_ids: Array = []) -> Array:
|
|
var pool: Array = []
|
|
for item: Dictionary in ITEMS:
|
|
var w: int = RARITY_WEIGHTS[int(item["rarity"])]
|
|
for _i in w:
|
|
pool.append(item)
|
|
pool.shuffle()
|
|
var result: Array = []
|
|
var seen_ids: Dictionary = {}
|
|
for item: Dictionary in pool:
|
|
var iid: String = item["id"]
|
|
if iid in seen_ids: continue
|
|
seen_ids[iid] = true
|
|
result.append(item)
|
|
if result.size() >= count:
|
|
break
|
|
return result
|
|
|
|
# ─── Werkstatt-System (Plugin-basiert) ─────────────────────────────────────────
|
|
# Auto-Discovery: alle *.gd unter res://items/ die ItemDef erweitern werden
|
|
# beim ersten Zugriff registriert.
|
|
|
|
static var _registry: Array = []
|
|
static var _registry_loaded: bool = false
|
|
|
|
# Static preload list — DirAccess doesn't work in exported builds (compiled scripts
|
|
# aren't raw files in the PCK). preload() is resolved at compile time and always works.
|
|
const _ITEM_SCRIPTS: Array = [
|
|
preload("res://items/weapons/wk_burst.gd"),
|
|
preload("res://items/weapons/wk_charge.gd"),
|
|
preload("res://items/weapons/wk_ion.gd"),
|
|
preload("res://items/weapons/wk_laser.gd"),
|
|
preload("res://items/weapons/wk_plasma.gd"),
|
|
preload("res://items/weapons/wk_rail.gd"),
|
|
preload("res://items/weapons/wk_scatter.gd"),
|
|
preload("res://items/weapons/wk_shotgun.gd"),
|
|
preload("res://items/weapons/wk_sniper.gd"),
|
|
preload("res://items/hull/hull_giant.gd"),
|
|
preload("res://items/hull/hull_nullfeld.gd"),
|
|
preload("res://items/hull/hull_plating.gd"),
|
|
preload("res://items/hull/hull_reaktor.gd"),
|
|
preload("res://items/drives/drive_overdrive.gd"),
|
|
preload("res://items/drives/drive_quantum.gd"),
|
|
preload("res://items/drives/drive_steer.gd"),
|
|
preload("res://items/special/special_credit_mag.gd"),
|
|
preload("res://items/special/special_wipe_core.gd"),
|
|
]
|
|
|
|
static func _ensure_loaded() -> void:
|
|
if _registry_loaded: return
|
|
_registry_loaded = true
|
|
for script: Script in _ITEM_SCRIPTS:
|
|
if script == null or not script.can_instantiate(): continue
|
|
var inst = script.new()
|
|
if inst is ItemDef and (inst as ItemDef).id != "":
|
|
_registry.append(inst)
|
|
|
|
static func get_all_defs() -> Array:
|
|
_ensure_loaded()
|
|
return _registry
|
|
|
|
static func get_def_by_id(id: String) -> ItemDef:
|
|
_ensure_loaded()
|
|
for item in _registry:
|
|
if (item as ItemDef).id == id:
|
|
return item
|
|
return null
|
|
|
|
# Rolls `count` random items from the Werkstatt pool, excluding given IDs.
|
|
static func roll_werkstatt(count: int, exclude_ids: Array = []) -> Array:
|
|
_ensure_loaded()
|
|
var pool: Array = []
|
|
for item in _registry:
|
|
var def := item as ItemDef
|
|
if exclude_ids.has(def.id):
|
|
continue
|
|
pool.append(def)
|
|
pool.shuffle()
|
|
var n: int = min(count, pool.size())
|
|
return pool.slice(0, n)
|
|
|
|
# ─── Effect-Klassifizierung (für UI-Farbkodierung) ────────────────────────────
|
|
|
|
static func is_positive_effect(key: String, val) -> bool:
|
|
match key:
|
|
"speed_mult", "turn_mult", "fire_rate_mult", "damage_mult", \
|
|
"bullet_speed_mult", "invuln_mult", "credit_bonus":
|
|
return float(val) >= 1.0
|
|
"bullet_count", "shield_charges":
|
|
return int(val) > 0
|
|
"bh_resist":
|
|
return float(val) > 0.0
|
|
"wipe_mult":
|
|
return float(val) <= 1.0 # kleiner = schneller = besser
|
|
return true
|
|
|
|
# Menschlich lesbarer Stat-Name für die Vorschau.
|
|
static func stat_display_name(key: String) -> String:
|
|
match key:
|
|
"speed_mult": return "Speed"
|
|
"turn_mult": return "Wendung"
|
|
"fire_rate_mult": return "Feuerrate"
|
|
"damage_mult": return "Schaden"
|
|
"bullet_speed_mult": return "Proj.-Speed"
|
|
"bullet_count": return "Projektile"
|
|
"shield_charges": return "Schilde"
|
|
"invuln_mult": return "Unverwundbar"
|
|
"bh_resist": return "BH-Resistenz"
|
|
"wipe_mult": return "Wipe-Ladezeit"
|
|
"credit_bonus": return "Kreditgewinn"
|
|
return key
|
|
|
|
static func get_by_id(id: String) -> Dictionary:
|
|
for item: Dictionary in ITEMS:
|
|
if item["id"] == id:
|
|
return item
|
|
return {}
|