Loot-System, Gegner-Drops und Gold-Anzeige hinzugefügt
- Enemy droppt Loot bei Tod (Gold + Items basierend auf LootTable) - LootWindow zeigt Beute an mit "Alles aufheben" Button - Gold-Anzeige im HUD unter XP-Leiste - Beispiel LootTables: Goblin (2-8 Gold) und Skeleton (5-15 Gold) - Loot-System in World verdrahtet Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
9ab6deddff
commit
b01059de50
9 changed files with 295 additions and 0 deletions
20
enemy.gd
20
enemy.gd
|
|
@ -3,6 +3,7 @@
|
||||||
extends CharacterBody3D
|
extends CharacterBody3D
|
||||||
|
|
||||||
signal enemy_died(spawn_position: Vector3, xp_reward: int)
|
signal enemy_died(spawn_position: Vector3, xp_reward: int)
|
||||||
|
signal enemy_dropped_loot(loot: Dictionary, world_position: Vector3)
|
||||||
|
|
||||||
const SPEED = 3.0
|
const SPEED = 3.0
|
||||||
const PATROL_SPEED = 1.5
|
const PATROL_SPEED = 1.5
|
||||||
|
|
@ -36,6 +37,9 @@ var attack_damage: int = 5
|
||||||
# XP-Belohnung (skaliert mit Level)
|
# XP-Belohnung (skaliert mit Level)
|
||||||
var xp_reward: int = 25
|
var xp_reward: int = 25
|
||||||
|
|
||||||
|
# Loot-System
|
||||||
|
@export var loot_table: LootTable
|
||||||
|
|
||||||
var target = null # Spieler-Referenz (wird von World gesetzt)
|
var target = null # Spieler-Referenz (wird von World gesetzt)
|
||||||
var can_attack = true
|
var can_attack = true
|
||||||
var spawn_position: Vector3 # Ursprüngliche Spawn-Position
|
var spawn_position: Vector3 # Ursprüngliche Spawn-Position
|
||||||
|
|
@ -119,9 +123,25 @@ func die():
|
||||||
# XP an Spieler geben
|
# XP an Spieler geben
|
||||||
if target and target.has_method("gain_xp"):
|
if target and target.has_method("gain_xp"):
|
||||||
target.gain_xp(xp_reward)
|
target.gain_xp(xp_reward)
|
||||||
|
# Loot generieren und droppen
|
||||||
|
_drop_loot()
|
||||||
enemy_died.emit(spawn_position, xp_reward)
|
enemy_died.emit(spawn_position, xp_reward)
|
||||||
queue_free()
|
queue_free()
|
||||||
|
|
||||||
|
# Loot generieren basierend auf LootTable
|
||||||
|
func _drop_loot():
|
||||||
|
if loot_table == null:
|
||||||
|
# Standard-Gold-Drop wenn keine LootTable zugewiesen
|
||||||
|
var gold = randi_range(1, 3) * level
|
||||||
|
var loot = {"gold": gold, "items": []}
|
||||||
|
enemy_dropped_loot.emit(loot, global_position)
|
||||||
|
return
|
||||||
|
|
||||||
|
var loot = loot_table.generate_loot()
|
||||||
|
# Gold mit Level skalieren
|
||||||
|
loot["gold"] = loot["gold"] * level
|
||||||
|
enemy_dropped_loot.emit(loot, global_position)
|
||||||
|
|
||||||
func _physics_process(delta):
|
func _physics_process(delta):
|
||||||
if not is_on_floor():
|
if not is_on_floor():
|
||||||
velocity.y -= GRAVITY * delta
|
velocity.y -= GRAVITY * delta
|
||||||
|
|
|
||||||
15
hud.gd
15
hud.gd
|
|
@ -10,6 +10,7 @@ signal slot_clicked(slot_index: int)
|
||||||
# Level/XP UI (wird dynamisch erstellt)
|
# Level/XP UI (wird dynamisch erstellt)
|
||||||
var level_label: Label
|
var level_label: Label
|
||||||
var xp_bar: ProgressBar
|
var xp_bar: ProgressBar
|
||||||
|
var gold_label: Label
|
||||||
@onready var action_slots = [
|
@onready var action_slots = [
|
||||||
$Control/ActionBar/A1,
|
$Control/ActionBar/A1,
|
||||||
$Control/ActionBar/A2,
|
$Control/ActionBar/A2,
|
||||||
|
|
@ -130,6 +131,20 @@ func _create_level_ui():
|
||||||
|
|
||||||
control.add_child(xp_bar)
|
control.add_child(xp_bar)
|
||||||
|
|
||||||
|
# Gold Label
|
||||||
|
gold_label = Label.new()
|
||||||
|
gold_label.name = "GoldLabel"
|
||||||
|
gold_label.position = Vector2(20, 78)
|
||||||
|
gold_label.add_theme_font_size_override("font_size", 14)
|
||||||
|
gold_label.add_theme_color_override("font_color", Color(1, 0.85, 0, 1))
|
||||||
|
gold_label.text = "0 Gold"
|
||||||
|
control.add_child(gold_label)
|
||||||
|
|
||||||
|
# Gold aktualisieren
|
||||||
|
func update_gold(amount: int):
|
||||||
|
if gold_label:
|
||||||
|
gold_label.text = str(amount) + " Gold"
|
||||||
|
|
||||||
# HP-Leiste und Text aktualisieren
|
# HP-Leiste und Text aktualisieren
|
||||||
func update_health(current_hp, max_hp):
|
func update_health(current_hp, max_hp):
|
||||||
health_bar.max_value = max_hp
|
health_bar.max_value = max_hp
|
||||||
|
|
|
||||||
28
loot_tables/goblin_loot.tres
Normal file
28
loot_tables/goblin_loot.tres
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
[gd_resource type="Resource" script_class="LootTable" format=3]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://loot_table.gd" id="1"]
|
||||||
|
[ext_resource type="Script" path="res://loot_entry.gd" id="2"]
|
||||||
|
[ext_resource type="Resource" path="res://equipment/iron_sword.tres" id="3"]
|
||||||
|
[ext_resource type="Resource" path="res://equipment/leather_chest.tres" id="4"]
|
||||||
|
[ext_resource type="Resource" path="res://equipment/iron_helm.tres" id="5"]
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="entry_1"]
|
||||||
|
script = ExtResource("2")
|
||||||
|
item = ExtResource("3")
|
||||||
|
drop_chance = 0.15
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="entry_2"]
|
||||||
|
script = ExtResource("2")
|
||||||
|
item = ExtResource("4")
|
||||||
|
drop_chance = 0.1
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="entry_3"]
|
||||||
|
script = ExtResource("2")
|
||||||
|
item = ExtResource("5")
|
||||||
|
drop_chance = 0.1
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
script = ExtResource("1")
|
||||||
|
min_gold = 2
|
||||||
|
max_gold = 8
|
||||||
|
possible_drops = [SubResource("entry_1"), SubResource("entry_2"), SubResource("entry_3")]
|
||||||
28
loot_tables/skeleton_loot.tres
Normal file
28
loot_tables/skeleton_loot.tres
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
[gd_resource type="Resource" script_class="LootTable" format=3]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://loot_table.gd" id="1"]
|
||||||
|
[ext_resource type="Script" path="res://loot_entry.gd" id="2"]
|
||||||
|
[ext_resource type="Resource" path="res://equipment/steel_sword.tres" id="3"]
|
||||||
|
[ext_resource type="Resource" path="res://equipment/wooden_shield.tres" id="4"]
|
||||||
|
[ext_resource type="Resource" path="res://equipment/iron_helm.tres" id="5"]
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="entry_1"]
|
||||||
|
script = ExtResource("2")
|
||||||
|
item = ExtResource("3")
|
||||||
|
drop_chance = 0.1
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="entry_2"]
|
||||||
|
script = ExtResource("2")
|
||||||
|
item = ExtResource("4")
|
||||||
|
drop_chance = 0.12
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="entry_3"]
|
||||||
|
script = ExtResource("2")
|
||||||
|
item = ExtResource("5")
|
||||||
|
drop_chance = 0.15
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
script = ExtResource("1")
|
||||||
|
min_gold = 5
|
||||||
|
max_gold = 15
|
||||||
|
possible_drops = [SubResource("entry_1"), SubResource("entry_2"), SubResource("entry_3")]
|
||||||
118
loot_window.gd
Normal file
118
loot_window.gd
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
# LootWindow.gd
|
||||||
|
# Zeigt Loot eines besiegten Gegners an und lässt Spieler Items aufheben
|
||||||
|
extends CanvasLayer
|
||||||
|
|
||||||
|
var player = null
|
||||||
|
var current_loot: Dictionary = {} # {"gold": int, "items": [Equipment]}
|
||||||
|
var loot_world_position: Vector3 = Vector3.ZERO
|
||||||
|
var panel_visible = false
|
||||||
|
|
||||||
|
const LOOT_PICKUP_RANGE = 5.0
|
||||||
|
|
||||||
|
@onready var panel = $Panel
|
||||||
|
@onready var gold_label = $Panel/VBoxContainer/GoldLabel
|
||||||
|
@onready var item_list = $Panel/VBoxContainer/ScrollContainer/ItemList
|
||||||
|
@onready var loot_all_button = $Panel/VBoxContainer/LootAllButton
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
panel.visible = false
|
||||||
|
loot_all_button.pressed.connect(_on_loot_all)
|
||||||
|
|
||||||
|
func setup(p):
|
||||||
|
player = p
|
||||||
|
|
||||||
|
# Loot anzeigen
|
||||||
|
func show_loot(loot: Dictionary, world_pos: Vector3):
|
||||||
|
current_loot = loot
|
||||||
|
loot_world_position = world_pos
|
||||||
|
_refresh_display()
|
||||||
|
panel_visible = true
|
||||||
|
panel.visible = true
|
||||||
|
|
||||||
|
func hide_loot():
|
||||||
|
panel_visible = false
|
||||||
|
panel.visible = false
|
||||||
|
current_loot = {}
|
||||||
|
|
||||||
|
func _refresh_display():
|
||||||
|
# Gold anzeigen
|
||||||
|
if current_loot.get("gold", 0) > 0:
|
||||||
|
gold_label.text = str(current_loot["gold"]) + " Gold"
|
||||||
|
gold_label.visible = true
|
||||||
|
else:
|
||||||
|
gold_label.visible = false
|
||||||
|
|
||||||
|
# Items anzeigen
|
||||||
|
for child in item_list.get_children():
|
||||||
|
child.queue_free()
|
||||||
|
|
||||||
|
var items = current_loot.get("items", [])
|
||||||
|
for i in range(items.size()):
|
||||||
|
var item = items[i]
|
||||||
|
var button = Button.new()
|
||||||
|
button.text = item.item_name + " (" + Equipment.get_slot_name(item.slot) + ")"
|
||||||
|
button.modulate = Equipment.get_rarity_color(item.rarity)
|
||||||
|
button.pressed.connect(_on_loot_item.bind(i))
|
||||||
|
button.tooltip_text = _get_item_tooltip(item)
|
||||||
|
item_list.add_child(button)
|
||||||
|
|
||||||
|
# Wenn kein Loot mehr da, Fenster schließen
|
||||||
|
if current_loot.get("gold", 0) <= 0 and items.size() == 0:
|
||||||
|
hide_loot()
|
||||||
|
|
||||||
|
# Einzelnes Item aufheben
|
||||||
|
func _on_loot_item(index: int):
|
||||||
|
if player == null:
|
||||||
|
return
|
||||||
|
|
||||||
|
var items = current_loot.get("items", [])
|
||||||
|
if index >= items.size():
|
||||||
|
return
|
||||||
|
|
||||||
|
var item = items[index]
|
||||||
|
if player.inventory.add_item(item):
|
||||||
|
items.remove_at(index)
|
||||||
|
_refresh_display()
|
||||||
|
|
||||||
|
# Alles aufheben
|
||||||
|
func _on_loot_all():
|
||||||
|
if player == null:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Gold aufheben
|
||||||
|
var gold = current_loot.get("gold", 0)
|
||||||
|
if gold > 0:
|
||||||
|
player.inventory.add_gold(gold)
|
||||||
|
current_loot["gold"] = 0
|
||||||
|
|
||||||
|
# Items aufheben
|
||||||
|
var items = current_loot.get("items", [])
|
||||||
|
var remaining = []
|
||||||
|
for item in items:
|
||||||
|
if not player.inventory.add_item(item):
|
||||||
|
remaining.append(item) # Inventar voll
|
||||||
|
current_loot["items"] = remaining
|
||||||
|
|
||||||
|
_refresh_display()
|
||||||
|
|
||||||
|
func _get_item_tooltip(item: Equipment) -> String:
|
||||||
|
var tooltip = item.item_name + "\n"
|
||||||
|
tooltip += Equipment.get_slot_name(item.slot) + "\n"
|
||||||
|
|
||||||
|
if item.slot == Equipment.Slot.WEAPON:
|
||||||
|
tooltip += "Schaden: " + str(item.min_damage) + "-" + str(item.max_damage) + "\n"
|
||||||
|
tooltip += "Tempo: " + str(item.attack_speed) + "s\n"
|
||||||
|
if item.armor > 0:
|
||||||
|
tooltip += "Rüstung: +" + str(item.armor) + "\n"
|
||||||
|
if item.strength > 0:
|
||||||
|
tooltip += "Stärke: +" + str(item.strength) + "\n"
|
||||||
|
if item.agility > 0:
|
||||||
|
tooltip += "Beweglichkeit: +" + str(item.agility) + "\n"
|
||||||
|
if item.intelligence > 0:
|
||||||
|
tooltip += "Intelligenz: +" + str(item.intelligence) + "\n"
|
||||||
|
if item.stamina > 0:
|
||||||
|
tooltip += "Ausdauer: +" + str(item.stamina) + "\n"
|
||||||
|
if item.haste > 0:
|
||||||
|
tooltip += "Tempo: +" + str(int(item.haste * 100)) + "%\n"
|
||||||
|
|
||||||
|
return tooltip
|
||||||
61
loot_window.tscn
Normal file
61
loot_window.tscn
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
[gd_scene format=3 uid="uid://loot_window"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://loot_window.gd" id="1_loot"]
|
||||||
|
|
||||||
|
[node name="LootWindow" type="CanvasLayer"]
|
||||||
|
script = ExtResource("1_loot")
|
||||||
|
|
||||||
|
[node name="Panel" type="Panel" parent="."]
|
||||||
|
anchors_preset = 7
|
||||||
|
anchor_left = 0.5
|
||||||
|
anchor_top = 1.0
|
||||||
|
anchor_right = 0.5
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = -130.0
|
||||||
|
offset_top = -350.0
|
||||||
|
offset_right = 130.0
|
||||||
|
offset_bottom = -150.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 0
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="Panel"]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = 8.0
|
||||||
|
offset_top = 8.0
|
||||||
|
offset_right = -8.0
|
||||||
|
offset_bottom = -8.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
theme_override_constants/separation = 6
|
||||||
|
|
||||||
|
[node name="Title" type="Label" parent="Panel/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_font_sizes/font_size = 16
|
||||||
|
text = "Beute"
|
||||||
|
horizontal_alignment = 1
|
||||||
|
|
||||||
|
[node name="HSeparator" type="HSeparator" parent="Panel/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="GoldLabel" type="Label" parent="Panel/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_font_sizes/font_size = 14
|
||||||
|
theme_override_colors/font_color = Color(1, 0.85, 0, 1)
|
||||||
|
text = "0 Gold"
|
||||||
|
|
||||||
|
[node name="ScrollContainer" type="ScrollContainer" parent="Panel/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
|
||||||
|
[node name="ItemList" type="VBoxContainer" parent="Panel/VBoxContainer/ScrollContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
theme_override_constants/separation = 4
|
||||||
|
|
||||||
|
[node name="LootAllButton" type="Button" parent="Panel/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Alles aufheben"
|
||||||
11
player.gd
11
player.gd
|
|
@ -61,6 +61,7 @@ const HEAVY_STRIKE_RANGE = 4.0
|
||||||
@onready var hud = $HUD
|
@onready var hud = $HUD
|
||||||
@onready var character_panel = $CharacterPanel
|
@onready var character_panel = $CharacterPanel
|
||||||
@onready var inventory_panel = $InventoryPanel
|
@onready var inventory_panel = $InventoryPanel
|
||||||
|
@onready var loot_window = $LootWindow
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
# Stats aus Klasse berechnen
|
# Stats aus Klasse berechnen
|
||||||
|
|
@ -80,6 +81,12 @@ func _ready():
|
||||||
# Inventar Panel initialisieren
|
# Inventar Panel initialisieren
|
||||||
inventory_panel.setup(self)
|
inventory_panel.setup(self)
|
||||||
|
|
||||||
|
# Loot Window initialisieren
|
||||||
|
loot_window.setup(self)
|
||||||
|
|
||||||
|
# Gold im HUD aktualisieren wenn sich Gold ändert
|
||||||
|
inventory.gold_changed.connect(func(amount): hud.update_gold(amount))
|
||||||
|
|
||||||
# Stats basierend auf Klasse und Level berechnen
|
# Stats basierend auf Klasse und Level berechnen
|
||||||
func _calculate_stats():
|
func _calculate_stats():
|
||||||
if character_class == null:
|
if character_class == null:
|
||||||
|
|
@ -251,6 +258,10 @@ func heal(amount):
|
||||||
current_hp = clamp(current_hp + amount, 0, max_hp)
|
current_hp = clamp(current_hp + amount, 0, max_hp)
|
||||||
hud.update_health(current_hp, max_hp)
|
hud.update_health(current_hp, max_hp)
|
||||||
|
|
||||||
|
# Loot empfangen und Fenster anzeigen
|
||||||
|
func receive_loot(loot: Dictionary, world_pos: Vector3):
|
||||||
|
loot_window.show_loot(loot, world_pos)
|
||||||
|
|
||||||
func die():
|
func die():
|
||||||
print("Spieler gestorben!")
|
print("Spieler gestorben!")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
[ext_resource type="PackedScene" uid="uid://bej3excyoxrdh" path="res://hud.tscn" id="4_hqtel"]
|
[ext_resource type="PackedScene" uid="uid://bej3excyoxrdh" path="res://hud.tscn" id="4_hqtel"]
|
||||||
[ext_resource type="PackedScene" uid="uid://character_panel" path="res://character_panel.tscn" id="5_char_panel"]
|
[ext_resource type="PackedScene" uid="uid://character_panel" path="res://character_panel.tscn" id="5_char_panel"]
|
||||||
[ext_resource type="PackedScene" uid="uid://inventory_panel" path="res://inventory_panel.tscn" id="6_inv_panel"]
|
[ext_resource type="PackedScene" uid="uid://inventory_panel" path="res://inventory_panel.tscn" id="6_inv_panel"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://loot_window" path="res://loot_window.tscn" id="7_loot_win"]
|
||||||
|
|
||||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_4flbx"]
|
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_4flbx"]
|
||||||
radius = 0.6
|
radius = 0.6
|
||||||
|
|
@ -33,3 +34,5 @@ transform = Transform3D(2, 0, 0, 0, 1.8126155, 0.84523654, 0, -0.84523654, 1.812
|
||||||
[node name="CharacterPanel" parent="." instance=ExtResource("5_char_panel")]
|
[node name="CharacterPanel" parent="." instance=ExtResource("5_char_panel")]
|
||||||
|
|
||||||
[node name="InventoryPanel" parent="." instance=ExtResource("6_inv_panel")]
|
[node name="InventoryPanel" parent="." instance=ExtResource("6_inv_panel")]
|
||||||
|
|
||||||
|
[node name="LootWindow" parent="." instance=ExtResource("7_loot_win")]
|
||||||
|
|
|
||||||
11
world.gd
11
world.gd
|
|
@ -10,6 +10,9 @@ const RESPAWN_TIME = 5.0
|
||||||
const STARTER_WEAPON = preload("res://equipment/iron_sword.tres")
|
const STARTER_WEAPON = preload("res://equipment/iron_sword.tres")
|
||||||
const STARTER_CHEST = preload("res://equipment/leather_chest.tres")
|
const STARTER_CHEST = preload("res://equipment/leather_chest.tres")
|
||||||
|
|
||||||
|
# Loot Tables
|
||||||
|
const GOBLIN_LOOT = preload("res://loot_tables/goblin_loot.tres")
|
||||||
|
|
||||||
@onready var player = $Player
|
@onready var player = $Player
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
|
|
@ -39,10 +42,18 @@ func _on_class_selected(character_class: CharacterClass):
|
||||||
func _setup_enemy(enemy):
|
func _setup_enemy(enemy):
|
||||||
if enemy and player:
|
if enemy and player:
|
||||||
enemy.target = player
|
enemy.target = player
|
||||||
|
if enemy.loot_table == null:
|
||||||
|
enemy.loot_table = GOBLIN_LOOT
|
||||||
enemy.enemy_died.connect(_on_enemy_died)
|
enemy.enemy_died.connect(_on_enemy_died)
|
||||||
|
enemy.enemy_dropped_loot.connect(_on_enemy_dropped_loot)
|
||||||
else:
|
else:
|
||||||
print("Fehler: Player oder Enemy nicht gefunden!")
|
print("Fehler: Player oder Enemy nicht gefunden!")
|
||||||
|
|
||||||
|
# Loot-Drop an Spieler weiterleiten
|
||||||
|
func _on_enemy_dropped_loot(loot: Dictionary, world_pos: Vector3):
|
||||||
|
if player:
|
||||||
|
player.receive_loot(loot, world_pos)
|
||||||
|
|
||||||
# Gegner gestorben: Nach 5 Sekunden respawnen
|
# Gegner gestorben: Nach 5 Sekunden respawnen
|
||||||
func _on_enemy_died(spawn_position: Vector3, _xp_reward: int):
|
func _on_enemy_died(spawn_position: Vector3, _xp_reward: int):
|
||||||
print("Respawn in ", RESPAWN_TIME, " Sekunden...")
|
print("Respawn in ", RESPAWN_TIME, " Sekunden...")
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue