Randoloot/scripts/items/item_instance.gd
2026-10-10 22:38:40 +02:00

111 lines
5.3 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

extends Resource
class_name ItemInstance
@export var definition: ItemDefinition
@export_range(1, 1000, 1) var item_level: int = 1
@export var additional_modifiers: Array[ItemStatModifier] = []
@export var primary_value_override: float = -1.0
@export var energy_regeneration_override: float = -1.0
@export_range(0, 4) var rarity: int = 0
@export var damage_min: float = -1.0
@export var damage_max: float = -1.0
func get_stat_total(stat_key: String) -> float:
if stat_key == "damage" and definition and definition.category == ItemDefinition.Category.WEAPON:
var damage_range := get_damage_range()
return (damage_range.x + damage_range.y) * 0.5
var total := 0.0
if definition and definition.primary_stat == stat_key:
total += primary_value_override if primary_value_override >= 0.0 else definition.primary_value
if definition and stat_key == "energy_regeneration":
total += energy_regeneration_override if energy_regeneration_override >= 0.0 else definition.energy_regeneration_bonus
for modifier in additional_modifiers:
if modifier and modifier.stat_key == stat_key:
total += modifier.value
return total
func get_damage_range() -> Vector2:
if definition == null or definition.category != ItemDefinition.Category.WEAPON:
return Vector2.ZERO
var lower := damage_min
var upper := damage_max
if lower < 0.0 or upper < 0.0:
if primary_value_override >= 0.0:
# Older item instances retain their previously rolled damage.
lower = primary_value_override
upper = primary_value_override
else:
# Starter weapons use the middle of the definition's roll settings.
lower = roundf((definition.damage_lower_roll_min + definition.damage_lower_roll_max) * 0.5)
upper = lower + roundf((definition.damage_spread_roll_min + definition.damage_spread_roll_max) * 0.5)
var flat_bonus := 0.0
for modifier in additional_modifiers:
if modifier and modifier.stat_key == "damage":
flat_bonus += modifier.value
return Vector2(maxf(0.0, minf(lower, upper) + flat_bonus), maxf(0.0, maxf(lower, upper) + flat_bonus))
func roll_damage() -> float:
var damage_range := get_damage_range()
# Inclusive integer rolls, preserving fractional flat bonuses on both bounds.
var whole_span := floori(damage_range.y - damage_range.x)
return damage_range.x + randi_range(0, whole_span)
func get_damage_range_text() -> String:
var damage_range := get_damage_range()
return "%s–%s DMG" % [_format_damage(damage_range.x), _format_damage(damage_range.y)]
static func _format_damage(value: float) -> String:
return str(roundi(value)) if is_equal_approx(value, roundf(value)) else "%.1f" % value
func get_rarity_name() -> String:
return ["Zwykły", "Niepospolity", "Rzadki", "Epicki", "Legendarny"][clampi(rarity, 0, 4)]
func get_rarity_color() -> Color:
return get_background_color().lightened(0.4)
func get_addon_count() -> int:
var count := 0
for modifier in additional_modifiers:
if modifier != null:
count += 1
return count
func get_background_color() -> Color:
return [Color("101925"), Color("414b58"), Color("65432d"), Color("244c79"), Color("796025")][mini(get_addon_count(), 4)]
func get_type_color() -> Color:
if definition == null:
return Color("354455")
match definition.category:
ItemDefinition.Category.WEAPON:
return Color("ae74ef")
ItemDefinition.Category.ACTIVE_EXTENSION:
return Color("f39c4d")
return Color("65ce8b")
func get_tooltip_text() -> String:
if definition == null:
return ""
var primary_text := "%s: +%.1f%s" % [stat_name(definition.primary_stat), get_stat_total(definition.primary_stat), definition.stat_suffix]
if definition.category == ItemDefinition.Category.WEAPON:
primary_text = "Obrażenia: %s" % get_damage_range_text()
elif definition.active_ability != null:
primary_text = definition.active_ability.description
var lines: Array[String] = [definition.display_name, "%s • Poziom %d" % [get_rarity_name(), item_level], "", definition.description, "", "CECHA GŁÓWNA", primary_text]
if definition.energy_regeneration_bonus > 0.0:
lines.append("Regeneracja generatora: +%.1f /s" % (energy_regeneration_override if energy_regeneration_override >= 0.0 else definition.energy_regeneration_bonus))
if definition.category == ItemDefinition.Category.WEAPON:
lines.append("Każdy strzał / impuls losuje obrażenia z tego zakresu.")
lines.append("Zasięg: %.0f px • Energia: %.1f / strzał" % [definition.weapon_range, definition.energy_cost])
lines.append("Odstęp strzałów: %.2f s" % maxf(definition.fire_interval, definition.weapon_cooldown))
if not additional_modifiers.is_empty():
lines.append("\nADDONY (aktywne po zamontowaniu)")
for modifier in additional_modifiers:
if modifier == null:
continue
lines.append(modifier.get_display_text())
return "\n".join(lines)
static func stat_name(key: String) -> String:
return str({"damage": "Obrażenia", "max_hull": "Kadłub", "max_shields": "Tarcze", "max_energy": "Energia", "max_speed": "Prędkość", "energy_regeneration": "Regeneracja energii", "shield_regeneration": "Regeneracja tarcz", "hull_percent": "Kadłub", "shield_percent": "Tarcze", "damage_percent": "Obrażenia broni", "speed_percent": "Prędkość statku", "experience_percent": "Doświadczenie (EXP)", "credits_percent": "Kredyty", "critical_chance_percent": "Szansa na trafienie krytyczne", "critical_damage_percent": "Obrażenia krytyczne"}.get(key, key))