Update systemu strzału
This commit is contained in:
parent
598835c885
commit
3a5f46998a
@ -219,16 +219,16 @@ X. RODZAJE BRONI I ICH PARAMETRY BAZOWE (POZIOM 1)
|
||||
* Prędkość Pocisku: Natychmiastowa (Hitscan)
|
||||
|
||||
3. Wyrzutnia Rakiet (Homing Missile Launcher)
|
||||
- Wystrzeliwuje wolno lecące rakiety, które automatycznie namierzają najbliższego wroga.
|
||||
- Wystrzeliwuje wolno lecące rakiety w kierunku wskazanym kursorem.
|
||||
- Po trafieniu wywołują eksplozję obszarową (AOE), raniąc grupy wrogów.
|
||||
- Parametry (Poziom 1):
|
||||
* Obrażenia (DMG): 45 - 70 (Obrażenia obszarowe w promieniu 120 px)
|
||||
* Szybkostrzelność: Bardzo Niska (0.8 strzału / sec)
|
||||
* Cooldown: 5 sekund między rakietami
|
||||
* Zasięg: Bardzo Duży (1000 px)
|
||||
* Koszt Energii: Wysoki (25 energy / strzał)
|
||||
* Prędkość Pocisku: Wolna (z systemem śledzenia celu)
|
||||
|
||||
4. Działko Obrotowe (Gatling Gun / Rotary Cannon)
|
||||
4. Działko Maszynowe (Machine Gun / Gatling Gun)
|
||||
- Posiada ekstremalnie wysoką szybkostrzelność ("ściana ołowiu").
|
||||
- Potrzebuje ułamka sekundy na rozkręcenie luf, zużywa masę energii, ale szybko czyści wrogów.
|
||||
- Parametry (Poziom 1):
|
||||
@ -245,8 +245,8 @@ PODSUMOWANIE MOCOWE BRONI (POZIOM 1)
|
||||
|-----------------|-----------|-----------------|---------|---------------|--------------------------|
|
||||
| Działko Plazmowe | 12 - 18 | 3.5 / sec | 350 px | 4 / strzał | Krótki dystans, ciągły ostrzał|
|
||||
| Laser | 6 - 9 | 5.0 / sec | 800 px | 6 / tick | Natychmiastowy hitscan |
|
||||
| Rakiety | 45 - 70 | 0.8 / sec | 1000 px | 25 / strzał | Naprowadzanie + AOE |
|
||||
| Działko Obrotowe| 3 - 5 | 10.0 / sec | 550 px | 3 / strzał | Wysoka szybkostrzelność i duże zużycie energii |
|
||||
| Rakiety | 45 - 70 | 1 / 5 sec | 1000 px | 25 / strzał | Wolna, celowana + AOE |
|
||||
| Działko Maszynowe| 3 - 5 | 10.0 / sec | 550 px | 3 / strzał | Wysoka szybkostrzelność i duże zużycie energii |
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
@ -55,6 +55,14 @@ ship_strafe_right={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"physical_keycode":69)]
|
||||
}
|
||||
ship_fire_primary={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventMouseButton,"button_index":1)]
|
||||
}
|
||||
ship_fire_secondary={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventMouseButton,"button_index":2)]
|
||||
}
|
||||
|
||||
[editor_plugins]
|
||||
|
||||
|
||||
@ -7,7 +7,12 @@ script = ExtResource("1_definition")
|
||||
item_id = "beam_laser"
|
||||
display_name = "Laser wiązkowy"
|
||||
category = 0
|
||||
description = "Precyzyjna broń o dużym zasięgu."
|
||||
description = "Laser pulsacyjny. Każdy impuls zadaje obrażenia i zużywa 6 energii."
|
||||
primary_stat = "damage"
|
||||
primary_value = 8.0
|
||||
stat_suffix = " DMG"
|
||||
weapon_kind = 2
|
||||
fire_interval = 0.2
|
||||
weapon_range = 800.0
|
||||
energy_cost = 6.0
|
||||
laser_pulse_duration = 0.08
|
||||
|
||||
@ -11,3 +11,4 @@ description = "Zwiększa maksymalną pojemność energii."
|
||||
primary_stat = "max_energy"
|
||||
primary_value = 20.0
|
||||
stat_suffix = " energii"
|
||||
energy_regeneration_bonus = 12.0
|
||||
|
||||
18
resources/items/machine_gun.tres
Normal file
18
resources/items/machine_gun.tres
Normal file
@ -0,0 +1,18 @@
|
||||
[gd_resource type="Resource" script_class="ItemDefinition" load_steps=2 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/items/item_definition.gd" id="1_definition"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_definition")
|
||||
item_id = "machine_gun"
|
||||
display_name = "Działko maszynowe"
|
||||
category = 0
|
||||
description = "Bardzo szybkostrzelna broń kinetyczna."
|
||||
primary_stat = "damage"
|
||||
primary_value = 4.0
|
||||
stat_suffix = " DMG"
|
||||
weapon_kind = 1
|
||||
fire_interval = 0.1
|
||||
projectile_speed = 1150.0
|
||||
weapon_range = 550.0
|
||||
energy_cost = 3.0
|
||||
19
resources/items/missile_launcher.tres
Normal file
19
resources/items/missile_launcher.tres
Normal file
@ -0,0 +1,19 @@
|
||||
[gd_resource type="Resource" script_class="ItemDefinition" load_steps=2 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/items/item_definition.gd" id="1_definition"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_definition")
|
||||
item_id = "missile_launcher"
|
||||
display_name = "Wyrzutnia rakiet"
|
||||
category = 0
|
||||
description = "Wystrzeliwuje wolną rakietę z eksplozją obszarową. Cooldown: 5 s."
|
||||
primary_stat = "damage"
|
||||
primary_value = 60.0
|
||||
stat_suffix = " DMG"
|
||||
weapon_kind = 3
|
||||
fire_interval = 5.0
|
||||
weapon_cooldown = 5.0
|
||||
projectile_speed = 220.0
|
||||
weapon_range = 1000.0
|
||||
energy_cost = 25.0
|
||||
@ -11,3 +11,8 @@ description = "Szybkostrzelna broń krótkiego zasięgu."
|
||||
primary_stat = "damage"
|
||||
primary_value = 15.0
|
||||
stat_suffix = " DMG"
|
||||
weapon_kind = 0
|
||||
fire_interval = 0.2857
|
||||
projectile_speed = 720.0
|
||||
weapon_range = 350.0
|
||||
energy_cost = 4.0
|
||||
|
||||
@ -58,6 +58,7 @@ anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="DebugToggle" type="Button" parent="HUD/HUDRoot"]
|
||||
offset_left = 18.0
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
[gd_scene load_steps=4 format=3]
|
||||
[gd_scene load_steps=5 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/game/ship_controller.gd" id="1_controller"]
|
||||
[ext_resource type="Script" path="res://scripts/items/ship_inventory.gd" id="2_inventory"]
|
||||
[ext_resource type="Script" path="res://scripts/game/weapon_controller.gd" id="3_weapons"]
|
||||
|
||||
[sub_resource type="CircleShape2D" id="ShipCollision"]
|
||||
radius = 24.0
|
||||
@ -23,3 +24,6 @@ position_smoothing_speed = 4.0
|
||||
|
||||
[node name="ShipInventory" type="Node" parent="."]
|
||||
script = ExtResource("2_inventory")
|
||||
|
||||
[node name="WeaponController" type="Node" parent="."]
|
||||
script = ExtResource("3_weapons")
|
||||
|
||||
16
scenes/game/weapon_projectile.tscn
Normal file
16
scenes/game/weapon_projectile.tscn
Normal file
@ -0,0 +1,16 @@
|
||||
[gd_scene load_steps=3 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/game/weapon_projectile.gd" id="1_projectile"]
|
||||
|
||||
[sub_resource type="CircleShape2D" id="ProjectileShape"]
|
||||
radius = 6.0
|
||||
|
||||
[node name="WeaponProjectile" type="Area2D"]
|
||||
collision_layer = 0
|
||||
collision_mask = 5
|
||||
monitoring = true
|
||||
monitorable = false
|
||||
script = ExtResource("1_projectile")
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||
shape = SubResource("ProjectileShape")
|
||||
@ -23,11 +23,13 @@ func _process(_delta: float) -> void:
|
||||
debug_info.text = """STEROWANIE
|
||||
W: ciąg S: hamulec / wsteczny
|
||||
Q / E: strafe A / D: obrót
|
||||
LPM / PPM: broń 1 / broń 2
|
||||
|
||||
STATEK
|
||||
KADŁUB: %d / %d
|
||||
TARCZE: %d / %d
|
||||
ENERGIA: %d / %d
|
||||
ENERGIA REGEN: %.1f /s
|
||||
|
||||
RUCH
|
||||
PRĘDKOŚĆ: %.1f px/s
|
||||
@ -40,6 +42,7 @@ OBRÓT: %.2f rad/s""" % [
|
||||
roundi(float(player.get("hull"))), roundi(float(player.get("max_hull"))),
|
||||
roundi(float(player.get("shields"))), roundi(float(player.get("max_shields"))),
|
||||
roundi(float(player.get("energy"))), roundi(float(player.get("max_energy"))),
|
||||
float(player.get("energy_regeneration")),
|
||||
ship_velocity.length(), ship_velocity.x, ship_velocity.y,
|
||||
ship_position.x, ship_position.y, rad_to_deg(player.rotation), angular_speed,
|
||||
]
|
||||
|
||||
@ -16,12 +16,14 @@ const DEFAULT_SHIP_TEXTURE := "res://assets/Ships/Spaceship_0.png"
|
||||
@export var base_max_shields := 100.0
|
||||
@export var base_max_energy := 100.0
|
||||
@export var base_max_speed := 420.0
|
||||
@export var base_energy_regeneration := 12.0
|
||||
@export var max_hull := 100.0
|
||||
@export var max_shields := 100.0
|
||||
@export var max_energy := 100.0
|
||||
var hull := 100.0
|
||||
var shields := 100.0
|
||||
var energy := 100.0
|
||||
var energy_regeneration := 12.0
|
||||
|
||||
var angular_velocity := 0.0
|
||||
var _sprite: Sprite2D
|
||||
@ -31,6 +33,7 @@ func apply_equipment_bonuses(bonuses: Dictionary) -> void:
|
||||
max_shields = base_max_shields + float(bonuses.get("max_shields", 0.0))
|
||||
max_energy = base_max_energy + float(bonuses.get("max_energy", 0.0))
|
||||
max_speed = base_max_speed + float(bonuses.get("max_speed", 0.0))
|
||||
energy_regeneration = base_energy_regeneration + float(bonuses.get("energy_regeneration", 0.0))
|
||||
reverse_max_speed = max_speed * 0.5
|
||||
max_strafe_speed = max_speed * 0.5
|
||||
hull = minf(hull, max_hull)
|
||||
@ -65,6 +68,7 @@ func _ensure_input_action(action_name: StringName, physical_key: Key) -> void:
|
||||
InputMap.action_add_event(action_name, event)
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
energy = minf(max_energy, energy + energy_regeneration * delta)
|
||||
var turn_input := Input.get_axis("ship_turn_left", "ship_turn_right")
|
||||
if not is_zero_approx(turn_input):
|
||||
angular_velocity = move_toward(
|
||||
|
||||
148
scripts/game/weapon_controller.gd
Normal file
148
scripts/game/weapon_controller.gd
Normal file
@ -0,0 +1,148 @@
|
||||
extends Node
|
||||
|
||||
const PROJECTILE_SCENE := preload("res://scenes/game/weapon_projectile.tscn")
|
||||
const RAY_COLLISION_MASK := 5 # World geometry and enemies on physics layer 3.
|
||||
|
||||
@onready var ship: CharacterBody2D = get_parent()
|
||||
@onready var inventory: ShipInventory = ship.get_node("ShipInventory")
|
||||
|
||||
var _shot_timers := [0.0, 0.0]
|
||||
var _laser_pulse_timers := [0.0, 0.0]
|
||||
var _laser_lines: Array[Line2D] = []
|
||||
var _fire_buttons_down := [false, false]
|
||||
var _fire_just_pressed := [false, false]
|
||||
|
||||
func _ready() -> void:
|
||||
_ensure_input_action(&"ship_fire_primary", MOUSE_BUTTON_LEFT)
|
||||
_ensure_input_action(&"ship_fire_secondary", MOUSE_BUTTON_RIGHT)
|
||||
for slot_index in 2:
|
||||
var beam := Line2D.new()
|
||||
beam.width = 4.0
|
||||
beam.default_color = Color(0.35, 0.9, 1.0, 0.92)
|
||||
beam.z_index = 20
|
||||
beam.visible = false
|
||||
ship.get_parent().call_deferred("add_child", beam)
|
||||
_laser_lines.append(beam)
|
||||
|
||||
func _ensure_input_action(action_name: StringName, button: MouseButton) -> void:
|
||||
if not InputMap.has_action(action_name):
|
||||
InputMap.add_action(action_name, 0.5)
|
||||
var event := InputEventMouseButton.new()
|
||||
event.button_index = button
|
||||
if not InputMap.action_has_event(action_name, event):
|
||||
InputMap.action_add_event(action_name, event)
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if not event is InputEventMouseButton:
|
||||
return
|
||||
var slot_index := -1
|
||||
if event.button_index == MOUSE_BUTTON_LEFT:
|
||||
slot_index = 0
|
||||
elif event.button_index == MOUSE_BUTTON_RIGHT:
|
||||
slot_index = 1
|
||||
if slot_index < 0:
|
||||
return
|
||||
_fire_buttons_down[slot_index] = event.pressed
|
||||
if event.pressed:
|
||||
_fire_just_pressed[slot_index] = true
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
var mouse_over_ui := ship.get_viewport().gui_get_hovered_control() != null
|
||||
for slot_index in 2:
|
||||
_shot_timers[slot_index] = maxf(0.0, _shot_timers[slot_index] - delta)
|
||||
_laser_pulse_timers[slot_index] = maxf(0.0, _laser_pulse_timers[slot_index] - delta)
|
||||
var action_name := "ship_fire_primary" if slot_index == 0 else "ship_fire_secondary"
|
||||
var is_pressed: bool = not mouse_over_ui and (
|
||||
Input.is_action_pressed(action_name) or _fire_buttons_down[slot_index]
|
||||
)
|
||||
var is_just_pressed: bool = not mouse_over_ui and (
|
||||
Input.is_action_just_pressed(action_name) or _fire_just_pressed[slot_index]
|
||||
)
|
||||
var item: ItemInstance = inventory.weapon_slots[slot_index]
|
||||
if not is_pressed or item == null or item.definition == null:
|
||||
_laser_lines[slot_index].visible = (
|
||||
item != null
|
||||
and item.definition != null
|
||||
and item.definition.weapon_kind == ItemDefinition.WeaponKind.LASER
|
||||
and _laser_pulse_timers[slot_index] > 0.0
|
||||
)
|
||||
continue
|
||||
|
||||
var definition := item.definition
|
||||
if definition.weapon_kind != ItemDefinition.WeaponKind.LASER:
|
||||
_laser_pulse_timers[slot_index] = 0.0
|
||||
_laser_lines[slot_index].visible = false
|
||||
match definition.weapon_kind:
|
||||
ItemDefinition.WeaponKind.LASER:
|
||||
_laser_lines[slot_index].visible = _laser_pulse_timers[slot_index] > 0.0
|
||||
_fire_laser(slot_index, definition, item.get_stat_total("damage"))
|
||||
ItemDefinition.WeaponKind.MISSILE:
|
||||
if (
|
||||
is_just_pressed
|
||||
and _shot_timers[slot_index] <= 0.0
|
||||
and _consume_energy(definition.energy_cost)
|
||||
):
|
||||
_fire_projectile(definition, item.get_stat_total("damage"))
|
||||
_shot_timers[slot_index] = definition.weapon_cooldown
|
||||
_:
|
||||
if _shot_timers[slot_index] <= 0.0 and _consume_energy(definition.energy_cost):
|
||||
_fire_projectile(definition, item.get_stat_total("damage"))
|
||||
_shot_timers[slot_index] = definition.fire_interval
|
||||
for slot_index in 2:
|
||||
_fire_just_pressed[slot_index] = false
|
||||
|
||||
func _fire_projectile(definition: ItemDefinition, projectile_damage: float) -> void:
|
||||
var direction := _aim_direction()
|
||||
var projectile := PROJECTILE_SCENE.instantiate()
|
||||
projectile.call(
|
||||
"configure",
|
||||
ship.global_position + direction * 30.0,
|
||||
direction,
|
||||
definition.weapon_kind,
|
||||
definition.projectile_speed,
|
||||
projectile_damage,
|
||||
definition.weapon_range
|
||||
)
|
||||
ship.get_parent().add_child(projectile)
|
||||
|
||||
func _fire_laser(slot_index: int, definition: ItemDefinition, beam_damage: float) -> void:
|
||||
var line := _laser_lines[slot_index]
|
||||
if _shot_timers[slot_index] > 0.0 or float(ship.get("energy")) < definition.energy_cost:
|
||||
return
|
||||
var direction := _aim_direction()
|
||||
var endpoint := ship.global_position + direction * definition.weapon_range
|
||||
var query := PhysicsRayQueryParameters2D.create(
|
||||
ship.global_position,
|
||||
endpoint,
|
||||
RAY_COLLISION_MASK,
|
||||
[ship.get_rid()]
|
||||
)
|
||||
var result := ship.get_world_2d().direct_space_state.intersect_ray(query)
|
||||
if not result.is_empty():
|
||||
endpoint = result["position"]
|
||||
line.clear_points()
|
||||
line.add_point(ship.global_position)
|
||||
line.add_point(endpoint)
|
||||
line.visible = true
|
||||
if not _consume_energy(definition.energy_cost):
|
||||
line.visible = false
|
||||
return
|
||||
if not result.is_empty():
|
||||
_apply_damage(result.get("collider"), beam_damage)
|
||||
_laser_pulse_timers[slot_index] = definition.laser_pulse_duration
|
||||
_shot_timers[slot_index] = definition.fire_interval
|
||||
|
||||
func _aim_direction() -> Vector2:
|
||||
var offset := ship.get_global_mouse_position() - ship.global_position
|
||||
return offset.normalized() if offset.length_squared() > 0.001 else Vector2.UP.rotated(ship.rotation)
|
||||
|
||||
func _consume_energy(amount: float) -> bool:
|
||||
var current_energy := float(ship.get("energy"))
|
||||
if current_energy < amount:
|
||||
return false
|
||||
ship.set("energy", current_energy - amount)
|
||||
return true
|
||||
|
||||
func _apply_damage(target: Variant, damage: float) -> void:
|
||||
if target is Node and target.has_method("take_damage"):
|
||||
target.call("take_damage", damage)
|
||||
1
scripts/game/weapon_controller.gd.uid
Normal file
1
scripts/game/weapon_controller.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://c1506hvftf1fe
|
||||
82
scripts/game/weapon_projectile.gd
Normal file
82
scripts/game/weapon_projectile.gd
Normal file
@ -0,0 +1,82 @@
|
||||
extends Area2D
|
||||
|
||||
var direction := Vector2.UP
|
||||
var projectile_speed := 600.0
|
||||
var damage := 1.0
|
||||
var max_range := 800.0
|
||||
var weapon_kind := ItemDefinition.WeaponKind.PLASMA
|
||||
var _distance_travelled := 0.0
|
||||
var _already_hit: Dictionary = {}
|
||||
|
||||
func _ready() -> void:
|
||||
body_entered.connect(_on_body_entered)
|
||||
area_entered.connect(_on_area_entered)
|
||||
rotation = direction.angle()
|
||||
|
||||
func configure(
|
||||
start_position: Vector2,
|
||||
travel_direction: Vector2,
|
||||
kind: int,
|
||||
speed: float,
|
||||
projectile_damage: float,
|
||||
projectile_range: float
|
||||
) -> void:
|
||||
global_position = start_position
|
||||
direction = travel_direction.normalized()
|
||||
weapon_kind = kind
|
||||
projectile_speed = speed
|
||||
damage = projectile_damage
|
||||
max_range = projectile_range
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
var step := projectile_speed * delta
|
||||
global_position += direction * step
|
||||
_distance_travelled += step
|
||||
if _distance_travelled >= max_range:
|
||||
queue_free()
|
||||
|
||||
func _draw() -> void:
|
||||
match weapon_kind:
|
||||
ItemDefinition.WeaponKind.PLASMA:
|
||||
draw_circle(Vector2.ZERO, 6.0, Color(0.3, 0.85, 1.0, 0.95))
|
||||
draw_circle(Vector2.ZERO, 3.0, Color(0.85, 0.98, 1.0, 1.0))
|
||||
ItemDefinition.WeaponKind.MACHINE_GUN:
|
||||
draw_rect(Rect2(-7.0, -2.0, 14.0, 4.0), Color(1.0, 0.82, 0.38, 1.0))
|
||||
ItemDefinition.WeaponKind.MISSILE:
|
||||
draw_colored_polygon(PackedVector2Array([
|
||||
Vector2(10, 0), Vector2(-7, -4), Vector2(-4, 0), Vector2(-7, 4),
|
||||
]), Color(1.0, 0.42, 0.2, 1.0))
|
||||
|
||||
func _on_body_entered(body: Node2D) -> void:
|
||||
_hit_target(body)
|
||||
|
||||
func _on_area_entered(area: Area2D) -> void:
|
||||
_hit_target(area)
|
||||
|
||||
func _hit_target(target: Node) -> void:
|
||||
if weapon_kind == ItemDefinition.WeaponKind.MISSILE:
|
||||
_explode_at_target(target)
|
||||
else:
|
||||
_apply_damage_once(target)
|
||||
queue_free()
|
||||
|
||||
func _explode_at_target(impact_target: Node) -> void:
|
||||
_apply_damage_once(impact_target)
|
||||
var explosion_shape := CircleShape2D.new()
|
||||
explosion_shape.radius = 120.0
|
||||
var query := PhysicsShapeQueryParameters2D.new()
|
||||
query.shape = explosion_shape
|
||||
query.transform = Transform2D(0.0, global_position)
|
||||
query.collision_mask = 4 # Enemy physics layer 3.
|
||||
for result in get_world_2d().direct_space_state.intersect_shape(query, 32):
|
||||
_apply_damage_once(result.get("collider"))
|
||||
|
||||
func _apply_damage_once(target: Variant) -> void:
|
||||
if not (target is Node):
|
||||
return
|
||||
var instance_id: int = target.get_instance_id()
|
||||
if _already_hit.has(instance_id):
|
||||
return
|
||||
_already_hit[instance_id] = true
|
||||
if target.has_method("take_damage"):
|
||||
target.call("take_damage", damage)
|
||||
1
scripts/game/weapon_projectile.gd.uid
Normal file
1
scripts/game/weapon_projectile.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://4pf7qyhqy6c6
|
||||
@ -2,6 +2,7 @@ extends Resource
|
||||
class_name ItemDefinition
|
||||
|
||||
enum Category { WEAPON, SHIELD, HULL, GENERATOR, EXTENSION }
|
||||
enum WeaponKind { PLASMA, MACHINE_GUN, LASER, MISSILE }
|
||||
|
||||
@export var item_id: String = ""
|
||||
@export var display_name: String = ""
|
||||
@ -10,3 +11,11 @@ enum Category { WEAPON, SHIELD, HULL, GENERATOR, EXTENSION }
|
||||
@export var primary_stat: String = ""
|
||||
@export var primary_value: float = 0.0
|
||||
@export var stat_suffix: String = ""
|
||||
@export var energy_regeneration_bonus: float = 0.0
|
||||
@export var weapon_kind: WeaponKind = WeaponKind.PLASMA
|
||||
@export var fire_interval: float = 0.25
|
||||
@export var weapon_cooldown: float = 0.0
|
||||
@export var laser_pulse_duration: float = 0.08
|
||||
@export var projectile_speed: float = 0.0
|
||||
@export var weapon_range: float = 0.0
|
||||
@export var energy_cost: float = 0.0
|
||||
|
||||
@ -9,6 +9,8 @@ func get_stat_total(stat_key: String) -> float:
|
||||
var total := 0.0
|
||||
if definition and definition.primary_stat == stat_key:
|
||||
total += definition.primary_value
|
||||
if definition and stat_key == "energy_regeneration":
|
||||
total += definition.energy_regeneration_bonus
|
||||
for modifier in additional_modifiers:
|
||||
if modifier and modifier.stat_key == stat_key:
|
||||
total += modifier.value
|
||||
|
||||
@ -84,7 +84,7 @@ func _recalculate_ship_stats() -> void:
|
||||
for item in weapon_slots + module_slots:
|
||||
if item == null or item.definition == null:
|
||||
continue
|
||||
for stat_key in ["max_hull", "max_shields", "max_energy", "max_speed"]:
|
||||
for stat_key in ["max_hull", "max_shields", "max_energy", "max_speed", "energy_regeneration"]:
|
||||
bonuses[stat_key] = float(bonuses.get(stat_key, 0.0)) + item.get_stat_total(stat_key)
|
||||
ship.call("apply_equipment_bonuses", bonuses)
|
||||
|
||||
@ -92,17 +92,26 @@ func _add_starter_items() -> void:
|
||||
var starter_items := [
|
||||
"res://resources/items/plasma_cannon.tres",
|
||||
"res://resources/items/beam_laser.tres",
|
||||
"res://resources/items/machine_gun.tres",
|
||||
"res://resources/items/missile_launcher.tres",
|
||||
"res://resources/items/reinforced_shield.tres",
|
||||
"res://resources/items/hull_plating.tres",
|
||||
"res://resources/items/compact_generator.tres",
|
||||
"res://resources/items/engine_extension.tres",
|
||||
]
|
||||
for index in starter_items.size():
|
||||
var definition := load(starter_items[index]) as ItemDefinition
|
||||
var cargo_index := 0
|
||||
var weapon_index := 0
|
||||
for path in starter_items:
|
||||
var definition := load(path) as ItemDefinition
|
||||
if definition == null:
|
||||
push_warning("Could not load starter item: %s" % starter_items[index])
|
||||
push_warning("Could not load starter item: %s" % path)
|
||||
continue
|
||||
var item := ItemInstance.new()
|
||||
item.definition = definition
|
||||
item.item_level = 1
|
||||
cargo[index] = item
|
||||
if definition.category == ItemDefinition.Category.WEAPON and weapon_index < WEAPON_SLOT_COUNT:
|
||||
weapon_slots[weapon_index] = item
|
||||
weapon_index += 1
|
||||
else:
|
||||
cargo[cargo_index] = item
|
||||
cargo_index += 1
|
||||
|
||||
@ -90,5 +90,6 @@ func _stat_text(item: ItemInstance) -> String:
|
||||
var definition := item.definition
|
||||
if definition.primary_stat.is_empty():
|
||||
return "Poz. %d" % item.item_level
|
||||
var sign_text := "+" if definition.primary_value >= 0.0 else ""
|
||||
return "%s%.0f%s · Poz. %d" % [sign_text, definition.primary_value, definition.stat_suffix, item.item_level]
|
||||
var total_value := item.get_stat_total(definition.primary_stat)
|
||||
var sign_text := "+" if total_value >= 0.0 else ""
|
||||
return "%s%.0f%s · Poz. %d" % [sign_text, total_value, definition.stat_suffix, item.item_level]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user