189 lines
7.0 KiB
GDScript
189 lines
7.0 KiB
GDScript
extends StaticBody2D
|
|
|
|
const GENERATOR := preload("res://scripts/items/item_generator.gd")
|
|
const LOOT := preload("res://scripts/items/loot_pickup.gd")
|
|
var kind := "wreck"
|
|
var poi_id := ""
|
|
var reward_seed := 1
|
|
var player: CharacterBody2D
|
|
var approach_radius := 115.0
|
|
var hull := 20.0
|
|
var _claimed := false
|
|
var _module_left_outside := false
|
|
var _label: Label
|
|
var _rng := RandomNumberGenerator.new()
|
|
var _mineral := "iron"
|
|
var _points := PackedVector2Array()
|
|
|
|
func _ready() -> void:
|
|
add_to_group("exploration_pois")
|
|
_rng.seed = reward_seed
|
|
_mineral = ["iron", "aluminium", "titanium"][_rng.randi_range(0, 2)]
|
|
hull = 20.0 * reward_scale()
|
|
collision_layer = 4 if kind == "asteroid" else 0
|
|
collision_mask = 0
|
|
if kind == "asteroid":
|
|
var shape := CollisionShape2D.new()
|
|
var circle := CircleShape2D.new()
|
|
circle.radius = 30
|
|
shape.shape = circle
|
|
add_child(shape)
|
|
for index in 10:
|
|
_points.append(Vector2.RIGHT.rotated(TAU * index / 10) * _rng.randf_range(23, 35))
|
|
_label = Label.new()
|
|
_label.light_mask = 4
|
|
_label.position = Vector2(-160, 40)
|
|
_label.size = Vector2(320, 70)
|
|
_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
|
_label.add_theme_font_size_override("font_size", 12)
|
|
if kind == "ruin":
|
|
z_index = 20
|
|
_label.position = Vector2(-40, -35)
|
|
_label.size = Vector2(80, 70)
|
|
_label.add_theme_font_size_override("font_size", 52)
|
|
_label.add_theme_color_override("font_color", Color("ffd166"))
|
|
_label.add_theme_color_override("font_outline_color", Color("151625"))
|
|
_label.add_theme_constant_override("outline_size", 8)
|
|
add_child(_label)
|
|
_update_label(false)
|
|
queue_redraw()
|
|
|
|
func reward_scale() -> float:
|
|
return 1.0 + 0.05 * (clampi(GameState.system_level, 1, 1000) - 1)
|
|
|
|
func _draw() -> void:
|
|
if kind == "asteroid":
|
|
draw_colored_polygon(_points, Color("655e56"))
|
|
var outline := _points.duplicate()
|
|
outline.append(_points[0])
|
|
draw_polyline(outline, Color("a39a88"), 2, true)
|
|
draw_circle(Vector2(-8, -5), 7, Color("49443f"))
|
|
elif kind == "wreck":
|
|
draw_colored_polygon(PackedVector2Array([Vector2(-38, 20), Vector2(-16, -30), Vector2(7, -12), Vector2(22, 27), Vector2(-5, 14)]), Color("626b78"))
|
|
draw_line(Vector2(-12, -20), Vector2(4, 15), Color("df9c67"), 3, true)
|
|
draw_colored_polygon(PackedVector2Array([Vector2(28, -16), Vector2(42, -5), Vector2(29, 8)]), Color("434e60"))
|
|
|
|
func _update_label(near: bool) -> void:
|
|
if kind == "ruin":
|
|
_label.text = "?"
|
|
elif kind == "asteroid":
|
|
_label.text = "Asteroida · %s\nHP: %.0f" % [{"iron": "Żelazo", "aluminium": "Aluminium", "titanium": "Tytan"}[_mineral], hull]
|
|
else:
|
|
_label.text = ("Wrak statku" if kind == "wreck" else "Antyczne znalezisko") + ("\n[E] Przeszukaj" if near else "\nPodleć, aby przeszukać")
|
|
|
|
func _physics_process(_delta: float) -> void:
|
|
if _claimed or not is_instance_valid(player) or bool(player.get("_is_destroyed")):
|
|
return
|
|
var near := global_position.distance_to(player.global_position) <= approach_radius
|
|
_update_label(near)
|
|
if near and (kind == "ruin" or (kind == "wreck" and Input.is_physical_key_pressed(KEY_E))):
|
|
claim()
|
|
|
|
func take_weapon_hit(amount: float, _critical: bool = false) -> void:
|
|
take_damage(amount)
|
|
|
|
func take_damage(amount: float) -> void:
|
|
if kind != "asteroid" or _claimed:
|
|
return
|
|
hull -= maxf(0, amount)
|
|
if hull <= 0:
|
|
claim()
|
|
else:
|
|
_update_label(false)
|
|
|
|
func claim() -> bool:
|
|
if _claimed or not is_instance_valid(player) or bool(player.get("_is_destroyed")):
|
|
return false
|
|
_claimed = true
|
|
GameState.explored_pois[poi_id] = true
|
|
var inventory := player.get_node("ShipInventory") as ShipInventory
|
|
var summary := ""
|
|
var scale := reward_scale()
|
|
if kind == "asteroid":
|
|
var amount := maxi(1, roundi(_rng.randi_range(1, 3) * scale))
|
|
GameState.captain.minerals[_mineral] = int(GameState.captain.minerals.get(_mineral, 0)) + amount
|
|
summary = "+%d %s" % [amount, {"iron": "żelaza", "aluminium": "aluminium", "titanium": "tytanu"}[_mineral]]
|
|
elif kind == "ruin":
|
|
var xp := roundi(_rng.randi_range(10, 20) * scale)
|
|
GameState.captain.add_rewards(xp, 0)
|
|
var module := _drop_module(true)
|
|
summary = "%d XP oraz %s (poziom %d)" % [xp, module.definition.display_name, module.item_level]
|
|
_show_discovery(summary)
|
|
else:
|
|
match _rng.randi_range(0, 3):
|
|
0:
|
|
var amount := roundi(_rng.randi_range(3, 8) * scale)
|
|
GameState.captain.parts += amount
|
|
summary = "+%d części" % amount
|
|
1:
|
|
_drop_module(false)
|
|
summary = "Znaleziono moduł"
|
|
2:
|
|
var amount := maxi(1, roundi(scale))
|
|
inventory.missile_ammunition += amount
|
|
summary = "+%d rakiet" % amount
|
|
3:
|
|
var amount := roundi(_rng.randi_range(5, 15) * scale)
|
|
inventory.ammunition += amount
|
|
summary = "+%d amunicji" % amount
|
|
inventory.ammunition_changed.emit()
|
|
GameState.captain.emit_changed()
|
|
if kind != "ruin":
|
|
var popup := preload("res://scenes/game/damage_popup.tscn").instantiate() as Label
|
|
popup.text = summary
|
|
popup.set("text_color", Color("c9e8ff"))
|
|
popup.position = position + Vector2(-80, -65)
|
|
get_parent().add_child.call_deferred(popup)
|
|
set_physics_process(false)
|
|
queue_free()
|
|
return true
|
|
|
|
func _show_discovery(reward: String) -> void:
|
|
var layer := CanvasLayer.new()
|
|
layer.layer = 30
|
|
layer.name = "AncientDiscoveryMessage"
|
|
get_parent().add_child(layer)
|
|
var panel := PanelContainer.new()
|
|
panel.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
layer.add_child(panel)
|
|
panel.set_anchors_and_offsets_preset(Control.PRESET_CENTER_TOP)
|
|
panel.offset_left = -300
|
|
panel.offset_right = 300
|
|
panel.offset_top = 70
|
|
var label := Label.new()
|
|
label.custom_minimum_size = Vector2(600, 95)
|
|
label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
|
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
|
label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
|
label.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
label.add_theme_font_size_override("font_size", 18)
|
|
label.add_theme_color_override("font_color", Color("ffd166"))
|
|
label.text = "Znalazłeś ślady starożytnej upadłej cywilizacji!\nZdobyłeś: " + reward
|
|
if _module_left_outside:
|
|
label.text += "\nMagazyn pełny — moduł czeka obok planety."
|
|
panel.add_child(label)
|
|
var tween := layer.create_tween()
|
|
tween.tween_interval(7.0)
|
|
tween.tween_property(panel, "modulate:a", 0.0, 0.5)
|
|
tween.tween_callback(layer.queue_free)
|
|
|
|
func _drop_module(ancient: bool) -> ItemInstance:
|
|
var definitions: Array[ItemDefinition] = []
|
|
for definition in GENERATOR.DEFINITIONS:
|
|
if definition.category != ItemDefinition.Category.WEAPON:
|
|
definitions.append(definition)
|
|
var item := GENERATOR.generate_for_definition(definitions[_rng.randi_range(0, definitions.size() - 1)], mini(1000, GameState.system_level + (1 if ancient else 0)), 2 if ancient else 0)
|
|
if ancient:
|
|
for modifier in item.additional_modifiers:
|
|
var bounds := modifier.affix.get_value_range(item.item_level)
|
|
modifier.value = lerpf(bounds.x, bounds.y, _rng.randf_range(0.9, 1.0))
|
|
if player.get_node("ShipInventory").add_item(item):
|
|
return item
|
|
_module_left_outside = true
|
|
var loot := Node2D.new()
|
|
loot.set_script(LOOT)
|
|
loot.set("item", item)
|
|
loot.position = position + Vector2(0, 70)
|
|
get_parent().add_child.call_deferred(loot)
|
|
return item
|