From 769d74b046752c22cacd94fe8fefcc5e23daf494 Mon Sep 17 00:00:00 2001 From: Tomasz Boruc Date: Sat, 10 Oct 2026 22:54:18 +0200 Subject: [PATCH] Zmiany --- documentation.txt | 10 ++++++++++ resources/items/beam_laser.tres | 2 +- scripts/game/weapon_controller.gd | 8 ++++---- scripts/items/item_definition.gd | 2 ++ scripts/items/item_instance.gd | 15 ++++++++++++++- tests/items/weapon_damage_test.gd | 15 +++++++++++++++ 6 files changed, 46 insertions(+), 6 deletions(-) diff --git a/documentation.txt b/documentation.txt index 1fd42b7..4dd775a 100644 --- a/documentation.txt +++ b/documentation.txt @@ -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. diff --git a/resources/items/beam_laser.tres b/resources/items/beam_laser.tres index abc2e71..08be4ff 100644 --- a/resources/items/beam_laser.tres +++ b/resources/items/beam_laser.tres @@ -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" diff --git a/scripts/game/weapon_controller.gd b/scripts/game/weapon_controller.gd index 6cada2a..12e2bdf 100644 --- a/scripts/game/weapon_controller.gd +++ b/scripts/game/weapon_controller.gd @@ -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) diff --git a/scripts/items/item_definition.gd b/scripts/items/item_definition.gd index 9991a5f..008534a 100644 --- a/scripts/items/item_definition.gd +++ b/scripts/items/item_definition.gd @@ -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)") diff --git a/scripts/items/item_instance.gd b/scripts/items/item_instance.gd index 8dd6a9c..c8469cf 100644 --- a/scripts/items/item_instance.gd +++ b/scripts/items/item_instance.gd @@ -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)") diff --git a/tests/items/weapon_damage_test.gd b/tests/items/weapon_damage_test.gd index 5185b69..af71215 100644 --- a/tests/items/weapon_damage_test.gd +++ b/tests/items/weapon_damage_test.gd @@ -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)