Zmiany
This commit is contained in:
parent
6658adf389
commit
1ad22be08e
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,3 +4,4 @@
|
|||||||
export_presets.cfg
|
export_presets.cfg
|
||||||
Randoloot.console.exe
|
Randoloot.console.exe
|
||||||
Randoloot.exe
|
Randoloot.exe
|
||||||
|
/builds/
|
||||||
|
|||||||
24
EXPORT_WINDOWS.md
Normal file
24
EXPORT_WINDOWS.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Eksport do jednego EXE
|
||||||
|
|
||||||
|
1. W Godocie zainstaluj Export Templates zgodne z wersją edytora (obecnie 4.7.2).
|
||||||
|
2. Otwórz Project → Export i wybierz preset Randoloot / Windows Desktop.
|
||||||
|
3. Ustaw architekturę x86_64, Embed PCK włączone i Export Console Wrapper wyłączone.
|
||||||
|
4. Użyj Export Project i wyłącz Export With Debug. Docelowa ścieżka: `builds/windows/Randoloot.exe`.
|
||||||
|
|
||||||
|
Do przekazania graczowi wystarczy ten EXE. Zasoby są wbudowane. Godot nie musi być zainstalowany na komputerze gracza; potrzebny jest Windows 64-bit i sterownik graficzny obsługujący Vulkan. Projekt używa Vulkan zamiast Direct3D 12, aby eksport nie potrzebował dodatkowych bibliotek Agility SDK / PIX.
|
||||||
|
|
||||||
|
Folder `builds` jest pomijany przez Godota i Git. Lokalny `export_presets.cfg` jest już ignorowany przez Git; przy przenoszeniu projektu należy odtworzyć powyższe ustawienia eksportu.
|
||||||
|
|
||||||
|
## Ścieżki i zasoby
|
||||||
|
|
||||||
|
- W PCK wielkość liter ma znaczenie. Ścieżka musi dokładnie odpowiadać nazwie na dysku, np. `res://assets/Ships/Spaceship_0.png`.
|
||||||
|
- Importowane grafiki i dźwięki wczytuj przez `load()` / `preload()` / ResourceLoader. Surowy FileAccess nie gwarantuje dostępu do oryginalnego pliku po eksporcie.
|
||||||
|
- Dane zapisywane podczas gry powinny korzystać z `user://`, ponieważ `res://` w EXE jest tylko do odczytu.
|
||||||
|
- Po eksporcie sprawdź EXE w osobnym folderze bez plików projektu.
|
||||||
|
|
||||||
|
## Dokumentacja
|
||||||
|
|
||||||
|
- https://docs.godotengine.org/en/stable/tutorials/export/exporting_for_windows.html
|
||||||
|
- https://docs.godotengine.org/en/stable/classes/class_editorexportplatformwindows.html
|
||||||
|
- https://docs.godotengine.org/en/stable/classes/class_fileaccess.html
|
||||||
|
- https://docs.godotengine.org/en/stable/tutorials/best_practices/project_organization.html
|
||||||
BIN
assets/Ships/alien_ship.jpg
Normal file
BIN
assets/Ships/alien_ship.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.8 MiB |
@ -15,10 +15,6 @@ run/main_scene="res://scenes/ui/main_menu.tscn"
|
|||||||
config/features=PackedStringArray("4.7", "Forward Plus")
|
config/features=PackedStringArray("4.7", "Forward Plus")
|
||||||
config/icon="res://icon.svg"
|
config/icon="res://icon.svg"
|
||||||
|
|
||||||
[audio]
|
|
||||||
|
|
||||||
buses/default_bus_layout="res://default_bus_layout.tres"
|
|
||||||
|
|
||||||
[autoload]
|
[autoload]
|
||||||
|
|
||||||
GameState="*res://scripts/game/game_state.gd"
|
GameState="*res://scripts/game/game_state.gd"
|
||||||
@ -88,7 +84,3 @@ ship_fire_secondary={
|
|||||||
|
|
||||||
3d/physics_engine="Jolt Physics"
|
3d/physics_engine="Jolt Physics"
|
||||||
common/physics_interpolation=true
|
common/physics_interpolation=true
|
||||||
|
|
||||||
[rendering]
|
|
||||||
|
|
||||||
rendering_device/driver.windows="d3d12"
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@ script = ExtResource("1_definition")
|
|||||||
item_id = "machine_gun"
|
item_id = "machine_gun"
|
||||||
display_name = "Działko maszynowe"
|
display_name = "Działko maszynowe"
|
||||||
category = 0
|
category = 0
|
||||||
description = "Bardzo szybkostrzelna broń kinetyczna."
|
description = "Bardzo szybkostrzelna broń kinetyczna. Zużywa 1 sztukę amunicji na strzał."
|
||||||
primary_stat = "damage"
|
primary_stat = "damage"
|
||||||
primary_value = 4.0
|
primary_value = 4.0
|
||||||
stat_suffix = " DMG"
|
stat_suffix = " DMG"
|
||||||
@ -15,7 +15,7 @@ weapon_kind = 1
|
|||||||
fire_interval = 0.1
|
fire_interval = 0.1
|
||||||
projectile_speed = 1150.0
|
projectile_speed = 1150.0
|
||||||
weapon_range = 550.0
|
weapon_range = 550.0
|
||||||
energy_cost = 3.0
|
energy_cost = 0.0
|
||||||
damage_lower_roll_min = 2
|
damage_lower_roll_min = 2
|
||||||
damage_lower_roll_max = 4
|
damage_lower_roll_max = 4
|
||||||
damage_spread_roll_min = 1
|
damage_spread_roll_min = 1
|
||||||
|
|||||||
@ -71,10 +71,16 @@ layout_mode = 2
|
|||||||
size_flags_vertical = 3
|
size_flags_vertical = 3
|
||||||
theme_override_colors/font_color = Color(0.59, 0.67, 0.75, 1)
|
theme_override_colors/font_color = Color(0.59, 0.67, 0.75, 1)
|
||||||
theme_override_font_sizes/font_size = 14
|
theme_override_font_sizes/font_size = 14
|
||||||
text = "Usługi w przygotowaniu"
|
text = "Kup amunicję do działka maszynowego."
|
||||||
horizontal_alignment = 1
|
horizontal_alignment = 1
|
||||||
vertical_alignment = 1
|
vertical_alignment = 1
|
||||||
|
|
||||||
|
[node name="BuyAmmunitionButton" type="Button" parent="Center/Panel/Contents"]
|
||||||
|
custom_minimum_size = Vector2(0, 44)
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_font_sizes/font_size = 15
|
||||||
|
text = "KUP 100 AMUNICJI — 100 KREDYTÓW"
|
||||||
|
|
||||||
[node name="NextButton" type="Button" parent="Center/Panel/Contents"]
|
[node name="NextButton" type="Button" parent="Center/Panel/Contents"]
|
||||||
custom_minimum_size = Vector2(0, 44)
|
custom_minimum_size = Vector2(0, 44)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|||||||
@ -49,6 +49,22 @@ layout_mode = 2
|
|||||||
theme_override_font_sizes/font_size = 11
|
theme_override_font_sizes/font_size = 11
|
||||||
text = "ZAMKNIJ"
|
text = "ZAMKNIJ"
|
||||||
|
|
||||||
|
[node name="Ammunition" type="HBoxContainer" parent="Contents"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_constants/separation = 12
|
||||||
|
|
||||||
|
[node name="Count" type="Label" parent="Contents/Ammunition"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
theme_override_font_sizes/font_size = 11
|
||||||
|
text = "AMUNICJA: 300"
|
||||||
|
|
||||||
|
[node name="CraftButton" type="Button" parent="Contents/Ammunition"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_font_sizes/font_size = 11
|
||||||
|
text = "TWÓRZ +100 AMUNICJI (50 części)"
|
||||||
|
tooltip_text = "Zamień 50 części na 100 sztuk amunicji do działka maszynowego."
|
||||||
|
|
||||||
[node name="CargoGrid" type="GridContainer" parent="Contents"]
|
[node name="CargoGrid" type="GridContainer" parent="Contents"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_horizontal = 4
|
size_flags_horizontal = 4
|
||||||
|
|||||||
@ -8,15 +8,11 @@ func _ready() -> void:
|
|||||||
push_error("SceneMusicPlayer has no track_path configured.")
|
push_error("SceneMusicPlayer has no track_path configured.")
|
||||||
return
|
return
|
||||||
|
|
||||||
var audio_data := FileAccess.get_file_as_bytes(track_path)
|
var music_stream := load(track_path) as AudioStreamMP3
|
||||||
if audio_data.is_empty():
|
|
||||||
push_error("Could not read music track: %s" % track_path)
|
|
||||||
return
|
|
||||||
|
|
||||||
var music_stream := AudioStreamMP3.load_from_buffer(audio_data)
|
|
||||||
if music_stream == null:
|
if music_stream == null:
|
||||||
push_error("Could not decode music track: %s" % track_path)
|
push_error("Could not decode music track: %s" % track_path)
|
||||||
return
|
return
|
||||||
|
music_stream = music_stream.duplicate() as AudioStreamMP3
|
||||||
music_stream.loop = true
|
music_stream.loop = true
|
||||||
stream = music_stream
|
stream = music_stream
|
||||||
volume_db = playback_volume_db
|
volume_db = playback_volume_db
|
||||||
|
|||||||
@ -9,15 +9,11 @@ var _ship: CharacterBody2D
|
|||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
_ship = get_parent() as CharacterBody2D
|
_ship = get_parent() as CharacterBody2D
|
||||||
var audio_data := FileAccess.get_file_as_bytes(ENGINE_SOUND_PATH)
|
var engine_stream := load(ENGINE_SOUND_PATH) as AudioStreamMP3
|
||||||
if audio_data.size() <= 44:
|
|
||||||
push_error("Could not read engine sound: %s" % ENGINE_SOUND_PATH)
|
|
||||||
return
|
|
||||||
|
|
||||||
var engine_stream := AudioStreamMP3.load_from_buffer(audio_data)
|
|
||||||
if engine_stream == null:
|
if engine_stream == null:
|
||||||
push_error("Could not decode engine sound: %s" % ENGINE_SOUND_PATH)
|
push_error("Could not decode engine sound: %s" % ENGINE_SOUND_PATH)
|
||||||
return
|
return
|
||||||
|
engine_stream = engine_stream.duplicate() as AudioStreamMP3
|
||||||
engine_stream.loop = true
|
engine_stream.loop = true
|
||||||
stream = engine_stream
|
stream = engine_stream
|
||||||
volume_db = SILENT_VOLUME_DB
|
volume_db = SILENT_VOLUME_DB
|
||||||
|
|||||||
@ -25,7 +25,7 @@ static func play(parent: Node, source_position: Vector2, weapon_kind: int, volum
|
|||||||
return
|
return
|
||||||
if not _streams.has(weapon_kind):
|
if not _streams.has(weapon_kind):
|
||||||
var sound_path: String = SOUND_PATHS[weapon_kind]
|
var sound_path: String = SOUND_PATHS[weapon_kind]
|
||||||
_streams[weapon_kind] = AudioStreamMP3.load_from_buffer(FileAccess.get_file_as_bytes(sound_path))
|
_streams[weapon_kind] = load(sound_path) as AudioStreamMP3
|
||||||
var stream := _streams[weapon_kind] as AudioStreamMP3
|
var stream := _streams[weapon_kind] as AudioStreamMP3
|
||||||
if stream == null:
|
if stream == null:
|
||||||
return
|
return
|
||||||
|
|||||||
@ -107,7 +107,7 @@ func _physics_process(delta: float) -> void:
|
|||||||
_fire_projectile(item)
|
_fire_projectile(item)
|
||||||
_shot_timers[slot_index] = definition.weapon_cooldown
|
_shot_timers[slot_index] = definition.weapon_cooldown
|
||||||
_:
|
_:
|
||||||
if _shot_timers[slot_index] <= 0.0 and _consume_energy(item.get_energy_cost()):
|
if _shot_timers[slot_index] <= 0.0 and _consume_shot_resource(item):
|
||||||
_fire_projectile(item)
|
_fire_projectile(item)
|
||||||
_shot_timers[slot_index] = definition.fire_interval
|
_shot_timers[slot_index] = definition.fire_interval
|
||||||
for slot_index in 2:
|
for slot_index in 2:
|
||||||
@ -173,6 +173,11 @@ func _muzzle_position() -> Vector2:
|
|||||||
var forward := Vector2.UP.rotated(ship.rotation)
|
var forward := Vector2.UP.rotated(ship.rotation)
|
||||||
return ship.global_position + forward * 28.0
|
return ship.global_position + forward * 28.0
|
||||||
|
|
||||||
|
func _consume_shot_resource(item: ItemInstance) -> bool:
|
||||||
|
if item.definition.weapon_kind == ItemDefinition.WeaponKind.MACHINE_GUN:
|
||||||
|
return inventory.consume_ammunition()
|
||||||
|
return _consume_energy(item.get_energy_cost())
|
||||||
|
|
||||||
func _consume_energy(amount: float) -> bool:
|
func _consume_energy(amount: float) -> bool:
|
||||||
var current_energy := float(ship.get("energy"))
|
var current_energy := float(ship.get("energy"))
|
||||||
if current_energy < amount:
|
if current_energy < amount:
|
||||||
|
|||||||
@ -53,6 +53,8 @@ func roll_damage() -> float:
|
|||||||
func get_energy_cost() -> float:
|
func get_energy_cost() -> float:
|
||||||
if definition == null or definition.category != ItemDefinition.Category.WEAPON:
|
if definition == null or definition.category != ItemDefinition.Category.WEAPON:
|
||||||
return 0.0
|
return 0.0
|
||||||
|
if definition.weapon_kind == ItemDefinition.WeaponKind.MACHINE_GUN:
|
||||||
|
return 0.0
|
||||||
# Compare this weapon with its starter damage. Captain/global gear buffs are free.
|
# 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_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_spread := roundf((definition.damage_spread_roll_min + definition.damage_spread_roll_max) * 0.5)
|
||||||
@ -109,7 +111,10 @@ 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))
|
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:
|
if definition.category == ItemDefinition.Category.WEAPON:
|
||||||
lines.append("Każdy strzał / impuls losuje obrażenia z tego zakresu.")
|
lines.append("Każdy strzał / impuls losuje obrażenia z tego zakresu.")
|
||||||
lines.append("Zasięg: %.0f px • Energia: %.1f / strzał" % [definition.weapon_range, get_energy_cost()])
|
if definition.weapon_kind == ItemDefinition.WeaponKind.MACHINE_GUN:
|
||||||
|
lines.append("Zasięg: %.0f px • Amunicja: 1 / strzał" % definition.weapon_range)
|
||||||
|
else:
|
||||||
|
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))
|
lines.append("Odstęp strzałów: %.2f s" % maxf(definition.fire_interval, definition.weapon_cooldown))
|
||||||
if not additional_modifiers.is_empty():
|
if not additional_modifiers.is_empty():
|
||||||
lines.append("\nADDONY (aktywne po zamontowaniu)")
|
lines.append("\nADDONY (aktywne po zamontowaniu)")
|
||||||
|
|||||||
@ -2,10 +2,18 @@ extends Node
|
|||||||
class_name ShipInventory
|
class_name ShipInventory
|
||||||
|
|
||||||
signal inventory_changed
|
signal inventory_changed
|
||||||
|
signal ammunition_changed
|
||||||
|
|
||||||
const CARGO_SIZE := 20
|
const CARGO_SIZE := 20
|
||||||
const WEAPON_SLOT_COUNT := 2
|
const WEAPON_SLOT_COUNT := 2
|
||||||
const MODULE_SLOT_COUNT := 6
|
const MODULE_SLOT_COUNT := 6
|
||||||
|
const STARTING_AMMUNITION := 300
|
||||||
|
const AMMUNITION_CRAFT_AMOUNT := 100
|
||||||
|
const AMMUNITION_CRAFT_PARTS_COST := 50.0
|
||||||
|
const AMMUNITION_BUY_AMOUNT := 100
|
||||||
|
const AMMUNITION_BUY_BASE_COST := 20
|
||||||
|
|
||||||
|
var ammunition: int = STARTING_AMMUNITION
|
||||||
|
|
||||||
var cargo: Array[ItemInstance] = []
|
var cargo: Array[ItemInstance] = []
|
||||||
var weapon_slots: Array[ItemInstance] = []
|
var weapon_slots: Array[ItemInstance] = []
|
||||||
@ -24,6 +32,7 @@ func _ready() -> void:
|
|||||||
cargo.assign(GameState.restart_inventory["cargo"])
|
cargo.assign(GameState.restart_inventory["cargo"])
|
||||||
weapon_slots.assign(GameState.restart_inventory["weapon"])
|
weapon_slots.assign(GameState.restart_inventory["weapon"])
|
||||||
module_slots.assign(GameState.restart_inventory["module"])
|
module_slots.assign(GameState.restart_inventory["module"])
|
||||||
|
ammunition = int(GameState.restart_inventory.get("ammunition", STARTING_AMMUNITION))
|
||||||
GameState.restart_inventory.clear()
|
GameState.restart_inventory.clear()
|
||||||
_recalculate_ship_stats()
|
_recalculate_ship_stats()
|
||||||
inventory_changed.emit()
|
inventory_changed.emit()
|
||||||
@ -41,14 +50,49 @@ func preserve_for_restart() -> void:
|
|||||||
"cargo": cargo.duplicate(),
|
"cargo": cargo.duplicate(),
|
||||||
"weapon": weapon_slots.duplicate(),
|
"weapon": weapon_slots.duplicate(),
|
||||||
"module": module_slots.duplicate(),
|
"module": module_slots.duplicate(),
|
||||||
|
"ammunition": ammunition,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func consume_ammunition() -> bool:
|
||||||
|
if ammunition <= 0:
|
||||||
|
return false
|
||||||
|
ammunition -= 1
|
||||||
|
ammunition_changed.emit()
|
||||||
|
return true
|
||||||
|
|
||||||
|
func can_craft_ammunition() -> bool:
|
||||||
|
return GameState.captain.parts >= AMMUNITION_CRAFT_PARTS_COST
|
||||||
|
|
||||||
|
func craft_ammunition() -> bool:
|
||||||
|
if not can_craft_ammunition():
|
||||||
|
return false
|
||||||
|
GameState.captain.parts -= AMMUNITION_CRAFT_PARTS_COST
|
||||||
|
ammunition += AMMUNITION_CRAFT_AMOUNT
|
||||||
|
GameState.captain.emit_changed()
|
||||||
|
ammunition_changed.emit()
|
||||||
|
return true
|
||||||
|
|
||||||
func get_item(slot_kind: String, index: int) -> ItemInstance:
|
func get_item(slot_kind: String, index: int) -> ItemInstance:
|
||||||
var slots := _get_slots(slot_kind)
|
var slots := _get_slots(slot_kind)
|
||||||
if index < 0 or index >= slots.size():
|
if index < 0 or index >= slots.size():
|
||||||
return null
|
return null
|
||||||
return slots[index]
|
return slots[index]
|
||||||
|
|
||||||
|
func get_ammunition_buy_cost() -> int:
|
||||||
|
return AMMUNITION_BUY_BASE_COST * maxi(1, GameState.system_level)
|
||||||
|
|
||||||
|
func can_buy_ammunition() -> bool:
|
||||||
|
return GameState.captain.credits >= get_ammunition_buy_cost()
|
||||||
|
|
||||||
|
func buy_ammunition() -> bool:
|
||||||
|
if not can_buy_ammunition():
|
||||||
|
return false
|
||||||
|
GameState.captain.credits -= get_ammunition_buy_cost()
|
||||||
|
ammunition += AMMUNITION_BUY_AMOUNT
|
||||||
|
GameState.captain.emit_changed()
|
||||||
|
ammunition_changed.emit()
|
||||||
|
return true
|
||||||
|
|
||||||
func add_item(item: ItemInstance) -> bool:
|
func add_item(item: ItemInstance) -> bool:
|
||||||
if item == null or item.definition == null:
|
if item == null or item.definition == null:
|
||||||
return false
|
return false
|
||||||
@ -122,34 +166,11 @@ func _recalculate_ship_stats() -> void:
|
|||||||
ship.call("apply_equipment_bonuses", bonuses)
|
ship.call("apply_equipment_bonuses", bonuses)
|
||||||
|
|
||||||
func _add_starter_items() -> void:
|
func _add_starter_items() -> void:
|
||||||
var starter_items := [
|
var definition := load("res://resources/items/plasma_cannon.tres") as ItemDefinition
|
||||||
"res://resources/items/plasma_cannon.tres",
|
if definition == null:
|
||||||
"res://resources/items/beam_laser.tres",
|
push_warning("Could not load starter plasma cannon")
|
||||||
"res://resources/items/machine_gun.tres",
|
return
|
||||||
"res://resources/items/missile_launcher.tres",
|
var item := ItemInstance.new()
|
||||||
"res://resources/items/reinforced_shield.tres",
|
item.definition = definition
|
||||||
"res://resources/items/hull_plating.tres",
|
item.item_level = 1
|
||||||
"res://resources/items/compact_generator.tres",
|
weapon_slots[0] = item
|
||||||
"res://resources/items/engine_extension.tres",
|
|
||||||
"res://resources/items/tuned_thrusters.tres",
|
|
||||||
"res://resources/items/shield_recharger.tres",
|
|
||||||
"res://resources/items/afterburner.tres",
|
|
||||||
"res://resources/items/shield_charge.tres",
|
|
||||||
"res://resources/items/repair_drones.tres",
|
|
||||||
]
|
|
||||||
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" % path)
|
|
||||||
continue
|
|
||||||
var item := ItemInstance.new()
|
|
||||||
item.definition = definition
|
|
||||||
item.item_level = 1
|
|
||||||
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
|
|
||||||
|
|||||||
@ -5,16 +5,37 @@ signal closed
|
|||||||
|
|
||||||
@onready var next_button: Button = $Center/Panel/Contents/NextButton
|
@onready var next_button: Button = $Center/Panel/Contents/NextButton
|
||||||
@onready var close_button: Button = $Center/Panel/Contents/CloseButton
|
@onready var close_button: Button = $Center/Panel/Contents/CloseButton
|
||||||
|
@onready var buy_ammunition_button: Button = $Center/Panel/Contents/BuyAmmunitionButton
|
||||||
|
@onready var services_label: Label = $Center/Panel/Contents/Services
|
||||||
|
|
||||||
|
var _inventory: ShipInventory
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
next_button.pressed.connect(func() -> void: next_level_requested.emit())
|
next_button.pressed.connect(func() -> void: next_level_requested.emit())
|
||||||
close_button.pressed.connect(_close)
|
close_button.pressed.connect(_close)
|
||||||
|
buy_ammunition_button.pressed.connect(_buy_ammunition)
|
||||||
|
_inventory = get_tree().get_first_node_in_group("ship_inventory") as ShipInventory
|
||||||
|
if _inventory:
|
||||||
|
_inventory.ammunition_changed.connect(_refresh_ammunition_service)
|
||||||
|
GameState.captain.changed.connect(_refresh_ammunition_service)
|
||||||
|
_refresh_ammunition_service()
|
||||||
|
|
||||||
func show_services(at_level_cap: bool) -> void:
|
func show_services(at_level_cap: bool) -> void:
|
||||||
|
_refresh_ammunition_service()
|
||||||
next_button.disabled = at_level_cap
|
next_button.disabled = at_level_cap
|
||||||
next_button.text = "OSIĄGNIĘTO OSTATNI UKŁAD" if at_level_cap else "PRZEJDŹ DO NASTĘPNEGO UKŁADU"
|
next_button.text = "OSIĄGNIĘTO OSTATNI UKŁAD" if at_level_cap else "PRZEJDŹ DO NASTĘPNEGO UKŁADU"
|
||||||
show()
|
show()
|
||||||
|
|
||||||
|
func _refresh_ammunition_service() -> void:
|
||||||
|
buy_ammunition_button.disabled = _inventory == null or not _inventory.can_buy_ammunition()
|
||||||
|
if _inventory:
|
||||||
|
buy_ammunition_button.text = "KUP %d AMUNICJI — %d KREDYTÓW" % [ShipInventory.AMMUNITION_BUY_AMOUNT, _inventory.get_ammunition_buy_cost()]
|
||||||
|
services_label.text = "Amunicja: %d • Kredyty: %d\nCena: 100 kredytów × poziom układu (%d)" % [_inventory.ammunition, GameState.captain.credits, GameState.system_level]
|
||||||
|
|
||||||
|
func _buy_ammunition() -> void:
|
||||||
|
if visible and _inventory:
|
||||||
|
_inventory.buy_ammunition()
|
||||||
|
|
||||||
func _close() -> void:
|
func _close() -> void:
|
||||||
hide()
|
hide()
|
||||||
closed.emit()
|
closed.emit()
|
||||||
|
|||||||
@ -6,6 +6,8 @@ const CARGO_SIZE := 20
|
|||||||
@onready var cargo_grid: GridContainer = $Contents/CargoGrid
|
@onready var cargo_grid: GridContainer = $Contents/CargoGrid
|
||||||
@onready var close_button: Button = $Contents/Header/CloseButton
|
@onready var close_button: Button = $Contents/Header/CloseButton
|
||||||
@onready var title_label: Label = $Contents/Header/Title
|
@onready var title_label: Label = $Contents/Header/Title
|
||||||
|
@onready var ammunition_label: Label = $Contents/Ammunition/Count
|
||||||
|
@onready var craft_button: Button = $Contents/Ammunition/CraftButton
|
||||||
|
|
||||||
var _inventory: ShipInventory
|
var _inventory: ShipInventory
|
||||||
var _drawer_open := false
|
var _drawer_open := false
|
||||||
@ -14,9 +16,12 @@ var drawer_width := 780.0
|
|||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
close_button.pressed.connect(close_drawer)
|
close_button.pressed.connect(close_drawer)
|
||||||
|
craft_button.pressed.connect(_craft_ammunition)
|
||||||
|
craft_button.text = "TWÓRZ +%d AMUNICJI (%.0f części)" % [ShipInventory.AMMUNITION_CRAFT_AMOUNT, ShipInventory.AMMUNITION_CRAFT_PARTS_COST]
|
||||||
_inventory = get_tree().get_first_node_in_group("ship_inventory") as ShipInventory
|
_inventory = get_tree().get_first_node_in_group("ship_inventory") as ShipInventory
|
||||||
if _inventory:
|
if _inventory:
|
||||||
_inventory.inventory_changed.connect(_refresh_title)
|
_inventory.inventory_changed.connect(_refresh_title)
|
||||||
|
_inventory.ammunition_changed.connect(_refresh_title)
|
||||||
GameState.captain.changed.connect(_refresh_title)
|
GameState.captain.changed.connect(_refresh_title)
|
||||||
for index in CARGO_SIZE:
|
for index in CARGO_SIZE:
|
||||||
var slot := SLOT_SCENE.instantiate()
|
var slot := SLOT_SCENE.instantiate()
|
||||||
@ -26,8 +31,14 @@ func _ready() -> void:
|
|||||||
_refresh_title()
|
_refresh_title()
|
||||||
|
|
||||||
func _refresh_title() -> void:
|
func _refresh_title() -> void:
|
||||||
|
craft_button.disabled = _inventory == null or not _inventory.can_craft_ammunition()
|
||||||
if _inventory:
|
if _inventory:
|
||||||
title_label.text = "MAGAZYN (%d/%d) · Części: %.1f" % [_inventory.get_cargo_used(), CARGO_SIZE, GameState.captain.parts]
|
title_label.text = "MAGAZYN (%d/%d) · Części: %.1f" % [_inventory.get_cargo_used(), CARGO_SIZE, GameState.captain.parts]
|
||||||
|
ammunition_label.text = "AMUNICJA: %d" % _inventory.ammunition
|
||||||
|
|
||||||
|
func _craft_ammunition() -> void:
|
||||||
|
if _inventory:
|
||||||
|
_inventory.craft_ammunition()
|
||||||
|
|
||||||
func toggle_drawer() -> void:
|
func toggle_drawer() -> void:
|
||||||
_set_drawer_open(not _drawer_open)
|
_set_drawer_open(not _drawer_open)
|
||||||
|
|||||||
@ -32,7 +32,10 @@ func _ready() -> void:
|
|||||||
addon.stat_key = "damage_percent"
|
addon.stat_key = "damage_percent"
|
||||||
addon.value = 10.0
|
addon.value = 10.0
|
||||||
stronger.additional_modifiers.append(addon)
|
stronger.additional_modifiers.append(addon)
|
||||||
assert(stronger.get_energy_cost() > cost_before_addon)
|
if definition.weapon_kind == ItemDefinition.WeaponKind.MACHINE_GUN:
|
||||||
|
assert(stronger.get_energy_cost() == 0.0)
|
||||||
|
else:
|
||||||
|
assert(stronger.get_energy_cost() > cost_before_addon)
|
||||||
for level in [1, 50, 1000]:
|
for level in [1, 50, 1000]:
|
||||||
for sample in 100:
|
for sample in 100:
|
||||||
var item := GENERATOR.generate_for_definition(definition, level)
|
var item := GENERATOR.generate_for_definition(definition, level)
|
||||||
@ -73,6 +76,38 @@ func _ready() -> void:
|
|||||||
var probe := LaserProbe.new()
|
var probe := LaserProbe.new()
|
||||||
player.add_child(probe)
|
player.add_child(probe)
|
||||||
probe.set_physics_process(false)
|
probe.set_physics_process(false)
|
||||||
|
var inventory := player.get_node("ShipInventory") as ShipInventory
|
||||||
|
assert(inventory.ammunition == 300)
|
||||||
|
var machine_gun := ItemInstance.new()
|
||||||
|
machine_gun.definition = preload("res://resources/items/machine_gun.tres")
|
||||||
|
player.set("energy", 0.0)
|
||||||
|
inventory.ammunition = 1
|
||||||
|
assert(probe._consume_shot_resource(machine_gun))
|
||||||
|
assert(inventory.ammunition == 0 and player.get("energy") == 0.0)
|
||||||
|
assert(not probe._consume_shot_resource(machine_gun))
|
||||||
|
GameState.captain.parts = 49.0
|
||||||
|
assert(not inventory.craft_ammunition())
|
||||||
|
assert(inventory.ammunition == 0 and GameState.captain.parts == 49.0)
|
||||||
|
GameState.captain.parts = 50.0
|
||||||
|
assert(inventory.craft_ammunition())
|
||||||
|
assert(inventory.ammunition == 100 and GameState.captain.parts == 0.0)
|
||||||
|
GameState.system_level = 3
|
||||||
|
assert(inventory.get_ammunition_buy_cost() == 300)
|
||||||
|
GameState.captain.credits = 299
|
||||||
|
assert(not inventory.buy_ammunition())
|
||||||
|
assert(inventory.ammunition == 100 and GameState.captain.credits == 299)
|
||||||
|
GameState.captain.credits = 600
|
||||||
|
assert(inventory.buy_ammunition())
|
||||||
|
assert(inventory.ammunition == 200 and GameState.captain.credits == 300)
|
||||||
|
assert(inventory.buy_ammunition())
|
||||||
|
assert(inventory.ammunition == 300 and GameState.captain.credits == 0)
|
||||||
|
assert(not inventory.buy_ammunition())
|
||||||
|
GameState.system_level = 1
|
||||||
|
inventory.preserve_for_restart()
|
||||||
|
var restored_player := PLAYER_SCENE.instantiate() as CharacterBody2D
|
||||||
|
add_child(restored_player)
|
||||||
|
assert(restored_player.get_node("ShipInventory").get("ammunition") == 300)
|
||||||
|
restored_player.queue_free()
|
||||||
var target := StaticBody2D.new()
|
var target := StaticBody2D.new()
|
||||||
target.position = Vector2(200, -28)
|
target.position = Vector2(200, -28)
|
||||||
target.collision_layer = 4
|
target.collision_layer = 4
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user