89 lines
4.6 KiB
GDScript
89 lines
4.6 KiB
GDScript
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 [Color("b9c5d4"), Color("63df91"), Color("65b4ff"), Color("bd83ff"), Color("ffca63")][clampi(rarity, 0, 4)]
|
||
|
||
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()
|
||
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"}.get(key, key))
|