Magier-Kampfsystem, Castbar, Inventar-Drag und Gegner-Aggro
- Zauberstab als eigener Fernkampf-Skill (20m, magisch, exklusiv mit Autoattack) - Frostblitz mit 1.5s Castzeit und Castbar (mittig über Aktionsleiste) - Cast wird durch Bewegung, Springen oder Schaden unterbrochen - Holzstab als Magier-Startwaffe (+3 INT) - Frostblitz-Icon (SVG) - Skills klassenabhängig: Magier=Zauberstab+Frostblitz, Krieger/Schurke=Heavy Strike - Inventar: Drag & Drop zum Umordnen mit gelbem Highlight - Gegner aggrot sofort bei Schadenstreffer (nicht nur in Aggro-Range) - Inventar: swap_items/move_items Funktionen Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d029a37e7f
commit
8f0ac2227e
13 changed files with 574 additions and 41 deletions
|
|
@ -16,3 +16,6 @@ strength_per_level = 1.0
|
|||
agility_per_level = 1.5
|
||||
intelligence_per_level = 3.0
|
||||
stamina_per_level = 1.5
|
||||
unarmed_min_damage = 2
|
||||
unarmed_max_damage = 5
|
||||
unarmed_attack_speed = 2.0
|
||||
|
|
|
|||
7
enemy.gd
7
enemy.gd
|
|
@ -104,10 +104,15 @@ func show_health():
|
|||
func hide_health():
|
||||
health_label.visible = false
|
||||
|
||||
# Schaden nehmen und Label aktualisieren (alte Methode für Kompatibilität)
|
||||
# Schaden nehmen und Label aktualisieren
|
||||
func take_damage(amount):
|
||||
current_hp -= amount
|
||||
_update_label()
|
||||
# Aggro bei Schaden — sofort angreifen
|
||||
if current_state == State.PATROL:
|
||||
current_state = State.CHASE
|
||||
is_waiting = false
|
||||
print("Gegner wurde angegriffen und verfolgt den Spieler!")
|
||||
if current_hp <= 0:
|
||||
die()
|
||||
|
||||
|
|
|
|||
14
equipment/wooden_staff.tres
Normal file
14
equipment/wooden_staff.tres
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
[gd_resource type="Resource" script_class="Equipment" format=3 uid="uid://wooden_staff_01"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://re0xiie1udfq" path="res://equipment.gd" id="1_equipment"]
|
||||
[ext_resource type="Texture2D" path="res://icons/wooden_staff_icon.svg" id="2_icon"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_equipment")
|
||||
item_name = "Holzstab"
|
||||
intelligence = 3
|
||||
min_damage = 2
|
||||
max_damage = 5
|
||||
attack_speed = 2.0
|
||||
weapon_range = 3.0
|
||||
icon = ExtResource("2_icon")
|
||||
92
hud.gd
92
hud.gd
|
|
@ -42,6 +42,11 @@ var slot_stack_labels = [] # Label für Stack-Anzahl
|
|||
var resource_bar: ProgressBar
|
||||
var resource_label: Label
|
||||
|
||||
# Castbar
|
||||
var castbar: ProgressBar
|
||||
var castbar_label: Label
|
||||
var castbar_container: PanelContainer
|
||||
|
||||
func _ready():
|
||||
_create_level_ui()
|
||||
|
||||
|
|
@ -147,10 +152,10 @@ func _input(event):
|
|||
|
||||
func _end_actionbar_drag():
|
||||
var drop_slot = get_slot_at_position(get_viewport().get_mouse_position())
|
||||
if drop_slot >= 2 and drop_slot <= 8 and drop_slot != drag_from_slot:
|
||||
if drop_slot >= 0 and drop_slot <= 8 and drop_slot != drag_from_slot:
|
||||
# Auf anderen Slot verschoben -> swap
|
||||
slot_drag_swapped.emit(drag_from_slot, drop_slot)
|
||||
elif drop_slot < 0 or drop_slot < 2 or drop_slot > 8:
|
||||
elif drop_slot < 0 or drop_slot > 8:
|
||||
# Außerhalb gedroppt -> aus Leiste entfernen
|
||||
slot_drag_removed.emit(drag_from_slot)
|
||||
# Aufräumen
|
||||
|
|
@ -253,6 +258,9 @@ func _create_level_ui():
|
|||
gold_label.text = "0 Gold"
|
||||
control.add_child(gold_label)
|
||||
|
||||
# Castbar — direkt über der Aktionsleiste positioniert
|
||||
_create_castbar()
|
||||
|
||||
# Gold aktualisieren
|
||||
func update_gold(amount: int):
|
||||
if gold_label:
|
||||
|
|
@ -340,7 +348,7 @@ func update_drag_hover(mouse_pos: Vector2):
|
|||
# Alten Highlight entfernen
|
||||
_clear_drag_highlight()
|
||||
# Neuen Highlight setzen (nur Slots 2-8)
|
||||
if hovered >= 2 and hovered <= 8:
|
||||
if hovered >= 0 and hovered <= 8:
|
||||
drag_highlight_slot = hovered
|
||||
var style = StyleBoxFlat.new()
|
||||
style.bg_color = Color(0.15, 0.15, 0.15)
|
||||
|
|
@ -361,3 +369,81 @@ func get_slot_at_position(mouse_pos: Vector2) -> int:
|
|||
if rect.has_point(mouse_pos):
|
||||
return i
|
||||
return -1
|
||||
|
||||
func _create_castbar():
|
||||
# Eigene CanvasLayer für die Castbar
|
||||
var castbar_layer = CanvasLayer.new()
|
||||
castbar_layer.name = "CastbarLayer"
|
||||
castbar_layer.layer = 10
|
||||
add_child(castbar_layer)
|
||||
|
||||
castbar_container = PanelContainer.new()
|
||||
castbar_container.name = "CastbarContainer"
|
||||
castbar_container.visible = false
|
||||
castbar_container.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
|
||||
var style = StyleBoxFlat.new()
|
||||
style.bg_color = Color(0.1, 0.1, 0.1, 0.85)
|
||||
style.set_border_width_all(2)
|
||||
style.border_color = Color(0.6, 0.6, 0.6)
|
||||
style.set_corner_radius_all(4)
|
||||
castbar_container.add_theme_stylebox_override("panel", style)
|
||||
|
||||
var vbox = VBoxContainer.new()
|
||||
vbox.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
castbar_container.add_child(vbox)
|
||||
|
||||
castbar_label = Label.new()
|
||||
castbar_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
castbar_label.add_theme_font_size_override("font_size", 13)
|
||||
castbar_label.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
vbox.add_child(castbar_label)
|
||||
|
||||
castbar = ProgressBar.new()
|
||||
castbar.custom_minimum_size = Vector2(300, 16)
|
||||
castbar.show_percentage = false
|
||||
castbar.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
|
||||
var fill = StyleBoxFlat.new()
|
||||
fill.bg_color = Color(1.0, 0.7, 0.0, 1.0)
|
||||
fill.set_corner_radius_all(2)
|
||||
castbar.add_theme_stylebox_override("fill", fill)
|
||||
|
||||
var bg = StyleBoxFlat.new()
|
||||
bg.bg_color = Color(0.2, 0.2, 0.2, 1.0)
|
||||
bg.set_corner_radius_all(2)
|
||||
castbar.add_theme_stylebox_override("background", bg)
|
||||
|
||||
vbox.add_child(castbar)
|
||||
castbar_layer.add_child(castbar_container)
|
||||
|
||||
# Castbar anzeigen
|
||||
func show_castbar(spell_name: String, cast_time: float):
|
||||
if castbar_container == null:
|
||||
return
|
||||
# Spell-Name übersetzen
|
||||
var display_name = spell_name
|
||||
match spell_name:
|
||||
"frostbolt": display_name = "Frostblitz"
|
||||
castbar_label.text = display_name + " (" + "%.1f" % cast_time + "s)"
|
||||
castbar.max_value = cast_time
|
||||
castbar.value = 0
|
||||
# Mittig über der Aktionsleiste positionieren
|
||||
var viewport_size = get_viewport().get_visible_rect().size
|
||||
castbar_container.position = Vector2(viewport_size.x / 2 - 160, viewport_size.y - 120)
|
||||
castbar_container.visible = true
|
||||
|
||||
# Castbar Fortschritt aktualisieren
|
||||
func update_castbar(elapsed: float, total: float):
|
||||
if castbar == null:
|
||||
return
|
||||
castbar.value = elapsed
|
||||
var remaining = total - elapsed
|
||||
if remaining < 0:
|
||||
remaining = 0
|
||||
castbar_label.text = castbar_label.text.split("(")[0].strip_edges() + " (%.1f" % remaining + "s)"
|
||||
|
||||
# Castbar verstecken
|
||||
func hide_castbar():
|
||||
if castbar_container:
|
||||
castbar_container.visible = false
|
||||
|
|
|
|||
14
icons/frostbolt_icon.svg
Normal file
14
icons/frostbolt_icon.svg
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
||||
<!-- Eisstrahl -->
|
||||
<polygon points="10,32 32,24 54,32 32,40" fill="#66CCFF" stroke="#3399DD" stroke-width="1.5"/>
|
||||
<!-- Eiskristall-Spitze -->
|
||||
<polygon points="54,32 62,32 58,26 58,38" fill="#99DDFF" stroke="#3399DD" stroke-width="1"/>
|
||||
<!-- Frost-Partikel -->
|
||||
<circle cx="20" cy="28" r="3" fill="white" opacity="0.7"/>
|
||||
<circle cx="38" cy="36" r="2.5" fill="white" opacity="0.6"/>
|
||||
<circle cx="28" cy="22" r="2" fill="white" opacity="0.5"/>
|
||||
<!-- Schneeflocke Mitte -->
|
||||
<line x1="32" y1="28" x2="32" y2="36" stroke="white" stroke-width="1.5" opacity="0.8"/>
|
||||
<line x1="28" y1="30" x2="36" y2="34" stroke="white" stroke-width="1.5" opacity="0.8"/>
|
||||
<line x1="28" y1="34" x2="36" y2="30" stroke="white" stroke-width="1.5" opacity="0.8"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 822 B |
43
icons/frostbolt_icon.svg.import
Normal file
43
icons/frostbolt_icon.svg.import
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://d3lnef1xxgol3"
|
||||
path="res://.godot/imported/frostbolt_icon.svg-97e9c6299dcf36b8065da5f6427efafe.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://icons/frostbolt_icon.svg"
|
||||
dest_files=["res://.godot/imported/frostbolt_icon.svg-97e9c6299dcf36b8065da5f6427efafe.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
14
icons/wooden_staff_icon.svg
Normal file
14
icons/wooden_staff_icon.svg
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
||||
<!-- Stab -->
|
||||
<line x1="20" y1="56" x2="38" y2="12" stroke="#8B6914" stroke-width="4" stroke-linecap="round"/>
|
||||
<!-- Kristall oben -->
|
||||
<polygon points="38,12 44,6 42,16 48,10" fill="#66CCFF" stroke="#3399DD" stroke-width="1"/>
|
||||
<polygon points="38,12 32,6 36,16 30,10" fill="#99DDFF" stroke="#3399DD" stroke-width="1"/>
|
||||
<!-- Glühen -->
|
||||
<circle cx="38" cy="10" r="6" fill="#66CCFF" opacity="0.3"/>
|
||||
<circle cx="38" cy="10" r="3" fill="white" opacity="0.5"/>
|
||||
<!-- Wicklung -->
|
||||
<line x1="25" y1="44" x2="29" y2="42" stroke="#C0A040" stroke-width="2"/>
|
||||
<line x1="26" y1="40" x2="30" y2="38" stroke="#C0A040" stroke-width="2"/>
|
||||
<line x1="27" y1="36" x2="31" y2="34" stroke="#C0A040" stroke-width="2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 787 B |
43
icons/wooden_staff_icon.svg.import
Normal file
43
icons/wooden_staff_icon.svg.import
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dts32a6fpdc84"
|
||||
path="res://.godot/imported/wooden_staff_icon.svg-9178c7c24ac6ded32a37ea646c50397f.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://icons/wooden_staff_icon.svg"
|
||||
dest_files=["res://.godot/imported/wooden_staff_icon.svg-9178c7c24ac6ded32a37ea646c50397f.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
33
inventory.gd
33
inventory.gd
|
|
@ -90,6 +90,39 @@ func get_item(index: int):
|
|||
return null
|
||||
return items[index]
|
||||
|
||||
# Zwei Items im Inventar tauschen
|
||||
func swap_items(index_a: int, index_b: int):
|
||||
if index_a < 0 or index_b < 0:
|
||||
return
|
||||
if index_a >= items.size() or index_b >= items.size():
|
||||
return
|
||||
var temp = items[index_a]
|
||||
items[index_a] = items[index_b]
|
||||
items[index_b] = temp
|
||||
inventory_changed.emit()
|
||||
|
||||
# Item an bestimmten Index verschieben (von aktuellem Platz)
|
||||
func move_item(from_index: int, to_index: int):
|
||||
if from_index < 0 or from_index >= items.size():
|
||||
return
|
||||
if to_index < 0 or to_index >= MAX_SLOTS:
|
||||
return
|
||||
if from_index == to_index:
|
||||
return
|
||||
if to_index < items.size():
|
||||
# Ziel belegt -> tauschen
|
||||
swap_items(from_index, to_index)
|
||||
else:
|
||||
# Ziel leer -> Item verschieben
|
||||
var item = items[from_index]
|
||||
items.remove_at(from_index)
|
||||
# Index anpassen falls nötig
|
||||
if to_index >= items.size():
|
||||
items.append(item)
|
||||
else:
|
||||
items.insert(to_index, item)
|
||||
inventory_changed.emit()
|
||||
|
||||
# Anzahl Items
|
||||
func item_count() -> int:
|
||||
return items.size()
|
||||
|
|
|
|||
|
|
@ -9,8 +9,10 @@ var player = null
|
|||
|
||||
# Drag & Drop
|
||||
var dragging = false
|
||||
var drag_item: Consumable = null
|
||||
var drag_item = null # Equipment oder Consumable
|
||||
var drag_from_index: int = -1 # Inventar-Index von dem gedraggt wird
|
||||
var drag_icon: TextureRect = null
|
||||
var drag_highlight_slot: int = -1 # Aktuell hervorgehobener Inventar-Slot
|
||||
|
||||
@onready var panel = $Panel
|
||||
@onready var gold_label = $Panel/VBoxContainer/Header/GoldLabel
|
||||
|
|
@ -68,6 +70,9 @@ func _create_slot(index: int) -> Panel:
|
|||
style.set_border_width_all(1)
|
||||
slot.add_theme_stylebox_override("panel", style)
|
||||
|
||||
# Alle Slots brauchen gui_input für Drop-Erkennung
|
||||
slot.gui_input.connect(_on_slot_input.bind(index))
|
||||
|
||||
# Item vorhanden?
|
||||
if player.inventory and index < player.inventory.item_count():
|
||||
var item = player.inventory.get_item(index)
|
||||
|
|
@ -85,6 +90,7 @@ func _create_slot(index: int) -> Panel:
|
|||
icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
|
||||
icon.custom_minimum_size = Vector2(SLOT_SIZE - 4, SLOT_SIZE - 4)
|
||||
icon.position = Vector2(2, 2)
|
||||
icon.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
slot.add_child(icon)
|
||||
else:
|
||||
# Fallback: Text
|
||||
|
|
@ -96,6 +102,7 @@ func _create_slot(index: int) -> Panel:
|
|||
if item is Equipment:
|
||||
label.modulate = Equipment.get_rarity_color(item.rarity)
|
||||
label.anchors_preset = Control.PRESET_FULL_RECT
|
||||
label.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
slot.add_child(label)
|
||||
|
||||
# Stack-Count für Consumables
|
||||
|
|
@ -107,25 +114,30 @@ func _create_slot(index: int) -> Panel:
|
|||
stack_label.add_theme_font_size_override("font_size", 11)
|
||||
stack_label.size = Vector2(SLOT_SIZE - 4, SLOT_SIZE - 4)
|
||||
stack_label.position = Vector2(0, 0)
|
||||
stack_label.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
slot.add_child(stack_label)
|
||||
|
||||
# Rahmen
|
||||
if item is Equipment:
|
||||
style.border_color = Equipment.get_rarity_color(item.rarity)
|
||||
elif item is Consumable:
|
||||
style.border_color = Color(0.3, 0.7, 0.3) # Grüner Rand für Consumables
|
||||
style.border_color = Color(0.3, 0.7, 0.3)
|
||||
style.set_border_width_all(2)
|
||||
|
||||
# Klick-Handler
|
||||
slot.gui_input.connect(_on_slot_clicked.bind(index, item))
|
||||
|
||||
# Tooltip
|
||||
slot.tooltip_text = _get_item_tooltip(item)
|
||||
|
||||
return slot
|
||||
|
||||
func _on_slot_clicked(event: InputEvent, index: int, item):
|
||||
func _on_slot_input(event: InputEvent, index: int):
|
||||
if event is InputEventMouseButton and event.pressed:
|
||||
var item = null
|
||||
if player.inventory and index < player.inventory.item_count():
|
||||
item = player.inventory.get_item(index)
|
||||
|
||||
if item == null:
|
||||
return
|
||||
|
||||
if item is Equipment:
|
||||
if event.button_index == MOUSE_BUTTON_RIGHT:
|
||||
# Rechtsklick auf Equipment: Anlegen
|
||||
|
|
@ -135,6 +147,9 @@ func _on_slot_clicked(event: InputEvent, index: int, item):
|
|||
if old_item:
|
||||
player.inventory.add_item(old_item)
|
||||
_refresh_inventory()
|
||||
elif event.button_index == MOUSE_BUTTON_LEFT:
|
||||
# Linksklick: Drag starten
|
||||
_start_drag(item, index)
|
||||
elif item is Consumable:
|
||||
if event.button_index == MOUSE_BUTTON_RIGHT:
|
||||
# Rechtsklick auf Consumable: Direkt benutzen
|
||||
|
|
@ -146,15 +161,18 @@ func _on_slot_clicked(event: InputEvent, index: int, item):
|
|||
player._update_action_bar_stacks()
|
||||
elif event.button_index == MOUSE_BUTTON_LEFT:
|
||||
# Linksklick: Drag starten
|
||||
_start_drag(item)
|
||||
_start_drag(item, index)
|
||||
|
||||
# Drag & Drop System
|
||||
func _start_drag(item: Consumable):
|
||||
func _start_drag(item, index: int):
|
||||
dragging = true
|
||||
drag_item = item
|
||||
drag_from_index = index
|
||||
# Icon am Mauszeiger erstellen
|
||||
var tex = item.icon if item.icon else null
|
||||
drag_icon = TextureRect.new()
|
||||
drag_icon.texture = item.icon
|
||||
if tex:
|
||||
drag_icon.texture = tex
|
||||
drag_icon.custom_minimum_size = Vector2(40, 40)
|
||||
drag_icon.size = Vector2(40, 40)
|
||||
drag_icon.expand_mode = TextureRect.EXPAND_FIT_WIDTH_PROPORTIONAL
|
||||
|
|
@ -174,9 +192,12 @@ func _start_drag(item: Consumable):
|
|||
func _process(_delta):
|
||||
if dragging and drag_icon:
|
||||
drag_icon.position = get_viewport().get_mouse_position() - Vector2(20, 20)
|
||||
var mouse_pos = get_viewport().get_mouse_position()
|
||||
# HUD Slots highlighten
|
||||
if player and player.hud:
|
||||
player.hud.update_drag_hover(get_viewport().get_mouse_position())
|
||||
player.hud.update_drag_hover(mouse_pos)
|
||||
# Inventar-Slots highlighten
|
||||
_update_inventory_hover(mouse_pos)
|
||||
|
||||
func _input(event):
|
||||
if not dragging:
|
||||
|
|
@ -188,20 +209,80 @@ func _input(event):
|
|||
func _end_drag():
|
||||
if not dragging:
|
||||
return
|
||||
# Prüfen ob über einem Action-Slot
|
||||
var mouse_pos = get_viewport().get_mouse_position()
|
||||
|
||||
# Prüfen ob über einem Inventar-Slot
|
||||
var inv_slot = _get_inventory_slot_at(mouse_pos)
|
||||
if inv_slot >= 0 and inv_slot != drag_from_index:
|
||||
# Innerhalb Inventar verschieben/tauschen
|
||||
player.inventory.move_item(drag_from_index, inv_slot)
|
||||
else:
|
||||
# Prüfen ob über einem Action-Slot (nur Consumables)
|
||||
if player and player.hud:
|
||||
var action_slot = player.hud.get_slot_at_position(mouse_pos)
|
||||
if action_slot >= 0 and action_slot <= 8 and drag_item:
|
||||
if drag_item is Consumable:
|
||||
player.assign_to_action_bar(action_slot, drag_item)
|
||||
print(drag_item.item_name + " auf Aktionsleiste Slot " + str(action_slot + 1) + " gelegt")
|
||||
|
||||
# HUD Highlight deaktivieren
|
||||
if player and player.hud:
|
||||
var slot_index = player.hud.get_slot_at_position(get_viewport().get_mouse_position())
|
||||
if slot_index >= 2 and slot_index <= 8 and drag_item:
|
||||
player.assign_to_action_bar(slot_index, drag_item)
|
||||
print(drag_item.item_name + " auf Slot " + str(slot_index + 1) + " gelegt")
|
||||
player.hud.set_drag_active(false)
|
||||
# Inventar Highlight entfernen
|
||||
_clear_inventory_highlight()
|
||||
# Aufräumen
|
||||
if drag_icon:
|
||||
var drag_layer = drag_icon.get_parent()
|
||||
drag_layer.queue_free() # Entfernt DragLayer + Icon
|
||||
drag_layer.queue_free()
|
||||
drag_icon = null
|
||||
dragging = false
|
||||
drag_item = null
|
||||
drag_from_index = -1
|
||||
|
||||
# Inventar-Slot unter Mausposition finden
|
||||
func _get_inventory_slot_at(mouse_pos: Vector2) -> int:
|
||||
for i in range(item_grid.get_child_count()):
|
||||
var slot = item_grid.get_child(i)
|
||||
var rect = slot.get_global_rect()
|
||||
if rect.has_point(mouse_pos):
|
||||
return i
|
||||
return -1
|
||||
|
||||
# Inventar-Slot Highlight während Drag
|
||||
func _update_inventory_hover(mouse_pos: Vector2):
|
||||
var hovered = _get_inventory_slot_at(mouse_pos)
|
||||
if hovered == drag_highlight_slot:
|
||||
return
|
||||
_clear_inventory_highlight()
|
||||
if hovered >= 0 and hovered != drag_from_index:
|
||||
drag_highlight_slot = hovered
|
||||
var slot = item_grid.get_child(hovered)
|
||||
var style = StyleBoxFlat.new()
|
||||
style.bg_color = Color(0.15, 0.15, 0.15)
|
||||
style.border_color = Color(1, 0.9, 0, 1) # Gelber Rand
|
||||
style.set_border_width_all(3)
|
||||
slot.add_theme_stylebox_override("panel", style)
|
||||
|
||||
func _clear_inventory_highlight():
|
||||
if drag_highlight_slot >= 0 and drag_highlight_slot < item_grid.get_child_count():
|
||||
# Style zurücksetzen
|
||||
var slot = item_grid.get_child(drag_highlight_slot)
|
||||
var item = null
|
||||
if player.inventory and drag_highlight_slot < player.inventory.item_count():
|
||||
item = player.inventory.get_item(drag_highlight_slot)
|
||||
var style = StyleBoxFlat.new()
|
||||
style.bg_color = Color(0.15, 0.15, 0.15)
|
||||
if item is Equipment:
|
||||
style.border_color = Equipment.get_rarity_color(item.rarity)
|
||||
style.set_border_width_all(2)
|
||||
elif item is Consumable:
|
||||
style.border_color = Color(0.3, 0.7, 0.3)
|
||||
style.set_border_width_all(2)
|
||||
else:
|
||||
style.border_color = Color(0.3, 0.3, 0.3)
|
||||
style.set_border_width_all(1)
|
||||
slot.add_theme_stylebox_override("panel", style)
|
||||
drag_highlight_slot = -1
|
||||
|
||||
func _get_item_tooltip(item) -> String:
|
||||
if item is Consumable:
|
||||
|
|
@ -217,7 +298,7 @@ func _get_consumable_tooltip(item: Consumable) -> String:
|
|||
tooltip += item.get_effect_text() + "\n"
|
||||
tooltip += "Cooldown: " + str(item.cooldown) + "s\n"
|
||||
tooltip += "Anzahl: " + str(item.stack_size) + "/" + str(item.max_stack) + "\n"
|
||||
tooltip += "\n[Rechtsklick: Benutzen]\n[Shift+Linksklick: Auf Leiste legen]"
|
||||
tooltip += "\n[Rechtsklick: Benutzen]\n[Linksklick: Ziehen]"
|
||||
return tooltip
|
||||
|
||||
func _get_equipment_tooltip(item: Equipment) -> String:
|
||||
|
|
|
|||
217
player.gd
217
player.gd
|
|
@ -30,13 +30,19 @@ var current_resource = 0
|
|||
var target = null # Aktuell markierter Gegner
|
||||
|
||||
# Aktionsleiste: Skills (String) oder Consumables in Slots (0-8)
|
||||
# Skills: "autoattack", "heavy_strike" — frei verschiebbar
|
||||
var action_bar_items: Array = ["autoattack", "heavy_strike", null, null, null, null, null, null, null]
|
||||
var action_bar_items: Array = [null, null, null, null, null, null, null, null, null]
|
||||
|
||||
# Alle verfügbaren Skills (für Fähigkeiten-Panel)
|
||||
var available_skills: Array = [
|
||||
{"id": "autoattack", "name": "Autoattack", "icon": "res://icons/autoattack_icon.svg", "description": "Greift das Ziel automatisch an.\nSchaden: Waffenschaden + Main-Stat"},
|
||||
{"id": "heavy_strike", "name": "Heavy Strike", "icon": "res://icons/heavy_strike_icon.svg", "description": "Starker Hieb mit 3s Cooldown.\nSchaden: 10-15 + Main-Stat"},
|
||||
# Alle verfügbaren Skills (für Fähigkeiten-Panel) — wird klassenabhängig befüllt
|
||||
var available_skills: Array = []
|
||||
|
||||
# Skill-Definitionen pro Klasse
|
||||
const AUTOATTACK_SKILL = {"id": "autoattack", "name": "Autoattack", "icon": "res://icons/autoattack_icon.svg", "description": "Greift das Ziel im Nahkampf an.\nSchaden: Waffenschaden + Main-Stat"}
|
||||
const MELEE_SKILLS = [
|
||||
{"id": "heavy_strike", "name": "Heavy Strike", "icon": "res://icons/heavy_strike_icon.svg", "description": "Starker Hieb mit 3s Cooldown.\nSchaden: 10-15 + Main-Stat\nReichweite: 4.0"},
|
||||
]
|
||||
const MAGE_SKILLS = [
|
||||
{"id": "wand", "name": "Zauberstab", "icon": "res://icons/autoattack_icon.svg", "description": "Magischer Fernkampfangriff.\nSchaden: Waffenschaden + INT\nReichweite: 20.0\nIgnoriert Rüstung\nDeaktiviert Autoattack"},
|
||||
{"id": "frostbolt", "name": "Frostblitz", "icon": "res://icons/frostbolt_icon.svg", "description": "Magischer Fernkampfangriff mit Castzeit.\nSchaden: 12-20 + INT\nManakosten: 20\nReichweite: 20.0\nCastzeit: 1.5s\nCooldown: 2.5s"},
|
||||
]
|
||||
var potion_cooldown: float = 0.0
|
||||
const POTION_COOLDOWN_TIME = 1.0
|
||||
|
|
@ -63,6 +69,10 @@ var haste: float = 0.0 # Angriffsgeschwindigkeits-Bonus (0.1 = 10% schneller)
|
|||
# Autoattack System
|
||||
var autoattack_active = false # Ob Autoattack aktiv ist
|
||||
|
||||
# Zauberstab System (Magier-Fernkampf, exklusiv mit Autoattack)
|
||||
var wand_active = false
|
||||
const WAND_RANGE = 20.0
|
||||
|
||||
# Skills System - individuelle Cooldowns (zusätzlich zum GCD)
|
||||
var heavy_strike_cooldown = 0.0
|
||||
const HEAVY_STRIKE_DAMAGE_MIN = 10
|
||||
|
|
@ -70,6 +80,20 @@ const HEAVY_STRIKE_DAMAGE_MAX = 15
|
|||
const HEAVY_STRIKE_COOLDOWN = 3.0
|
||||
const HEAVY_STRIKE_RANGE = 4.0
|
||||
|
||||
var frostbolt_cooldown = 0.0
|
||||
const FROSTBOLT_DAMAGE_MIN = 12
|
||||
const FROSTBOLT_DAMAGE_MAX = 20
|
||||
const FROSTBOLT_COOLDOWN = 2.5
|
||||
const FROSTBOLT_RANGE = 20.0
|
||||
const FROSTBOLT_MANA_COST = 20
|
||||
const FROSTBOLT_CAST_TIME = 1.5
|
||||
|
||||
# Cast-System
|
||||
var is_casting = false
|
||||
var cast_time_remaining = 0.0
|
||||
var cast_time_total = 0.0
|
||||
var cast_spell_id = "" # Welcher Zauber gecastet wird
|
||||
|
||||
@onready var camera_pivot = $CameraPivot
|
||||
@onready var camera = $CameraPivot/Camera3D
|
||||
@onready var hud = $HUD
|
||||
|
|
@ -88,6 +112,8 @@ func _ready():
|
|||
hud.update_resource(current_resource, max_resource, get_resource_name())
|
||||
hud.update_level(level, current_xp, xp_to_next_level)
|
||||
hud.set_active_slot(0)
|
||||
# Skills klassenabhängig aufbauen
|
||||
_init_class_skills()
|
||||
# Aktionsleiste initialisieren (Skills + Items)
|
||||
for i in range(9):
|
||||
_refresh_action_slot(i)
|
||||
|
|
@ -138,6 +164,21 @@ func _calculate_stats():
|
|||
|
||||
print("Stats berechnet - STR: ", strength, " AGI: ", agility, " INT: ", intelligence, " STA: ", stamina, " ARM: ", armor, " HP: ", max_hp, " RES: ", max_resource)
|
||||
|
||||
# Skills klassenabhängig aufbauen
|
||||
func _init_class_skills():
|
||||
available_skills = [AUTOATTACK_SKILL.duplicate()]
|
||||
if character_class and character_class.resource_type == CharacterClass.ResourceType.MANA:
|
||||
# Magier: Autoattack + Zauberstab + Frostblitz
|
||||
available_skills.append_array(MAGE_SKILLS.duplicate(true))
|
||||
action_bar_items[0] = "wand"
|
||||
action_bar_items[1] = "frostbolt"
|
||||
action_bar_items[2] = "autoattack"
|
||||
else:
|
||||
# Krieger/Schurke: Autoattack + Heavy Strike
|
||||
available_skills.append_array(MELEE_SKILLS.duplicate(true))
|
||||
action_bar_items[0] = "autoattack"
|
||||
action_bar_items[1] = "heavy_strike"
|
||||
|
||||
# Klassen-Ressource berechnen (Mana aus INT, Energie fix, Wut fix)
|
||||
func _calculate_resource():
|
||||
if character_class == null or character_class.resource_type == CharacterClass.ResourceType.NONE:
|
||||
|
|
@ -304,8 +345,12 @@ func _get_slot_cooldown(slot_index: int) -> float:
|
|||
match entry:
|
||||
"autoattack":
|
||||
return global_cooldown
|
||||
"wand":
|
||||
return global_cooldown
|
||||
"heavy_strike":
|
||||
return heavy_strike_cooldown
|
||||
"frostbolt":
|
||||
return frostbolt_cooldown
|
||||
elif entry is Consumable:
|
||||
return potion_cooldown
|
||||
return 0.0
|
||||
|
|
@ -334,10 +379,18 @@ func _use_action_slot(slot_index: int):
|
|||
match entry:
|
||||
"autoattack":
|
||||
if target != null and global_cooldown <= 0:
|
||||
wand_active = false # Zauberstab deaktivieren
|
||||
start_autoattack()
|
||||
perform_autoattack()
|
||||
"wand":
|
||||
if target != null and global_cooldown <= 0:
|
||||
autoattack_active = false # Autoattack deaktivieren
|
||||
start_wand()
|
||||
perform_wand_attack()
|
||||
"heavy_strike":
|
||||
use_heavy_strike()
|
||||
"frostbolt":
|
||||
use_frostbolt()
|
||||
elif entry is Consumable:
|
||||
if use_consumable(entry):
|
||||
if entry.stack_size <= 0:
|
||||
|
|
@ -348,6 +401,8 @@ func _use_action_slot(slot_index: int):
|
|||
func take_damage(amount):
|
||||
current_hp = clamp(current_hp - amount, 0, max_hp)
|
||||
hud.update_health(current_hp, max_hp)
|
||||
if is_casting:
|
||||
_cancel_cast()
|
||||
if current_hp <= 0:
|
||||
die()
|
||||
|
||||
|
|
@ -488,7 +543,7 @@ func get_dps() -> float:
|
|||
# DPS = Schaden / GCD
|
||||
return total_damage / gcd
|
||||
|
||||
# Reichweite basierend auf ausgerüsteter Waffe (unbewaffnet = 3.0)
|
||||
# Reichweite basierend auf ausgerüsteter Waffe (Nahkampf)
|
||||
func get_attack_range() -> float:
|
||||
var weapon = get_equipped_weapon()
|
||||
if weapon == null:
|
||||
|
|
@ -503,9 +558,7 @@ func set_target(new_target, start_attack: bool = false):
|
|||
target.show_health()
|
||||
print("Ziel markiert: ", target.name)
|
||||
if start_attack:
|
||||
start_autoattack()
|
||||
if global_cooldown <= 0:
|
||||
perform_autoattack()
|
||||
_start_default_attack()
|
||||
|
||||
# Ziel komplett aufheben und Autoattack stoppen
|
||||
func clear_target():
|
||||
|
|
@ -513,7 +566,19 @@ func clear_target():
|
|||
target.hide_health()
|
||||
target = null
|
||||
autoattack_active = false
|
||||
print("Ziel aufgehoben, Autoattack gestoppt")
|
||||
wand_active = false
|
||||
print("Ziel aufgehoben, Angriff gestoppt")
|
||||
|
||||
# Standard-Angriff starten (Rechtsklick): Magier=Zauberstab, Rest=Autoattack
|
||||
func _start_default_attack():
|
||||
if character_class and character_class.resource_type == CharacterClass.ResourceType.MANA:
|
||||
start_wand()
|
||||
if global_cooldown <= 0:
|
||||
perform_wand_attack()
|
||||
else:
|
||||
start_autoattack()
|
||||
if global_cooldown <= 0:
|
||||
perform_autoattack()
|
||||
|
||||
# Autoattack aktivieren
|
||||
func start_autoattack():
|
||||
|
|
@ -525,6 +590,34 @@ func stop_autoattack():
|
|||
autoattack_active = false
|
||||
print("Autoattack deaktiviert")
|
||||
|
||||
# Zauberstab aktivieren (deaktiviert Autoattack)
|
||||
func start_wand():
|
||||
wand_active = true
|
||||
autoattack_active = false
|
||||
print("Zauberstab aktiviert")
|
||||
|
||||
# Zauberstab deaktivieren
|
||||
func stop_wand():
|
||||
wand_active = false
|
||||
print("Zauberstab deaktiviert")
|
||||
|
||||
# Zauberstab-Angriff ausführen (Fernkampf, magisch)
|
||||
func perform_wand_attack():
|
||||
if target == null or not is_instance_valid(target):
|
||||
target = null
|
||||
wand_active = false
|
||||
return
|
||||
|
||||
var distance = global_position.distance_to(target.global_position)
|
||||
if distance <= WAND_RANGE:
|
||||
var dmg = get_attack_damage()
|
||||
if target.has_method("take_damage_from"):
|
||||
target.take_damage_from(dmg, level, false) # Magisch, ignoriert Rüstung
|
||||
else:
|
||||
target.take_damage(dmg)
|
||||
print("Zauberstab: ", dmg, " magischer Schaden")
|
||||
trigger_global_cooldown()
|
||||
|
||||
# Führt einen Autoattack aus (wird vom GCD-System aufgerufen)
|
||||
func perform_autoattack():
|
||||
if target == null or not is_instance_valid(target):
|
||||
|
|
@ -535,13 +628,11 @@ func perform_autoattack():
|
|||
var distance = global_position.distance_to(target.global_position)
|
||||
if distance <= get_attack_range():
|
||||
var dmg = get_attack_damage()
|
||||
# Neues Schadenssystem mit Rüstung und Level-Differenz
|
||||
if target.has_method("take_damage_from"):
|
||||
target.take_damage_from(dmg, level, true) # true = Nahkampf
|
||||
target.take_damage_from(dmg, level, true) # Nahkampf
|
||||
else:
|
||||
target.take_damage(dmg)
|
||||
print("Autoattack: ", dmg, " Schaden (GCD: %.2fs, DPS: %.1f)" % [get_current_gcd(), get_dps()])
|
||||
# GCD auslösen basierend auf Waffengeschwindigkeit + Haste
|
||||
trigger_global_cooldown()
|
||||
|
||||
# Global Cooldown auslösen (basierend auf Waffe + Haste)
|
||||
|
|
@ -577,6 +668,82 @@ func use_heavy_strike():
|
|||
start_autoattack() # Autoattack nach Skill automatisch aktivieren
|
||||
print("Heavy Strike! ", damage, " Rohschaden")
|
||||
|
||||
# Frostblitz: Cast starten
|
||||
func use_frostbolt():
|
||||
if is_casting:
|
||||
return # Bereits am Casten
|
||||
if target == null or not is_instance_valid(target):
|
||||
print("Kein Ziel für Frostblitz!")
|
||||
return
|
||||
if frostbolt_cooldown > 0:
|
||||
print("Frostblitz noch im Cooldown: ", "%.1f" % frostbolt_cooldown, "s")
|
||||
return
|
||||
if current_resource < FROSTBOLT_MANA_COST:
|
||||
print("Nicht genug Mana für Frostblitz! (", current_resource, "/", FROSTBOLT_MANA_COST, ")")
|
||||
return
|
||||
var distance = global_position.distance_to(target.global_position)
|
||||
if distance > FROSTBOLT_RANGE:
|
||||
print("Ziel zu weit entfernt für Frostblitz!")
|
||||
return
|
||||
|
||||
# Cast starten
|
||||
_start_cast("frostbolt", FROSTBOLT_CAST_TIME)
|
||||
print("Frostblitz wird gewirkt... (", FROSTBOLT_CAST_TIME, "s)")
|
||||
|
||||
# Frostblitz: Schaden anwenden nach erfolgreichem Cast
|
||||
func _finish_frostbolt():
|
||||
if target == null or not is_instance_valid(target):
|
||||
print("Ziel verloren!")
|
||||
return
|
||||
var distance = global_position.distance_to(target.global_position)
|
||||
if distance > FROSTBOLT_RANGE:
|
||||
print("Ziel zu weit entfernt!")
|
||||
return
|
||||
|
||||
# Mana abziehen
|
||||
spend_resource(FROSTBOLT_MANA_COST)
|
||||
|
||||
var base_damage = randi_range(FROSTBOLT_DAMAGE_MIN, FROSTBOLT_DAMAGE_MAX)
|
||||
var stat_bonus = int(intelligence * CharacterClass.DAMAGE_PER_MAIN_STAT)
|
||||
var damage = base_damage + stat_bonus
|
||||
if target.has_method("take_damage_from"):
|
||||
target.take_damage_from(damage, level, false)
|
||||
else:
|
||||
target.take_damage(damage)
|
||||
frostbolt_cooldown = FROSTBOLT_COOLDOWN
|
||||
trigger_global_cooldown()
|
||||
start_wand() # Zauberstab nach Cast weiter aktiv
|
||||
print("Frostblitz! ", damage, " magischer Schaden (", FROSTBOLT_MANA_COST, " Mana)")
|
||||
|
||||
# Cast-System
|
||||
func _start_cast(spell_id: String, cast_time: float):
|
||||
is_casting = true
|
||||
cast_spell_id = spell_id
|
||||
cast_time_total = cast_time
|
||||
cast_time_remaining = cast_time
|
||||
autoattack_active = false # Autoattack pausieren während Cast
|
||||
hud.show_castbar(spell_id, cast_time)
|
||||
|
||||
func _cancel_cast():
|
||||
if not is_casting:
|
||||
return
|
||||
is_casting = false
|
||||
cast_spell_id = ""
|
||||
cast_time_remaining = 0.0
|
||||
hud.hide_castbar()
|
||||
print("Zauber unterbrochen!")
|
||||
|
||||
func _finish_cast():
|
||||
var spell = cast_spell_id
|
||||
is_casting = false
|
||||
cast_spell_id = ""
|
||||
cast_time_remaining = 0.0
|
||||
hud.hide_castbar()
|
||||
# Fertigen Zauber ausführen
|
||||
match spell:
|
||||
"frostbolt":
|
||||
_finish_frostbolt()
|
||||
|
||||
# Raycast von der Kamera auf Mausposition — trifft Gegner mit take_damage()
|
||||
func _try_select_target(start_attack: bool = false):
|
||||
var space_state = get_world_3d().direct_space_state
|
||||
|
|
@ -595,17 +762,29 @@ func _try_select_target(start_attack: bool = false):
|
|||
clear_target()
|
||||
|
||||
func _physics_process(delta):
|
||||
# Cast-System
|
||||
if is_casting:
|
||||
cast_time_remaining -= delta
|
||||
hud.update_castbar(cast_time_total - cast_time_remaining, cast_time_total)
|
||||
if cast_time_remaining <= 0:
|
||||
_finish_cast()
|
||||
|
||||
# Global Cooldown herunterzählen (gilt für alle Aktionen)
|
||||
if global_cooldown > 0:
|
||||
global_cooldown -= delta
|
||||
|
||||
# Wenn GCD bereit und Autoattack aktiv, versuche anzugreifen
|
||||
if global_cooldown <= 0 and autoattack_active:
|
||||
# Wenn GCD bereit und nicht am Casten
|
||||
if global_cooldown <= 0 and not is_casting:
|
||||
if wand_active:
|
||||
perform_wand_attack()
|
||||
elif autoattack_active:
|
||||
perform_autoattack()
|
||||
|
||||
# Skill-Cooldowns herunterzählen
|
||||
if heavy_strike_cooldown > 0:
|
||||
heavy_strike_cooldown -= delta
|
||||
if frostbolt_cooldown > 0:
|
||||
frostbolt_cooldown -= delta
|
||||
if potion_cooldown > 0:
|
||||
potion_cooldown -= delta
|
||||
|
||||
|
|
@ -621,6 +800,8 @@ func _physics_process(delta):
|
|||
# Springen
|
||||
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
|
||||
velocity.y = JUMP_VELOCITY
|
||||
if is_casting:
|
||||
_cancel_cast()
|
||||
|
||||
# Linksklick: nur markieren
|
||||
if Input.is_action_just_pressed("select_target"):
|
||||
|
|
@ -665,6 +846,10 @@ func _physics_process(delta):
|
|||
if Input.is_action_pressed("move_right"):
|
||||
input_dir.x += 1
|
||||
|
||||
# Bewegung unterbricht Cast
|
||||
if is_casting and input_dir.length() > 0:
|
||||
_cancel_cast()
|
||||
|
||||
# Bewegung relativ zur Kamera
|
||||
var world_yaw = rotation.y + camera_pivot.rotation.y
|
||||
var forward = Vector3(-sin(world_yaw), 0, -cos(world_yaw)).normalized()
|
||||
|
|
|
|||
1
skill_panel.gd.uid
Normal file
1
skill_panel.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://gf03d1ewoxcf
|
||||
17
world.gd
17
world.gd
|
|
@ -8,7 +8,8 @@ const CLASS_SELECTION_MENU = preload("res://class_selection_menu.tscn")
|
|||
const RESPAWN_TIME = 5.0
|
||||
|
||||
# Startausrüstung
|
||||
const STARTER_WEAPON = preload("res://equipment/iron_sword.tres")
|
||||
const STARTER_SWORD = preload("res://equipment/iron_sword.tres")
|
||||
const STARTER_STAFF = preload("res://equipment/wooden_staff.tres")
|
||||
const STARTER_CHEST = preload("res://equipment/leather_chest.tres")
|
||||
|
||||
# Loot Tables
|
||||
|
|
@ -34,13 +35,23 @@ func _on_start_game():
|
|||
func _on_class_selected(character_class: CharacterClass):
|
||||
player.character_class = character_class
|
||||
|
||||
# Startausrüstung geben
|
||||
player.equip_item(STARTER_WEAPON)
|
||||
# Skills klassenabhängig aufbauen
|
||||
player._init_class_skills()
|
||||
for i in range(9):
|
||||
player._refresh_action_slot(i)
|
||||
|
||||
# Startausrüstung klassenabhängig
|
||||
if character_class.resource_type == CharacterClass.ResourceType.MANA:
|
||||
player.equip_item(STARTER_STAFF)
|
||||
else:
|
||||
player.equip_item(STARTER_SWORD)
|
||||
player.equip_item(STARTER_CHEST)
|
||||
|
||||
player._calculate_stats()
|
||||
player.current_hp = player.max_hp
|
||||
player.current_resource = player.max_resource
|
||||
player.hud.update_health(player.current_hp, player.max_hp)
|
||||
player.hud.update_resource(player.current_resource, player.max_resource, player.get_resource_name())
|
||||
print("Klasse gewählt: ", character_class.class_name_de)
|
||||
|
||||
# Jetzt Gegner initialisieren
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue