This commit is contained in:
Tomasz Boruc 2026-10-10 22:54:18 +02:00
parent bf74111d72
commit 769d74b046
6 changed files with 46 additions and 6 deletions

View File

@ -239,3 +239,13 @@ Bazowa regeneracja energii wszystkich modeli: 5 pkt/s.
Statystyki modelu ustawiane są przed przeliczeniem wyposażenia, także przy restarcie.
Brak lub nieaktualny wybór modelu powoduje użycie Aegis. Dopalacz i inne umiejętności
korzystają z faktycznych maksimów, więc Phantom wydaje całą swoją energię 125 pkt.
KOSZT ENERGII WYLOSOWANEJ BRONI
ItemInstance.get_energy_cost() jest wspólne dla tooltipów i strzelania każdą bronią.
Koszt = bazowy energy_cost * (średnie obrażenia / średnie obrażenia startowe)^0.5
* (1 + liczba addonów * 0.05), zaokrąglony do 0.1 pkt.
Wyższy poziom zwiększa zakres obrażeń, a przez niego koszt. Czterokrotnie wyższe
średnie obrażenia dają dwukrotny koszt przed addonami. Każdy addon dodaje 5% kosztu.
Bonusy kapitana i innych zamontowanych przedmiotów nie zmieniają kosztu tego egzemplarza.
Parametry energy_damage_exponent i energy_per_addon edytuje się w definicji broni.

View File

@ -7,7 +7,7 @@ script = ExtResource("1_definition")
item_id = "beam_laser"
display_name = "Laser wiązkowy"
category = 0
description = "Laser pulsacyjny o bardzo dużym zasięgu. Każdy impuls zużywa 12 energii."
description = "Laser pulsacyjny o bardzo dużym zasięgu. Koszt impulsu zależy od obrażeń i addonów egzemplarza."
primary_stat = "damage"
primary_value = 8.0
stat_suffix = " DMG"

View File

@ -86,12 +86,12 @@ func _physics_process(delta: float) -> void:
if (
is_just_pressed
and _shot_timers[slot_index] <= 0.0
and _consume_energy(definition.energy_cost)
and _consume_energy(item.get_energy_cost())
):
_fire_projectile(item)
_shot_timers[slot_index] = definition.weapon_cooldown
_:
if _shot_timers[slot_index] <= 0.0 and _consume_energy(definition.energy_cost):
if _shot_timers[slot_index] <= 0.0 and _consume_energy(item.get_energy_cost()):
_fire_projectile(item)
_shot_timers[slot_index] = definition.fire_interval
for slot_index in 2:
@ -120,7 +120,7 @@ func _fire_projectile(item: ItemInstance) -> void:
func _fire_laser(slot_index: int, item: ItemInstance) -> void:
var definition := item.definition
var line := _laser_lines[slot_index]
if _shot_timers[slot_index] > 0.0 or float(ship.get("energy")) < definition.energy_cost:
if _shot_timers[slot_index] > 0.0 or float(ship.get("energy")) < item.get_energy_cost():
return
var muzzle_position := _muzzle_position()
var direction := _aim_direction_from(muzzle_position)
@ -138,7 +138,7 @@ func _fire_laser(slot_index: int, item: ItemInstance) -> void:
line.add_point(muzzle_position)
line.add_point(endpoint)
line.visible = true
if not _consume_energy(definition.energy_cost):
if not _consume_energy(item.get_energy_cost()):
line.visible = false
return
WEAPON_AUDIO_SCRIPT.play(ship.get_parent(), muzzle_position, ItemDefinition.WeaponKind.LASER)

View File

@ -19,6 +19,8 @@ enum WeaponKind { PLASMA, MACHINE_GUN, LASER, MISSILE }
@export var projectile_speed: float = 0.0
@export var weapon_range: float = 0.0
@export var energy_cost: float = 0.0
@export_range(0.0, 1.0, 0.05) var energy_damage_exponent: float = 0.5
@export_range(0.0, 1.0, 0.01) var energy_per_addon: float = 0.05
@export var active_ability: ActiveAbility
@export_group("Losowanie zakresu obrażeń broni (poziom 1)")

View File

@ -50,6 +50,19 @@ func roll_damage() -> float:
var whole_span := floori(damage_range.y - damage_range.x)
return damage_range.x + randi_range(0, whole_span)
func get_energy_cost() -> float:
if definition == null or definition.category != ItemDefinition.Category.WEAPON:
return 0.0
# Compare this weapon with its starter damage. Captain/global gear buffs are free.
var base_lower := roundf((definition.damage_lower_roll_min + definition.damage_lower_roll_max) * 0.5)
var base_spread := roundf((definition.damage_spread_roll_min + definition.damage_spread_roll_max) * 0.5)
var base_average := maxf(1.0, base_lower + base_spread * 0.5)
var damage_range := get_damage_range()
var average := maxf(0.1, (damage_range.x + damage_range.y) * 0.5)
var damage_factor := pow(average / base_average, definition.energy_damage_exponent)
var addon_factor := 1.0 + get_addon_count() * definition.energy_per_addon
return snappedf(maxf(0.0, definition.energy_cost * damage_factor * addon_factor), 0.1)
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)]
@ -96,7 +109,7 @@ func get_tooltip_text() -> String:
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("Zasięg: %.0f px • Energia: %.1f / strzał" % [definition.weapon_range, get_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)")

View File

@ -18,6 +18,21 @@ func _ready() -> void:
for definition in GENERATOR.DEFINITIONS:
if definition.category != ItemDefinition.Category.WEAPON:
continue
var starter := ItemInstance.new()
starter.definition = definition
assert(is_equal_approx(starter.get_energy_cost(), definition.energy_cost))
var stronger := ItemInstance.new()
stronger.definition = definition
var initial_range := starter.get_damage_range()
stronger.damage_min = initial_range.x * 4.0
stronger.damage_max = initial_range.y * 4.0
assert(is_equal_approx(stronger.get_energy_cost(), definition.energy_cost * 2.0))
var cost_before_addon := stronger.get_energy_cost()
var addon := ItemStatModifier.new()
addon.stat_key = "damage_percent"
addon.value = 10.0
stronger.additional_modifiers.append(addon)
assert(stronger.get_energy_cost() > cost_before_addon)
for level in [1, 50, 1000]:
for sample in 100:
var item := GENERATOR.generate_for_definition(definition, level)