Badania obcych

This commit is contained in:
Tomasz Boruc 2026-10-25 13:30:48 +01:00
parent 40cd69f8cb
commit 31a352e4b7
9 changed files with 104 additions and 20 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 910 KiB

After

Width:  |  Height:  |  Size: 920 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 888 KiB

After

Width:  |  Height:  |  Size: 897 KiB

View File

@ -0,0 +1,8 @@
shader_type canvas_item;
render_mode unshaded;
void fragment() {
vec4 pixel = texture(TEXTURE, UV);
float brightness = max(pixel.r, max(pixel.g, pixel.b));
COLOR = vec4(vec3(1.0, 0.19, 0.16) * (0.7 + brightness * 0.3), pixel.a * smoothstep(0.03, 0.16, brightness));
}

View File

@ -2,6 +2,8 @@ extends Node2D
var enemy: CharacterBody2D
var _tier_label: Label
var _disabled_icons: Array[PanelContainer] = []
const DISABLED_ICONS := [preload("res://assets/icons/engine.png"),preload("res://assets/icons/plasma.png"),preload("res://assets/icons/shield.png")]
func _ready() -> void:
enemy = get_parent() as CharacterBody2D
@ -18,14 +20,56 @@ func _ready() -> void:
_tier_label.add_theme_color_override("font_outline_color", Color("08111d"))
_tier_label.add_theme_constant_override("outline_size", 3)
add_child(_tier_label)
_build_disabled_icons()
_update_position()
_update_tier_label()
_update_disabled_icons()
func _process(_delta: float) -> void:
_update_position()
_update_tier_label()
_update_disabled_icons()
queue_redraw()
func _build_disabled_icons() -> void:
var material := ShaderMaterial.new()
material.shader = preload("res://resources/effects/disabled_system_icon.gdshader")
for system in 3:
var panel := PanelContainer.new()
panel.name = ["DisabledEngine","DisabledWeapon","DisabledShields"][system]
panel.mouse_filter = Control.MOUSE_FILTER_IGNORE
panel.size = Vector2(20,20)
panel.light_mask = 4
var style := StyleBoxFlat.new()
style.bg_color = Color("17090be8")
style.border_color = Color("ff4b43")
style.set_border_width_all(1)
style.set_corner_radius_all(3)
style.set_content_margin_all(2)
panel.add_theme_stylebox_override("panel",style)
var icon := TextureRect.new()
icon.texture = DISABLED_ICONS[system]
icon.material = material
icon.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
icon.texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR
icon.mouse_filter = Control.MOUSE_FILTER_IGNORE
icon.light_mask = 4
panel.add_child(icon)
add_child(panel)
_disabled_icons.append(panel)
func _update_disabled_icons() -> void:
var active: Array[int] = []
if enemy.hull > 0.0 and not enemy.is_queued_for_deletion():
for system in 3:
if enemy.system_disabled(system): active.append(system)
for system in 3:
var panel := _disabled_icons[system]
panel.visible = system in active
if panel.visible:
panel.position = Vector2(-float(active.size()*22-2)*0.5+active.find(system)*22,-56)
func _update_position() -> void:
global_position = enemy.global_position + Vector2(0, -enemy.get_visual_size() * 0.5 - 12.0)

View File

@ -382,13 +382,8 @@ func disable_system(system: int) -> void:
if system == 2 and not system_disabled(2):
_offline_shields = shields
shields = 0.0
_disabled_systems[system] = 3.0
_disabled_systems[system] = preload("res://scripts/planets/alien_research.gd").SYSTEM_DISABLE_DURATION
if is_instance_valid(_shield_visual): _shield_visual.set_shield_values(shields,max_shields)
var popup := DAMAGE_POPUP_SCENE.instantiate() as Label
popup.text = "%s OFF · 3 s" % ["SILNIK","BROŃ","TARCZE"][system]
popup.set("text_color",Color("efa653"))
popup.position = position+Vector2(-30,-50)
get_parent().add_child(popup)
func tick_disabled_systems(delta: float) -> void:
var shields_offline := system_disabled(2)

View File

@ -1,6 +1,7 @@
extends RefCounted
const ACTIVE_IDS := ["general", "weapons", "hull", "shields", "weapons_a", "weapons_a_next", "weapons_a_next_next", "weapons_a_next_next_next", "weapons_b", "weapons_b_next", "weapons_b_next_next", "weapons_b_next_next_next"]
const BRANCHES := ["weapons", "hull", "shields"]
const SYSTEM_DISABLE_DURATION := 5.0
const TITLES := {"general":"Ogólna wiedza", "weapons":"Wiedza o broni", "hull":"Wiedza o kadłubie", "shields":"Wiedza o tarczach", "weapons_a":"Słaby punkt", "weapons_a_next":"Celny strzał", "weapons_a_next_next":"Rykoszet", "weapons_a_next_next_next":"Strzał w 10", "weapons_b":"Manewr wyprzedzający", "weapons_b_next":"System obrony przed obcymi", "weapons_b_next_next":"Dezorientacja celowania", "weapons_b_next_next_next":"Zakłócenia systemów obcych"}
static func learned(id: String) -> bool:
@ -27,7 +28,7 @@ static func description(id: String) -> String:
"hull": return "Twoja broń zadaje o 10% więcej obrażeń kadłubom obcych."
"shields": return "Twoja broń zadaje o 10% więcej obrażeń tarczom obcych."
"weapons_a": return "Każde bezpośrednie trafienie twojej broni zadaje obcym dodatkowe 5 obrażeń przed absorpcją."
"weapons_a_next": return "Każdy strzał ma 1% szansy wyłączyć na 3 sekundy losowy system obcego: silnik, broń lub tarcze. Obrażenia okresowe nie losują ponownie."
"weapons_a_next": return "Każdy strzał ma 1% szansy wyłączyć na 5 sekund losowy system obcego: silnik, broń lub tarcze. Czerwona ikona nad wrogiem wskazuje wyłączony system. Obrażenia okresowe nie losują ponownie."
"weapons_a_next_next": return "Trafienie dowolną bronią razi też obcych do 10 px od obrysu trafionego statku. Promień eksplozji twoich rakiet rośnie o 10 px. Bez łańcuchowych rykoszetów."
"weapons_a_next_next_next": return "Każde bezpośrednie trafienie zadaje pełne obrażenia jednocześnie tarczom i kadłubowi obcego. Nadal działa absorpcja."
"weapons_b": return "Dodatkowe 5% szansy uniknięcia obrażeń od wrogich obcych. Łączy się niezależnie z pozostałymi unikami."

View File

@ -4,12 +4,13 @@ const MENU := preload("res://scripts/planets/freighter_menu.gd")
const COLORS := [Color("dfb775"), Color("e68c77"), Color("79cba8"), Color("7bc9e6")]
const TILE_SIZE := Vector2(36,40)
const PLACEHOLDER_LEVELS := 4
const COST_COLUMN_WIDTH := 48.0
var progress: Resource
var refreshed: Callable
var points: Dictionary = {}
func _ready() -> void:
custom_minimum_size = Vector2(290, 300)
custom_minimum_size = Vector2(330, 300)
resized.connect(_build)
_build()
@ -18,11 +19,18 @@ func _build() -> void:
remove_child(child)
child.queue_free()
points.clear()
var width := maxf(290, size.x)
_add_skill("general", Vector2(width * 0.5, 24), COLORS[0])
var width := maxf(330, size.x)
var tree_width := width-COST_COLUMN_WIDTH
_add_row_cost("general",24)
_add_row_cost("weapons",80)
var row_id := "weapons_a"
for level in PLACEHOLDER_LEVELS:
_add_row_cost(row_id,142+level*46)
row_id += "_next"
_add_skill("general", Vector2(COST_COLUMN_WIDTH+tree_width*0.5, 24), COLORS[0])
for i in range(3):
var branch: String = DATA.BRANCHES[i]
var x := width * (float(i) + 0.5) / 3.0
var x := COST_COLUMN_WIDTH+tree_width * (float(i) + 0.5) / 3.0
_add_skill(branch, Vector2(x, 80), COLORS[i + 1])
for path in ["a","b"]:
var id: String = branch+"_"+path
@ -57,18 +65,32 @@ func _add_skill(id: String, center: Vector2, color: Color) -> void:
var icon := TextureRect.new()
icon.texture = load("res://assets/freighter/research/" + id + ".png")
icon.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_COVERED
icon.texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR_WITH_MIPMAPS
icon.mouse_filter = Control.MOUSE_FILTER_IGNORE
icon.position = Vector2(5, 1)
icon.size = Vector2(26, 26)
icon.position = Vector2.ONE
icon.size = TILE_SIZE-Vector2(2,2)
icon.clip_contents = true
if not unlocked: icon.modulate = Color(0.5, 0.55, 0.55, 0.65)
button.add_child(icon)
var price := MENU.label(button, "✓" if learned else str(DATA.cost(id)), 12, color if unlocked else MENU.MUTED)
price.mouse_filter = Control.MOUSE_FILTER_IGNORE
price.position = Vector2(0, 27)
price.size = Vector2(36, 12)
if learned:
var check := MENU.label(button,"✓",12,color)
check.mouse_filter = Control.MOUSE_FILTER_IGNORE
check.position = TILE_SIZE-Vector2(13,15)
check.size = Vector2(12,12)
check.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
func _add_row_cost(id: String, y: float) -> void:
var price := MENU.label(self,"%d pkt" % DATA.cost(id),12,MENU.MUTED)
price.name = "RowCost_%d" % DATA.cost(id)
price.autowrap_mode = TextServer.AUTOWRAP_OFF
price.position = Vector2(0,y-10)
price.size = Vector2(COST_COLUMN_WIDTH-6,20)
price.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
price.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
price.tooltip_text = "Koszt każdej technologii w tym rzędzie: %d próbek." % DATA.cost(id)
# The initially wrapped label may retain its old minimum height until text is shaped.
price.set_deferred("size",Vector2(COST_COLUMN_WIDTH-6,20))
func _add_placeholder(id: String, center: Vector2) -> void:
points[id] = center

View File

@ -49,6 +49,8 @@ func _ready() -> void:
assert(screen._drawer.size.x == 490 and screen._drawer.size.y == 430)
var skill_buttons: Array[Node] = screen._content.find_children("*", "Button", true, false)
assert(skill_buttons.size() == 28)
var tree: Control = skill_buttons[0].get_parent()
assert(is_equal_approx(tree.get_node("RowCost_10").get_global_rect().get_center().y,skill_buttons[0].get_global_rect().get_center().y))
assert(DATA.parent("weapons_a_next_next") == "weapons_a_next")
assert(not DATA.purchase(progress,"weapons_a_next_next_next"))
for button in skill_buttons:

View File

@ -70,18 +70,30 @@ func _ready() -> void:
assert(target.system_disabled(2) and target.shields==0.0)
target.regenerate_defenses(1.0)
assert(target.shields==0.0)
target.tick_disabled_systems(3.1)
var health_bar: Node2D = target.get_node("HealthBar")
health_bar._process(0.0)
assert(health_bar.get_node("DisabledShields").visible)
assert(not health_bar.get_node("DisabledEngine").visible and not health_bar.get_node("DisabledWeapon").visible)
target.tick_disabled_systems(4.9)
assert(target.system_disabled(2),"System remains disabled for five seconds")
target.tick_disabled_systems(0.2)
health_bar._process(0.0)
assert(not health_bar.get_node("DisabledShields").visible)
assert(not target.system_disabled(2) and target.shields==85.0)
target.disable_system(1)
var count := get_child_count()
target._fire_plasma(Vector2.RIGHT)
assert(get_child_count()==count,"Disabled weapons cannot fire")
target.disable_system(0)
target.rotation = 1.2
health_bar._process(0.0)
assert(health_bar.get_node("DisabledEngine").visible and health_bar.get_node("DisabledWeapon").visible)
assert(is_zero_approx(health_bar.global_rotation),"Status icons stay upright as the enemy turns")
target.velocity = Vector2.ZERO
target._activated = true
target._physics_process(0.1)
assert(target.velocity.is_zero_approx(),"Disabled engines cannot produce thrust")
target.tick_disabled_systems(3.1)
target.tick_disabled_systems(5.1)
assert(not target.system_disabled(0) and not target.system_disabled(1))
reset_enemy(target,0.0)
target.take_research_dot(10,DamageTypes.Type.RADIATION,0)