Add all files

This commit is contained in:
2025-04-18 22:30:19 +02:00
parent 44aec1a1fb
commit 4ec52c34d4
2477 changed files with 76624 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
[gd_scene format=3 uid="uid://sc01ppjgkfew"]
[node name="GameManager" type="Node2D"]

View File

@@ -0,0 +1,346 @@
extends Node2D
# Add at the top with other variables
class ChatMessage:
var text: String
var timestamp: Dictionary
var type: String # "chat", "connection", "system"
func _init(msg: String, typ: String):
text = msg
timestamp = Time.get_datetime_dict_from_system()
type = typ
func format_timestamp() -> String:
return "%02d:%02d:%02d" % [timestamp.hour, timestamp.minute, timestamp.second]
var chat_history: Array[ChatMessage] = []
var show_timestamps: bool = false
const MAX_CHAT_HISTORY = 10
# Add at the top with other variables
var connection_label_timer: Timer
var connection_label_tween: Tween
var character_data:CharacterStats = null
var SERVER_PORT = 21212
var SERVER_HOST = "ruinborn.thefirstboss.com"
var hasMultiplayerInitiated = false
# Add these variables at the top
#var tcp_server: TCPServer = TCPServer.new()
# Add at top with other variables
#var websocket = WebSocketPeer.new()
# Track which peers are ready for entity sync
var peers_ready_for_sync: Dictionary = {}
# Add at the top with other variables
var peers_character_data: Dictionary = {}
signal addPlayerSignal(id:int)
signal delPlayerSignal(id:int)
signal finished_hosting()
signal client_ready_for_players(peer_id: int)
signal connectionFailed
signal connectionSucceeded
signal countdownFinished
func _ready():
connection_label_timer = Timer.new()
connection_label_timer.one_shot = true
connection_label_timer.wait_time = 5.0
connection_label_timer.timeout.connect(_on_connection_label_timeout)
add_child(connection_label_timer)
$CanvasLayer/ControlCenter/MarginContainerForScore.visible = false # hide on start
$CanvasLayer/ControlCountdown.visible = false
%LabelRoundWinner.visible = false
pass
func _on_connection_label_timeout():
# Create tween for fading out
if connection_label_tween:
connection_label_tween.kill()
connection_label_tween = create_tween()
connection_label_tween.tween_property(
$CanvasLayer/BottomLeftCorner/VBoxContainer/LabelPlayerConnect,
"modulate:a",
0.0,
1.0
)
func _physics_process(_delta: float) -> void:
if %LabelRoundWinner.visible == false and Input.is_action_just_pressed("ui_focus_next"):
$CanvasLayer/ControlCenter/MarginContainerForScore.visible = !$CanvasLayer/ControlCenter/MarginContainerForScore.visible
pass
pass
func host():
print("hosting")
#var server_peer = ENetMultiplayerPeer.new()
var server_peer = WebSocketMultiplayerPeer.new()
server_peer.create_server(SERVER_PORT)
#multiplayer.allow_object_decoding = true
multiplayer.multiplayer_peer = server_peer
multiplayer.peer_connected.connect(_add_player_to_game)
multiplayer.peer_disconnected.connect(_del_player)
_add_player_to_game(multiplayer.get_unique_id())
emit_signal("finished_hosting")
hasMultiplayerInitiated = true
pass
func join():
print("joining")
#var client_peer = ENetMultiplayerPeer.new()
#client_peer.create_client(SERVER_HOST, 443)
var client_peer = WebSocketMultiplayerPeer.new()
var _error = OK
if not OS.has_feature("pc"):
_error = client_peer.create_client("wss://" + SERVER_HOST + ":" + str(443))
else:
_error = client_peer.create_client("ws://" + SERVER_HOST + ":" + str(SERVER_PORT))
#multiplayer.allow_object_decoding = true
multiplayer.multiplayer_peer = client_peer
multiplayer.peer_connected.connect(_on_peer_connected)
multiplayer.peer_disconnected.connect(_on_peer_disconnected)
# Wait for connection
var max_attempts = 10
var attempts = 0
while client_peer.get_connection_status() == MultiplayerPeer.CONNECTION_CONNECTING:
attempts += 1
print("Connection attempt ", attempts, " - Status: ", client_peer.get_connection_status())
if attempts >= max_attempts:
print("Connection timed out after", max_attempts, "attempts")
#_cleanup_connections()
connectionFailed.emit()
return
await get_tree().create_timer(1.0).timeout
if client_peer.get_connection_status() == MultiplayerPeer.CONNECTION_CONNECTED:
print("Connected to game server!")
connectionSucceeded.emit()
hasMultiplayerInitiated = true
pass
func _add_player_to_game(id: int):
print("Player %d joined the game!", id)
emit_signal("addPlayerSignal", id)
pass
func _del_player(id: int):
print("Player %d left the game!", id)
emit_signal("delPlayerSignal", id)
pass
@rpc("any_peer", "reliable")
func notify_client_ready(peer_id: int):
if multiplayer.is_server():
print("Client ", peer_id, " is ready for sync")
peers_ready_for_sync[peer_id] = true
client_ready_for_players.emit(peer_id)
# Send host's character data to the new client
sync_character_data.rpc_id(peer_id, multiplayer.get_unique_id(), character_data.save())
# Send all other peers' character data to the new client
for other_peer_id in peers_character_data:
sync_character_data.rpc_id(peer_id, other_peer_id, peers_character_data[other_peer_id])
else:
# Client sends its character data to server
print("Sending character data to server")
sync_character_data.rpc_id(1, multiplayer.get_unique_id(), character_data.save())
@rpc("any_peer", "reliable")
func sync_character_data(peer_id: int, char_data: Dictionary):
print("Received character data for peer: ", peer_id)
if multiplayer.is_server():
# Store the character data
peers_character_data[peer_id] = char_data
# Broadcast this character data to all other connected peers
for other_peer in multiplayer.get_peers():
if other_peer != peer_id: # Don't send back to the sender
sync_character_data.rpc_id(other_peer, peer_id, char_data)
var playersNode = get_tree().current_scene.get_node("SpawnRoot")
# Update the player's stats locally
var player = playersNode.get_node_or_null(str(peer_id))
if player:
player.stats.load(char_data)
player.initStats(player.stats)
print("Updated character stats for player: ", peer_id, " with name: ", player.stats.character_name)
updateScore(true)
func _on_peer_connected(_peer_id: int):
#add_chat_message("Player " + str(peer_id) + " connected", "connection")
print("WE SUCCESSFUNYL CONNECT!")
add_chat_message("Player " + str(_peer_id) + " connected", "connection")
$CanvasLayer/BottomLeftCorner/VBoxContainer/LabelPlayerConnect.text = "Player " + str(_peer_id) + " connected"
$CanvasLayer/BottomLeftCorner/VBoxContainer/LabelPlayerConnect.modulate.a = 1.0
# Reset and start the timer
if connection_label_tween:
connection_label_tween.kill()
connection_label_timer.start()
# Tell server we're ready for sync
notify_client_ready(multiplayer.get_unique_id()) # run locally also
notify_client_ready.rpc_id(1, multiplayer.get_unique_id())
pass
func _on_peer_disconnected(peer_id: int):
add_chat_message("Player " + str(peer_id) + " disconnected", "connection")
pass
func add_chat_message(message: String, type: String = "chat"):
var chat_msg = ChatMessage.new(message, type)
chat_history.append(chat_msg)
# Keep only last MAX_CHAT_HISTORY messages
if chat_history.size() > MAX_CHAT_HISTORY:
chat_history.pop_front()
update_chat_display()
func update_chat_display():
var display_text = ""
for msg in chat_history:
if show_timestamps:
display_text += "[%s] " % msg.format_timestamp()
display_text += msg.text + "\n"
$CanvasLayer/BottomLeftCorner/VBoxContainer/LabelPlayerConnect.text = display_text.strip_edges()
$CanvasLayer/BottomLeftCorner/VBoxContainer/LabelPlayerConnect.modulate.a = 1.0
# Reset and start the fade timer
if connection_label_tween:
connection_label_tween.kill()
connection_label_timer.start()
# Add RPC for chat messages between players
@rpc("any_peer", "reliable")
func send_chat_message(message: String):
var sender_id = multiplayer.get_remote_sender_id()
add_chat_message("Player %d: %s" % [sender_id, message], "chat")
# Function to send a chat message
func broadcast_chat_message(message: String):
if multiplayer.multiplayer_peer != null:
send_chat_message.rpc(message)
# Add local copy of the message
add_chat_message("You: " + message, "chat")
func sortScoreArr(a, b):
if a.kills > b.kills:
return true # More kills should come first
elif a.kills == b.kills:
return a.deaths < b.deaths # Fewer deaths should come first
return false # Otherwise, b comes first
var previousScores = []
func updateScore(playerJoined:bool = false):
%LabelPlayerNr.text = "#"
%LabelPlayerNames.text = "Player"
%LabelPlayerKills.text = "Kills"
%LabelPlayerDeaths.text = "Deaths"
var playersNode = get_tree().current_scene.get_node("SpawnRoot")
var scores = []
for pl in playersNode.get_children():
if "is_player" in pl:
scores.push_back({ "name": pl.stats.character_name, "kills": pl.stats.kills, "deaths": pl.stats.deaths})
pass
pass
scores.sort_custom(sortScoreArr)
# play sfx depending on score.
if !playerJoined and previousScores.size() != 0:
# check if you were leading
if previousScores[0].name == MultiplayerManager.character_data.character_name:
# you were previously leading, but no longer
if scores[0].name != previousScores[0].name:
$SfxLostTheLead.play()
pass
else:
# still in lead
if previousScores.size() > 1:
if previousScores[0].kills == previousScores[1].kills and previousScores[0].deaths == previousScores[1].deaths:
if scores.size() > 1:
if scores[0].kills > scores[1].kills or scores[0].deaths < scores[1].deaths:
$SfxTakenTheLead.play()
pass
pass
pass
else:
# you were NOT previously leading
if scores[0].name == MultiplayerManager.character_data.character_name:
# you have taken the lead!
$SfxTakenTheLead.play()
pass
pass
pass
var nr = 1
var cnt = 0
for sc in scores:
if cnt == 0:
%LabelRoundWinner.text = sc.name + " WINS THE ROUND!"
if cnt != 0 and (scores[cnt].kills < scores[cnt-1].kills or scores[cnt].deaths > scores[cnt-1].deaths):
nr += 1
%LabelPlayerNr.text += "\r\n" + str(nr)
%LabelPlayerNames.text += "\r\n" + sc.name
%LabelPlayerKills.text += "\r\n" + str(sc.kills)
%LabelPlayerDeaths.text += "\r\n" + str(sc.deaths)
cnt += 1
pass
previousScores = scores
pass
func start_round():
$CanvasLayer/ControlCountdown.visible = true
$CanvasLayer/ControlCountdown/LabelCountdown/AnimationPlayer.play("countdown")
await $CanvasLayer/ControlCountdown/LabelCountdown/AnimationPlayer.animation_finished
$CanvasLayer/ControlCountdown.visible = false
emit_signal("countdownFinished")
pass
@rpc("call_local", "reliable")
func round_finished():
if previousScores.size() != 0 and previousScores[0].name == MultiplayerManager.character_data.character_name:
$SfxWinner.play()
%LabelRoundWinner.visible = true
$CanvasLayer/ControlCenter/MarginContainerForScore.visible = true
# reset score
# Broadcast this character data to all other connected peers
pass
func new_round_started():
previousScores = [] # reset scores...
%LabelRoundWinner.visible = false
$CanvasLayer/ControlCenter/MarginContainerForScore.visible = false
if multiplayer.is_server():
var playersNode = get_tree().current_scene.get_node("SpawnRoot")
for pl in playersNode.get_children():
if "is_player" in pl:
pl.stats.kills = 0
pl.stats.deaths = 0
pl.stats.hp = pl.stats.maxhp
if int(pl.name) != multiplayer.get_unique_id(): # no need to sync server char, cuz it will be done in the initStats below.
for other_peer in multiplayer.get_peers():
sync_character_data.rpc_id(other_peer, int(pl.name), pl.stats.save())
pl.initStats(pl.stats)
updateScore(true)
pass

View File

@@ -0,0 +1 @@
uid://ct73f1m77ayyp

View File

@@ -0,0 +1,344 @@
[gd_scene load_steps=11 format=3 uid="uid://m8hiw0yydn5"]
[ext_resource type="Script" uid="uid://ct73f1m77ayyp" path="res://scripts/Autoloads/multiplayer_manager.gd" id="1_vqyfe"]
[ext_resource type="AudioStream" uid="uid://caqdvm1q8lk3a" path="res://assets/audio/sfx/ut99/cd1.wav" id="2_84xnf"]
[ext_resource type="AudioStream" uid="uid://b5f6j5p5wcqht" path="res://assets/audio/sfx/announcer/taken_lead.mp3" id="2_eak84"]
[ext_resource type="AudioStream" uid="uid://cv10napkg4ft" path="res://assets/audio/sfx/announcer/lost_lead.mp3" id="3_62id2"]
[ext_resource type="AudioStream" uid="uid://cnc5mjushyugx" path="res://assets/audio/sfx/ut99/cd2.wav" id="3_h0fyv"]
[ext_resource type="AudioStream" uid="uid://dyjn7rgi6of0o" path="res://assets/audio/sfx/ut99/cd3.wav" id="4_4gr8q"]
[ext_resource type="AudioStream" uid="uid://hnwotbj3kwmu" path="res://assets/audio/sfx/ut99/winner.wav" id="5_h0fyv"]
[sub_resource type="Animation" id="Animation_62id2"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:scale")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(1, 1)]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath(".:text")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": ["3"]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath(".:pivot_offset")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(40, 58)]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("Sfx3:playing")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/4/type = "value"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath("Sfx2:playing")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/5/type = "value"
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/path = NodePath("Sfx1:playing")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
[sub_resource type="Animation" id="Animation_eak84"]
resource_name = "countdown"
length = 3.4
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:text")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 1, 2, 3),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 1,
"values": ["3", "2", "1", "GO"]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath(".:scale")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.733333, 0.966667, 1.03333, 1.57554, 1.93691, 2.00097, 2.61712, 2.93333, 2.96667, 3.0533, 3.16667, 3.36138),
"transitions": PackedFloat32Array(1, 0.420448, 0.277392, 2, 0.5, 1, 1, 1, 1, 1, 1, 1, 1),
"update": 0,
"values": [Vector2(0.001, 0.001), Vector2(4, 4), Vector2(4, 4), Vector2(0.001, 0.001), Vector2(4, 4), Vector2(4, 4), Vector2(0.001, 0.001), Vector2(4, 4), Vector2(4, 4), Vector2(0.001, 0.001), Vector2(4, 4), Vector2(4, 4), Vector2(0.001, 0.001)]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath(".:pivot_offset")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0, 3),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [Vector2(40, 58), Vector2(98, 58)]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("Sfx3:playing")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
tracks/4/type = "value"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath("Sfx2:playing")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(0.866667),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
tracks/5/type = "value"
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/path = NodePath("Sfx1:playing")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/keys = {
"times": PackedFloat32Array(1.93333),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_n0fp4"]
_data = {
&"RESET": SubResource("Animation_62id2"),
&"countdown": SubResource("Animation_eak84")
}
[node name="MultiplayerManager" type="Node2D"]
script = ExtResource("1_vqyfe")
[node name="CanvasLayer" type="CanvasLayer" parent="."]
layer = 21
[node name="ControlCenter" type="Control" parent="CanvasLayer"]
layout_mode = 3
anchors_preset = 5
anchor_left = 0.5
anchor_right = 0.5
grow_horizontal = 2
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="MarginContainerForScore" type="MarginContainer" parent="CanvasLayer/ControlCenter"]
layout_mode = 1
anchors_preset = 5
anchor_left = 0.5
anchor_right = 0.5
offset_left = -74.5
offset_top = 24.0
offset_right = 74.5
offset_bottom = 82.0
grow_horizontal = 2
[node name="ColorRect" type="ColorRect" parent="CanvasLayer/ControlCenter/MarginContainerForScore"]
layout_mode = 2
size_flags_vertical = 3
color = Color(0, 0, 0, 0.356863)
[node name="MarginContainer" type="MarginContainer" parent="CanvasLayer/ControlCenter/MarginContainerForScore"]
layout_mode = 2
theme_override_constants/margin_left = 10
theme_override_constants/margin_top = 10
theme_override_constants/margin_right = 10
theme_override_constants/margin_bottom = 10
[node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer/ControlCenter/MarginContainerForScore/MarginContainer"]
layout_mode = 2
theme_override_constants/separation = 4
[node name="LabelCurrentScore" type="Label" parent="CanvasLayer/ControlCenter/MarginContainerForScore/MarginContainer/VBoxContainer"]
layout_mode = 2
size_flags_horizontal = 4
theme_override_constants/outline_size = 6
text = "- Current score -"
horizontal_alignment = 1
[node name="HBoxContainer" type="HBoxContainer" parent="CanvasLayer/ControlCenter/MarginContainerForScore/MarginContainer/VBoxContainer"]
layout_mode = 2
theme_override_constants/separation = 10
[node name="LabelPlayerNr" type="Label" parent="CanvasLayer/ControlCenter/MarginContainerForScore/MarginContainer/VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
theme_override_constants/outline_size = 6
text = "#
1."
[node name="LabelPlayerNames" type="Label" parent="CanvasLayer/ControlCenter/MarginContainerForScore/MarginContainer/VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
theme_override_constants/outline_size = 6
text = "Player
Elrinth"
[node name="LabelPlayerKills" type="Label" parent="CanvasLayer/ControlCenter/MarginContainerForScore/MarginContainer/VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 8
theme_override_constants/outline_size = 6
text = "Kills
0"
horizontal_alignment = 1
[node name="LabelPlayerDeaths" type="Label" parent="CanvasLayer/ControlCenter/MarginContainerForScore/MarginContainer/VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 8
size_flags_vertical = 8
theme_override_constants/outline_size = 6
text = "Deaths
0"
horizontal_alignment = 1
[node name="LabelRoundWinner" type="Label" parent="CanvasLayer/ControlCenter/MarginContainerForScore/MarginContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
theme_override_constants/outline_size = 10
theme_override_font_sizes/font_size = 37
text = "Elrinth WINS the round!"
horizontal_alignment = 1
[node name="BottomLeftCorner" type="Control" parent="CanvasLayer"]
layout_mode = 3
anchors_preset = 2
anchor_top = 1.0
anchor_bottom = 1.0
offset_top = -40.0
offset_right = 40.0
grow_vertical = 0
mouse_filter = 2
[node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer/BottomLeftCorner"]
layout_mode = 1
anchors_preset = 2
anchor_top = 1.0
anchor_bottom = 1.0
offset_top = -40.0
offset_right = 40.0
grow_vertical = 0
[node name="LabelPlayerConnect" type="Label" parent="CanvasLayer/BottomLeftCorner/VBoxContainer"]
layout_mode = 2
horizontal_alignment = 2
[node name="LabelChatHistory" type="Label" parent="CanvasLayer/BottomLeftCorner/VBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
vertical_alignment = 2
[node name="ControlCountdown" type="Control" parent="CanvasLayer"]
visible = false
layout_mode = 3
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -20.0
offset_top = -20.0
offset_right = 20.0
offset_bottom = 20.0
grow_horizontal = 2
grow_vertical = 2
[node name="LabelCountdown" type="Label" parent="CanvasLayer/ControlCountdown"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
pivot_offset = Vector2(40, 58)
theme_override_constants/outline_size = 16
theme_override_font_sizes/font_size = 128
text = "3"
horizontal_alignment = 1
vertical_alignment = 1
[node name="AnimationPlayer" type="AnimationPlayer" parent="CanvasLayer/ControlCountdown/LabelCountdown"]
libraries = {
&"": SubResource("AnimationLibrary_n0fp4")
}
[node name="Sfx1" type="AudioStreamPlayer2D" parent="CanvasLayer/ControlCountdown/LabelCountdown"]
stream = ExtResource("2_84xnf")
[node name="Sfx2" type="AudioStreamPlayer2D" parent="CanvasLayer/ControlCountdown/LabelCountdown"]
stream = ExtResource("3_h0fyv")
[node name="Sfx3" type="AudioStreamPlayer2D" parent="CanvasLayer/ControlCountdown/LabelCountdown"]
stream = ExtResource("4_4gr8q")
[node name="SfxWinner" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("5_h0fyv")
[node name="SfxTakenTheLead" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("2_eak84")
bus = &"Sfx"
[node name="SfxLostTheLead" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("3_62id2")
bus = &"Sfx"

View File

@@ -0,0 +1,169 @@
extends CharacterBody2D
var speed = 300
var direction = Vector2.ZERO
var stick_duration = 3.0 # How long the arrow stays stuck to walls
var is_stuck = false
var stick_timer = 0.0
var initiated_by: Node2D = null
@onready var arrow_area = $ArrowArea # Assuming you have an Area2D node named ArrowArea
@onready var shadow = $Shadow # Assuming you have a Shadow node under the CharacterBody2D
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
arrow_area.set_deferred("monitoring", true)
#arrow_area.body_entered.connect(_on_body_entered)
$SfxArrowFire.play()
call_deferred("_initialize_arrow")
func _initialize_arrow() -> void:
var angle = direction.angle()
self.rotation = angle - PI / 2 # Adjust for sprite orientation
# Set initial rotation based on direction
velocity = direction * speed # Set initial velocity to move the arrow
# Calculate the offset for the shadow position, which should be below the arrow
var shadow_offset = Vector2(0, 4) # Adjust the 16 to how far you want the shadow from the arrow (this is just an example)
# Apply the rotation of the arrow to the shadow offset
shadow.position += shadow_offset.rotated(-self.rotation)
if abs(direction.x) == 1:
shadow.scale.x = 0.26
shadow.scale.y = 0.062
elif abs(direction.x) > 0:
shadow.scale.x = 0.18
shadow.scale.y = 0.08
else:
shadow.scale.x = 0.1
shadow.scale.y = 0.1
# Calculate the shadow's scale based on the velocity or direction of the arrow
#var velocity_magnitude = velocity.length()
# Scale more in the horizontal direction if moving diagonally or horizontally
#var scale_factor = 0.28 + abs(velocity.x) / velocity_magnitude # Adjust the factor to your preference
# Apply the scaling to the shadow
shadow.rotation = -(angle - PI / 2)
func shoot(shoot_direction: Vector2, start_pos: Vector2) -> void:
direction = shoot_direction.normalized()
global_position = start_pos
#position = start_pos
# Called every frame. 'delta' is the e lapsed time since the previous frame.
func _process(delta: float) -> void:
if is_stuck:
# Handle fade out here if it's stuck
stick_timer += delta
if stick_timer >= stick_duration:
# Start fading out after it sticks
modulate.a = max(0, 1 - (stick_timer - stick_duration) / 1.0) # Fade out over 1 second
if stick_timer >= stick_duration + 1.0: # Extra second for fade out
queue_free() # Remove the arrow after fade out
move_and_slide()
func _physics_process(_delta: float) -> void:
# If the arrow is stuck, stop it from moving
if is_stuck:
velocity = Vector2.ZERO # Stop movement
# Optional: disable further physics interaction by setting linear_velocity
# move_and_slide(Vector2.ZERO) # You can also use this to stop the character
func play_impact():
$SfxImpactSound.play()
# Called when the arrow hits a wall or another object
func _on_body_entered(body: Node) -> void:
if not is_stuck:
if body == initiated_by:
return
if body is CharacterBody2D and body.stats.is_invulnerable == false and body.stats.hp > 0: # hit an enemy
#if body is CharacterBody2D and body.collision_layer & (1 << 8) and body.taking_damage_timer <= 0 and body.stats.hp > 0: # Check if body is enemy (layer 9)
# Stop the arrow
velocity = Vector2.ZERO
is_stuck = true
stick_timer = 0.0
arrow_area.set_deferred("monitoring", false)
# Calculate the collision point - move arrow slightly back from its direction
var collision_normal = -direction # Opposite of arrow's direction
var offset_distance = 8 # Adjust this value based on your collision shape sizes
var stick_position = global_position + (collision_normal * offset_distance)
# Make arrow a child of the enemy to stick to it
var global_rot = global_rotation
get_parent().call_deferred("remove_child", self)
body.call_deferred("add_child", self)
self.set_deferred("global_position", stick_position)
self.set_deferred("global_rotation", global_rot)
#global_rotation = global_rot
body.call_deferred("take_damage", self, initiated_by)
self.call_deferred("play_impact") # need to play the sound on the next frame, because else it cuts it.
else:
$SfxImpactWall.play()
# Stop the arrow
velocity = Vector2.ZERO
is_stuck = true
stick_timer = 0.0
arrow_area.set_deferred("monitoring", false)
# You can optionally stick the arrow at the collision point if you want:
# position = body.position # Uncomment this if you want to "stick" it at the collision point
# Additional logic for handling interaction with walls or other objects
func _on_arrow_area_area_entered(area: Area2D) -> void:
if not is_stuck:
if area.get_parent() == initiated_by:
return
if area.get_parent() is CharacterBody2D and area.get_parent().stats.is_invulnerable == false and area.get_parent().stats.hp > 0: # hit an enemy
#if body is CharacterBody2D and body.collision_layer & (1 << 8) and body.taking_damage_timer <= 0 and body.stats.hp > 0: # Check if body is enemy (layer 9)
# Stop the arrow
velocity = Vector2.ZERO
is_stuck = true
stick_timer = 0.0
arrow_area.set_deferred("monitoring", false)
# Calculate the collision point - move arrow slightly back from its direction
var collision_normal = -direction # Opposite of arrow's direction
var offset_distance = 8 # Adjust this value based on your collision shape sizes
var stick_position = global_position + (collision_normal * offset_distance)
# Make arrow a child of the enemy to stick to it
var global_rot = global_rotation
get_parent().call_deferred("remove_child", self)
area.get_parent().call_deferred("add_child", self)
self.set_deferred("global_position", stick_position)
self.set_deferred("global_rotation", global_rot)
#global_rotation = global_rot
area.get_parent().call_deferred("take_damage", self, initiated_by)
self.call_deferred("play_impact") # need to play the sound on the next frame, because else it cuts it.
else:
$SfxImpactWall.play()
# Stop the arrow
velocity = Vector2.ZERO
is_stuck = true
stick_timer = 0.0
arrow_area.set_deferred("monitoring", false)
# You can optionally stick the arrow at the collision point if you want:
# position = body.position # Uncomment this if you want to "stick" it at the collision point
# Additional logic for handling interaction with walls or other objects
pass # Replace with function body.
func _on_arrow_area_body_entered(body: Node2D) -> void:
if not is_stuck:
if body == initiated_by:
return
$SfxImpactWall.play()
# Stop the arrow
velocity = Vector2.ZERO
is_stuck = true
stick_timer = 0.0
arrow_area.set_deferred("monitoring", false)
pass # Replace with function body.

View File

@@ -0,0 +1 @@
uid://5o1ua60xh3jr

View File

@@ -0,0 +1,76 @@
[gd_scene load_steps=10 format=3 uid="uid://bh3q00c8grsdp"]
[ext_resource type="Texture2D" uid="uid://ba772auc1t65n" path="res://assets/gfx/arrow.png" id="1_bey2v"]
[ext_resource type="Script" path="res://scripts/attacks/arrow.gd" id="1_if6eb"]
[ext_resource type="AudioStream" uid="uid://hmci4kgvbqib" path="res://assets/audio/sfx/weapons/bow/arrow_fire_swosh.wav" id="3_o8cb2"]
[ext_resource type="AudioStream" uid="uid://b140nlsak4ub7" path="res://assets/audio/sfx/weapons/bow/arrow-hit-brick-wall-01.mp3" id="4_8l43l"]
[ext_resource type="AudioStream" uid="uid://dc7nt8gnjt5u5" path="res://assets/audio/sfx/weapons/melee_attack_12.wav.mp3" id="4_ol4b0"]
[sub_resource type="Gradient" id="Gradient_yp18a"]
colors = PackedColorArray(0, 0, 0, 1, 0, 0, 0, 0)
[sub_resource type="GradientTexture2D" id="GradientTexture2D_gpny7"]
gradient = SubResource("Gradient_yp18a")
fill = 1
fill_from = Vector2(0.504587, 0.504587)
fill_to = Vector2(0.848624, 0.784404)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_b6ybh"]
size = Vector2(2, 6)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_wuwd8"]
size = Vector2(2, 8)
[node name="Arrow" type="CharacterBody2D"]
z_index = 10
y_sort_enabled = true
collision_layer = 0
collision_mask = 0
motion_mode = 1
script = ExtResource("1_if6eb")
[node name="Shadow" type="Sprite2D" parent="."]
z_index = 1
z_as_relative = false
position = Vector2(-2.98023e-08, 0)
scale = Vector2(0.09375, 0.0820313)
texture = SubResource("GradientTexture2D_gpny7")
[node name="Sprite2D" type="Sprite2D" parent="."]
texture = ExtResource("1_bey2v")
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
shape = SubResource("RectangleShape2D_b6ybh")
[node name="ArrowArea" type="Area2D" parent="."]
collision_layer = 0
collision_mask = 320
priority = 1
[node name="CollisionShape2D" type="CollisionShape2D" parent="ArrowArea"]
physics_interpolation_mode = 1
position = Vector2(0, 1)
shape = SubResource("RectangleShape2D_wuwd8")
debug_color = Color(0.7, 0, 0.195726, 0.42)
[node name="SfxArrowFire" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("3_o8cb2")
pitch_scale = 1.61
max_polyphony = 4
[node name="SfxImpactWall" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("4_8l43l")
volume_db = -4.0
pitch_scale = 1.29
attenuation = 3.4822
max_polyphony = 4
panning_strength = 1.3
[node name="SfxImpactSound" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("4_ol4b0")
volume_db = -4.685
pitch_scale = 1.47
max_polyphony = 4
[connection signal="area_entered" from="ArrowArea" to="." method="_on_arrow_area_area_entered"]
[connection signal="body_entered" from="ArrowArea" to="." method="_on_arrow_area_body_entered"]

View File

@@ -0,0 +1,64 @@
extends Node2D
var direction := Vector2.ZERO # Default direction
var fade_delay := 0.14 # When to start fading (mid-move)
var move_duration := 0.2 # Slash exists for 0.3 seconds
var fade_duration := 0.06 # Time to fade out
var stretch_amount := Vector2(1, 1.4) # How much to stretch the sprite
var slash_amount = 8
var initiated_by: Node2D = null
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
call_deferred("_initialize_swing")
pass # Replace with function body.
func _initialize_swing():
var tween = create_tween()
var move_target = global_position + (direction.normalized() * slash_amount) # Moves in given direction
tween.set_trans(Tween.TRANS_CUBIC) # Smooth acceleration & deceleration
tween.set_ease(Tween.EASE_OUT) # Fast start, then slows down
tween.tween_property(self, "global_position", move_target, move_duration)
'
# Create stretch tween (grow and shrink slightly)
var stretch_tween = create_tween()
stretch_tween.set_trans(Tween.TRANS_CUBIC)
stretch_tween.set_ease(Tween.EASE_OUT)
stretch_tween.tween_property($Sprite2D, "scale", Vector2.ONE, move_duration / 2) # start normal
stretch_tween.tween_property($Sprite2D, "scale", stretch_amount, move_duration / 2)
'
# Wait until mid-move to start fade
await get_tree().create_timer(fade_delay).timeout
# Start fade-out effect
var fade_tween = create_tween()
fade_tween.tween_property($Sprite2D, "modulate:a", 0.0, fade_duration) # Fade to transparent
await fade_tween.finished
queue_free()
pass
func _on_damage_area_body_entered(body: Node2D) -> void:
if body.get_parent() == initiated_by or body == initiated_by:
return
if body.get_parent() is CharacterBody2D and body.get_parent().stats.is_invulnerable == false and body.get_parent().stats.hp > 0: # hit an enemy
$MeleeImpact.play()
body.take_damage(self, initiated_by)
pass
else:
$MeleeImpactWall.play()
pass
pass # Replace with function body.
func _on_damage_area_area_entered(body: Area2D) -> void:
if body.get_parent() == initiated_by:
return
if body.get_parent() is CharacterBody2D and body.get_parent().stats.is_invulnerable == false and body.get_parent().stats.hp > 0: # hit an enemy
$MeleeImpact.play()
body.get_parent().take_damage(self, initiated_by)
pass
else:
$MeleeImpactWall.play()
pass
pass # Replace with function body.

View File

@@ -0,0 +1 @@
uid://cefxlk4jnptp3

View File

@@ -0,0 +1,88 @@
[gd_scene load_steps=10 format=3 uid="uid://cjqyrhyeexbxb"]
[ext_resource type="Script" path="res://scripts/attacks/axe_swing.gd" id="1_xo3v0"]
[ext_resource type="Texture2D" uid="uid://bwxpic53sluul" path="res://assets/gfx/sword_slash.png" id="2_lwt2c"]
[ext_resource type="AudioStream" uid="uid://4vulahdsj4i2" path="res://assets/audio/sfx/swoosh/throw_01.wav.mp3" id="3_v2p0x"]
[ext_resource type="AudioStream" uid="uid://uerx5rib87a6" path="res://assets/audio/sfx/weapons/bone_hit_wall_01.wav.mp3" id="4_ul7bj"]
[ext_resource type="AudioStream" uid="uid://dc7nt8gnjt5u5" path="res://assets/audio/sfx/weapons/melee_attack_12.wav.mp3" id="5_whqew"]
[sub_resource type="Animation" id="Animation_6bxep"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:modulate")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Color(1, 1, 1, 1)]
}
[sub_resource type="Animation" id="Animation_p46b1"]
resource_name = "slash_anim"
length = 0.8
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:modulate")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.533333, 0.733333),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [Color(1, 1, 1, 1), Color(1, 1, 1, 1), Color(1, 1, 1, 0)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_hj6i2"]
_data = {
&"RESET": SubResource("Animation_6bxep"),
&"slash_anim": SubResource("Animation_p46b1")
}
[sub_resource type="RectangleShape2D" id="RectangleShape2D_3jdng"]
size = Vector2(12, 12)
[node name="AxeSwing" type="Node2D"]
z_index = 10
y_sort_enabled = true
script = ExtResource("1_xo3v0")
[node name="Sprite2D" type="Sprite2D" parent="."]
texture = ExtResource("2_lwt2c")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
&"": SubResource("AnimationLibrary_hj6i2")
}
[node name="AttackSwosh" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("3_v2p0x")
pitch_scale = 0.74
autoplay = true
[node name="DamageArea" type="Area2D" parent="."]
collision_layer = 0
collision_mask = 832
[node name="CollisionShape2D" type="CollisionShape2D" parent="DamageArea"]
shape = SubResource("RectangleShape2D_3jdng")
debug_color = Color(0.7, 0, 0.18232, 0.42)
[node name="MeleeImpactWall" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("4_ul7bj")
volume_db = -4.0
pitch_scale = 1.3
max_polyphony = 4
[node name="MeleeImpact" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("5_whqew")
volume_db = -5.622
pitch_scale = 1.43
max_polyphony = 4
[connection signal="area_entered" from="DamageArea" to="." method="_on_damage_area_area_entered"]
[connection signal="body_entered" from="DamageArea" to="." method="_on_damage_area_body_entered"]

View File

@@ -0,0 +1,65 @@
extends Node2D
var direction := Vector2.ZERO # Default direction
var fade_delay := 0.14 # When to start fading (mid-move)
var move_duration := 0.2 # Slash exists for 0.3 seconds
var fade_duration := 0.06 # Time to fade out
var stretch_amount := Vector2(1, 1.4) # How much to stretch the sprite
var slash_amount = 8
var initiated_by: Node2D = null
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
call_deferred("_initialize_punch")
pass # Replace with function body.
func _initialize_punch():
$AnimationPlayer.play("punch")
var tween = create_tween()
var move_target = global_position + (direction.normalized() * slash_amount) # Moves in given direction
tween.set_trans(Tween.TRANS_CUBIC) # Smooth acceleration & deceleration
tween.set_ease(Tween.EASE_OUT) # Fast start, then slows down
tween.tween_property(self, "global_position", move_target, move_duration)
'
# Create stretch tween (grow and shrink slightly)
var stretch_tween = create_tween()
stretch_tween.set_trans(Tween.TRANS_CUBIC)
stretch_tween.set_ease(Tween.EASE_OUT)
stretch_tween.tween_property($Sprite2D, "scale", Vector2.ONE, move_duration / 2) # start normal
stretch_tween.tween_property($Sprite2D, "scale", stretch_amount, move_duration / 2)
'
# Wait until mid-move to start fade
await get_tree().create_timer(fade_delay).timeout
# Start fade-out effect
var fade_tween = create_tween()
fade_tween.tween_property($Sprite2D, "modulate:a", 0.0, fade_duration) # Fade to transparent
await fade_tween.finished
queue_free()
pass
func _on_damage_area_body_entered(body: Node2D) -> void:
if body.get_parent() == initiated_by or body == initiated_by:
return
if body.get_parent() is CharacterBody2D and body.get_parent().stats.is_invulnerable == false and body.get_parent().stats.hp > 0: # hit an enemy
$MeleeImpact.play()
body.take_damage(self, initiated_by)
pass
else:
$MeleeImpactWall.play()
pass
pass # Replace with function body.
func _on_damage_area_area_entered(body: Area2D) -> void:
if body.get_parent() == initiated_by:
return
if body.get_parent() is CharacterBody2D and body.get_parent().stats.is_invulnerable == false and body.get_parent().stats.hp > 0: # hit an enemy
$MeleeImpact.play()
body.get_parent().take_damage(self, initiated_by)
pass
else:
$MeleeImpactWall.play()
pass
pass # Replace with function body.

View File

@@ -0,0 +1 @@
uid://bkc5yi3tjw22m

View File

@@ -0,0 +1,109 @@
[gd_scene load_steps=11 format=3 uid="uid://cdef4c61y40ya"]
[ext_resource type="Script" path="res://scripts/attacks/punch.gd" id="1_8mni7"]
[ext_resource type="Texture2D" uid="uid://b7y7es36vcp8o" path="res://assets/gfx/fx/punch_fx.png" id="2_3hp7h"]
[ext_resource type="AudioStream" uid="uid://4vulahdsj4i2" path="res://assets/audio/sfx/swoosh/throw_01.wav.mp3" id="3_6lqdg"]
[ext_resource type="AudioStream" uid="uid://uerx5rib87a6" path="res://assets/audio/sfx/weapons/bone_hit_wall_01.wav.mp3" id="4_tjs11"]
[ext_resource type="AudioStream" uid="uid://dc7nt8gnjt5u5" path="res://assets/audio/sfx/weapons/melee_attack_12.wav.mp3" id="5_4f3c6"]
[sub_resource type="Animation" id="Animation_6bxep"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [0]
}
[sub_resource type="Animation" id="Animation_oq2oo"]
resource_name = "punch"
length = 0.2
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.0666667, 0.1),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 1,
"values": [0, 1, 2]
}
[sub_resource type="Animation" id="Animation_p46b1"]
resource_name = "slash_anim"
length = 0.8
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:modulate")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.533333, 0.733333),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [Color(1, 1, 1, 1), Color(1, 1, 1, 1), Color(1, 1, 1, 0)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_hj6i2"]
_data = {
&"RESET": SubResource("Animation_6bxep"),
&"punch": SubResource("Animation_oq2oo"),
&"slash_anim": SubResource("Animation_p46b1")
}
[sub_resource type="RectangleShape2D" id="RectangleShape2D_3jdng"]
size = Vector2(8, 7)
[node name="Punch" type="Node2D"]
z_index = 10
y_sort_enabled = true
script = ExtResource("1_8mni7")
[node name="Sprite2D" type="Sprite2D" parent="."]
scale = Vector2(0.5, 0.5)
texture = ExtResource("2_3hp7h")
hframes = 3
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
&"": SubResource("AnimationLibrary_hj6i2")
}
[node name="AttackSwosh" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("3_6lqdg")
pitch_scale = 0.46
autoplay = true
[node name="DamageArea" type="Area2D" parent="."]
collision_layer = 0
collision_mask = 832
[node name="CollisionShape2D" type="CollisionShape2D" parent="DamageArea"]
position = Vector2(0, 0.5)
shape = SubResource("RectangleShape2D_3jdng")
debug_color = Color(0.7, 0, 0.18232, 0.42)
[node name="MeleeImpactWall" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("4_tjs11")
volume_db = -4.0
pitch_scale = 1.3
max_polyphony = 4
[node name="MeleeImpact" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("5_4f3c6")
volume_db = -5.622
pitch_scale = 1.43
max_polyphony = 4
[connection signal="area_entered" from="DamageArea" to="." method="_on_damage_area_area_entered"]
[connection signal="body_entered" from="DamageArea" to="." method="_on_damage_area_body_entered"]

View File

@@ -0,0 +1,64 @@
extends Node2D
var direction := Vector2.ZERO # Default direction
var fade_delay := 0.14 # When to start fading (mid-move)
var move_duration := 0.2 # Slash exists for 0.3 seconds
var fade_duration := 0.06 # Time to fade out
var stretch_amount := Vector2(1, 1.4) # How much to stretch the sprite
var slash_amount = 8
var initiated_by: Node2D = null
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
call_deferred("_initialize_thrust")
pass # Replace with function body.
func _initialize_thrust():
var tween = create_tween()
var move_target = global_position + (direction.normalized() * slash_amount) # Moves in given direction
tween.set_trans(Tween.TRANS_CUBIC) # Smooth acceleration & deceleration
tween.set_ease(Tween.EASE_OUT) # Fast start, then slows down
tween.tween_property(self, "global_position", move_target, move_duration)
'
# Create stretch tween (grow and shrink slightly)
var stretch_tween = create_tween()
stretch_tween.set_trans(Tween.TRANS_CUBIC)
stretch_tween.set_ease(Tween.EASE_OUT)
stretch_tween.tween_property($Sprite2D, "scale", Vector2.ONE, move_duration / 2) # start normal
stretch_tween.tween_property($Sprite2D, "scale", stretch_amount, move_duration / 2)
'
# Wait until mid-move to start fade
await get_tree().create_timer(fade_delay).timeout
# Start fade-out effect
var fade_tween = create_tween()
fade_tween.tween_property($Sprite2D, "modulate:a", 0.0, fade_duration) # Fade to transparent
await fade_tween.finished
queue_free()
pass
func _on_damage_area_body_entered(body: Node2D) -> void:
if body.get_parent() == initiated_by or body == initiated_by:
return
if body.get_parent() is CharacterBody2D and body.get_parent().stats.is_invulnerable == false and body.get_parent().stats.hp > 0: # hit an enemy
$MeleeImpact.play()
body.take_damage(self, initiated_by)
pass
else:
$MeleeImpactWall.play()
pass
pass # Replace with function body.
func _on_damage_area_area_entered(body: Area2D) -> void:
if body.get_parent() == initiated_by:
return
if body.get_parent() is CharacterBody2D and body.get_parent().stats.is_invulnerable == false and body.get_parent().stats.hp > 0: # hit an enemy
$MeleeImpact.play()
body.get_parent().take_damage(self, initiated_by)
pass
else:
$MeleeImpactWall.play()
pass
pass # Replace with function body.

View File

@@ -0,0 +1 @@
uid://0qhn3bjmlb24

View File

@@ -0,0 +1,88 @@
[gd_scene load_steps=10 format=3 uid="uid://bgdys34sdkuwi"]
[ext_resource type="Script" path="res://scripts/attacks/spear_thrust.gd" id="1_psi1x"]
[ext_resource type="Texture2D" uid="uid://bwxpic53sluul" path="res://assets/gfx/sword_slash.png" id="2_rh1o6"]
[ext_resource type="AudioStream" uid="uid://4vulahdsj4i2" path="res://assets/audio/sfx/swoosh/throw_01.wav.mp3" id="3_j7ui3"]
[ext_resource type="AudioStream" uid="uid://uerx5rib87a6" path="res://assets/audio/sfx/weapons/bone_hit_wall_01.wav.mp3" id="4_cijfq"]
[ext_resource type="AudioStream" uid="uid://dc7nt8gnjt5u5" path="res://assets/audio/sfx/weapons/melee_attack_12.wav.mp3" id="5_h4gub"]
[sub_resource type="Animation" id="Animation_6bxep"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:modulate")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Color(1, 1, 1, 1)]
}
[sub_resource type="Animation" id="Animation_p46b1"]
resource_name = "slash_anim"
length = 0.8
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:modulate")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.533333, 0.733333),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [Color(1, 1, 1, 1), Color(1, 1, 1, 1), Color(1, 1, 1, 0)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_hj6i2"]
_data = {
&"RESET": SubResource("Animation_6bxep"),
&"slash_anim": SubResource("Animation_p46b1")
}
[sub_resource type="RectangleShape2D" id="RectangleShape2D_3jdng"]
size = Vector2(12, 12)
[node name="SpearThrust" type="Node2D"]
z_index = 10
y_sort_enabled = true
script = ExtResource("1_psi1x")
[node name="Sprite2D" type="Sprite2D" parent="."]
texture = ExtResource("2_rh1o6")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
&"": SubResource("AnimationLibrary_hj6i2")
}
[node name="AttackSwosh" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("3_j7ui3")
pitch_scale = 1.4
autoplay = true
[node name="DamageArea" type="Area2D" parent="."]
collision_layer = 0
collision_mask = 832
[node name="CollisionShape2D" type="CollisionShape2D" parent="DamageArea"]
shape = SubResource("RectangleShape2D_3jdng")
debug_color = Color(0.7, 0, 0.18232, 0.42)
[node name="MeleeImpactWall" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("4_cijfq")
volume_db = -4.0
pitch_scale = 1.3
max_polyphony = 4
[node name="MeleeImpact" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("5_h4gub")
volume_db = -5.622
pitch_scale = 1.43
max_polyphony = 4
[connection signal="area_entered" from="DamageArea" to="." method="_on_damage_area_area_entered"]
[connection signal="body_entered" from="DamageArea" to="." method="_on_damage_area_body_entered"]

View File

@@ -0,0 +1,64 @@
extends Node2D
var direction := Vector2.ZERO # Default direction
var fade_delay := 0.14 # When to start fading (mid-move)
var move_duration := 0.2 # Slash exists for 0.3 seconds
var fade_duration := 0.06 # Time to fade out
var stretch_amount := Vector2(1, 1.4) # How much to stretch the sprite
var slash_amount = 8
var initiated_by: Node2D = null
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
call_deferred("_initialize_slash")
pass # Replace with function body.
func _initialize_slash():
var tween = create_tween()
var move_target = global_position + (direction.normalized() * slash_amount) # Moves in given direction
tween.set_trans(Tween.TRANS_CUBIC) # Smooth acceleration & deceleration
tween.set_ease(Tween.EASE_OUT) # Fast start, then slows down
tween.tween_property(self, "global_position", move_target, move_duration)
'
# Create stretch tween (grow and shrink slightly)
var stretch_tween = create_tween()
stretch_tween.set_trans(Tween.TRANS_CUBIC)
stretch_tween.set_ease(Tween.EASE_OUT)
stretch_tween.tween_property($Sprite2D, "scale", Vector2.ONE, move_duration / 2) # start normal
stretch_tween.tween_property($Sprite2D, "scale", stretch_amount, move_duration / 2)
'
# Wait until mid-move to start fade
await get_tree().create_timer(fade_delay).timeout
# Start fade-out effect
var fade_tween = create_tween()
fade_tween.tween_property($Sprite2D, "modulate:a", 0.0, fade_duration) # Fade to transparent
await fade_tween.finished
queue_free()
pass
func _on_damage_area_body_entered(body: Node2D) -> void:
if body.get_parent() == initiated_by or body == initiated_by:
return
if body.get_parent() is CharacterBody2D and body.get_parent().stats.is_invulnerable == false and body.get_parent().stats.hp > 0: # hit an enemy
$MeleeImpact.play()
body.take_damage(self, initiated_by)
pass
else:
$MeleeImpactWall.play()
pass
pass # Replace with function body.
func _on_damage_area_area_entered(area: Area2D) -> void:
if area.get_parent() == initiated_by:
return
if area.get_parent() is CharacterBody2D and area.get_parent().stats.is_invulnerable == false and area.get_parent().stats.hp > 0: # hit an enemy
$MeleeImpact.play()
area.get_parent().take_damage(self,self)
pass
else:
$MeleeImpactWall.play()
pass
pass # Replace with function body.

View File

@@ -0,0 +1 @@
uid://p1jghmgvhqic

View File

@@ -0,0 +1,88 @@
[gd_scene load_steps=10 format=3 uid="uid://cfm53nbsy2e33"]
[ext_resource type="Script" uid="uid://p1jghmgvhqic" path="res://scripts/attacks/sword_slash.gd" id="1_3ef01"]
[ext_resource type="Texture2D" uid="uid://bwxpic53sluul" path="res://assets/gfx/sword_slash.png" id="1_asvt4"]
[ext_resource type="AudioStream" uid="uid://4vulahdsj4i2" path="res://assets/audio/sfx/swoosh/throw_01.wav.mp3" id="3_c1h6a"]
[ext_resource type="AudioStream" uid="uid://dc7nt8gnjt5u5" path="res://assets/audio/sfx/weapons/melee_attack_12.wav.mp3" id="4_e5miu"]
[ext_resource type="AudioStream" uid="uid://uerx5rib87a6" path="res://assets/audio/sfx/weapons/bone_hit_wall_01.wav.mp3" id="4_hx26t"]
[sub_resource type="Animation" id="Animation_6bxep"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:modulate")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Color(1, 1, 1, 1)]
}
[sub_resource type="Animation" id="Animation_p46b1"]
resource_name = "slash_anim"
length = 0.8
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:modulate")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.533333, 0.733333),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [Color(1, 1, 1, 1), Color(1, 1, 1, 1), Color(1, 1, 1, 0)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_hj6i2"]
_data = {
&"RESET": SubResource("Animation_6bxep"),
&"slash_anim": SubResource("Animation_p46b1")
}
[sub_resource type="RectangleShape2D" id="RectangleShape2D_3jdng"]
size = Vector2(12, 12)
[node name="SwordSlash" type="Node2D"]
z_index = 10
y_sort_enabled = true
script = ExtResource("1_3ef01")
[node name="Sprite2D" type="Sprite2D" parent="."]
texture = ExtResource("1_asvt4")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
&"": SubResource("AnimationLibrary_hj6i2")
}
[node name="AttackSwosh" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("3_c1h6a")
pitch_scale = 1.4
autoplay = true
[node name="DamageArea" type="Area2D" parent="."]
collision_layer = 0
collision_mask = 832
[node name="CollisionShape2D" type="CollisionShape2D" parent="DamageArea"]
shape = SubResource("RectangleShape2D_3jdng")
debug_color = Color(0.7, 0, 0.18232, 0.42)
[node name="MeleeImpactWall" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("4_hx26t")
volume_db = -4.0
pitch_scale = 1.3
max_polyphony = 4
[node name="MeleeImpact" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("4_e5miu")
volume_db = -5.622
pitch_scale = 1.43
max_polyphony = 4
[connection signal="area_entered" from="DamageArea" to="." method="_on_damage_area_area_entered"]
[connection signal="body_entered" from="DamageArea" to="." method="_on_damage_area_body_entered"]

View File

@@ -0,0 +1,24 @@
[gd_scene load_steps=4 format=3 uid="uid://dan4lcifonhd6"]
[ext_resource type="Script" uid="uid://5ik7rqtmhcxb" path="res://scripts/components/tile_particle.gd" id="1_2gfs2"]
[ext_resource type="Texture2D" uid="uid://bu4dq78f8lgj5" path="res://assets/gfx/sheet_18.png" id="2_ux51i"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_l644m"]
size = Vector2(15, 15)
[node name="TileParticle" type="CharacterBody2D"]
z_index = 17
z_as_relative = false
y_sort_enabled = true
collision_layer = 0
collision_mask = 0
script = ExtResource("1_2gfs2")
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(-0.5, -0.5)
shape = SubResource("RectangleShape2D_l644m")
[node name="Sprite2D" type="Sprite2D" parent="."]
texture = ExtResource("2_ux51i")
region_enabled = true
region_rect = Rect2(0, 0, 16, 16)

View File

@@ -0,0 +1,45 @@
extends CharacterBody2D
var friction = 8.0 # Lower values make the slowdown more gradual
var is_collected = false
var bounceTimer = 0.0
var timeBeforePickup = 0.8
# Z-axis variables
var positionZ = 4.0 # Start slightly in the air
var velocityZ = 10.0 # Initial upward velocity
var accelerationZ = -300.0 # Gravity
var bounceRestitution = 0.6 # How much bounce energy is retained (0-1)
var minBounceVelocity = 40.0 # Minimum velocity needed to bounce
var bloodTime = 2.0
func _process(delta: float) -> void:
# Update vertical movement
velocityZ += accelerationZ * delta
positionZ += velocityZ * delta
# Ground collision and bounce
if positionZ <= 0:
velocity = velocity.lerp(Vector2.ZERO, 1.0 - exp(-friction * delta)) # only slow down if on floor
positionZ = 0
velocityZ = 0
if bloodTime <= 0.0:
var fade_tween = create_tween()
fade_tween.set_trans(Tween.TRANS_CUBIC)
fade_tween.set_ease(Tween.EASE_OUT)
fade_tween.tween_property($Sprite2D, "modulate:a", 0.0, 0.5)
await fade_tween.finished
call_deferred("queue_free")
bloodTime -= delta
update_sprite_scale()
move_and_slide()
func update_sprite_scale() -> void:
# Calculate scale based on height
# Maximum height will have scale 1.3, ground will have scale 1.0
var height_factor = positionZ / 50.0 # Assuming 20 is max height
var posY = 0.0 + (2 * positionZ)
var sc = 1.0 + (0.8 * height_factor)
$Sprite2D.scale = Vector2(sc, sc)
$Sprite2D.position.y = -posY

View File

@@ -0,0 +1 @@
uid://bmr3h7slu80ps

View File

@@ -0,0 +1,28 @@
[gd_scene load_steps=5 format=3 uid="uid://cjv34dxmi1fje"]
[ext_resource type="Script" uid="uid://bkj75f0p8yp8t" path="res://assets/scripts/components/blood_clot.gd" id="1_s6bhv"]
[sub_resource type="Gradient" id="Gradient_yyyio"]
offsets = PackedFloat32Array(0)
colors = PackedColorArray(0.983734, 0.952478, 1, 1)
[sub_resource type="GradientTexture2D" id="GradientTexture2D_s6bhv"]
gradient = SubResource("Gradient_yyyio")
width = 3
height = 3
[sub_resource type="RectangleShape2D" id="RectangleShape2D_s6bhv"]
size = Vector2(1, 1)
[node name="BloodClot" type="CharacterBody2D"]
collision_layer = 0
collision_mask = 64
script = ExtResource("1_s6bhv")
[node name="Sprite2D" type="Sprite2D" parent="."]
modulate = Color(0.585938, 0, 0.0793956, 1)
scale = Vector2(0.5, 0.5)
texture = SubResource("GradientTexture2D_s6bhv")
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
shape = SubResource("RectangleShape2D_s6bhv")

View File

@@ -0,0 +1,34 @@
extends Label
@export var label: String = "1"
@export var color := Color(1, 1, 1, 1)
@export var direction := Vector2.ZERO # Default direction
var fade_delay := 0.6 # When to start fading (mid-move)
var move_duration := 0.8 # Slash exists for 0.3 seconds
var fade_duration := 0.2 # Time to fade out
var stretch_amount := Vector2(1, 1.4) # How much to stretch the sprite
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
call_deferred("_initialize_damage_number")
pass # Replace with function body.
func _initialize_damage_number() -> void:
self.modulate = color
self.text = label
var tween = create_tween()
var move_target = global_position + (direction.normalized() * 10) # Moves in given direction
tween.set_trans(Tween.TRANS_CUBIC) # Smooth acceleration & deceleration
tween.set_ease(Tween.EASE_OUT) # Fast start, then slows down
tween.tween_property(self, "global_position", move_target, move_duration)
# Wait until mid-move to start fade
await get_tree().create_timer(fade_delay).timeout
# Start fade-out effect
var fade_tween = create_tween()
fade_tween.tween_property(self, "modulate:a", 0.0, fade_duration) # Fade to transparent
await fade_tween.finished
queue_free()
pass

View File

@@ -0,0 +1 @@
uid://dkaeib51vnhsn

View File

@@ -0,0 +1,20 @@
[gd_scene load_steps=4 format=3 uid="uid://cbobah2ptwqh7"]
[ext_resource type="FontFile" uid="uid://cbmcfue0ek0tk" path="res://assets/fonts/dmg_numbers.png" id="1_q3q3r"]
[ext_resource type="Script" uid="uid://dkaeib51vnhsn" path="res://scripts/components/damage_number.gd" id="2_l584u"]
[sub_resource type="Theme" id="Theme_rmltq"]
default_font = ExtResource("1_q3q3r")
default_font_size = 8
[node name="DamageNumber" type="Label"]
light_mask = 262144
visibility_layer = 262144
z_index = 19
size_flags_horizontal = 6
size_flags_vertical = 6
theme = SubResource("Theme_rmltq")
text = "1"
horizontal_alignment = 1
vertical_alignment = 1
script = ExtResource("2_l584u")

View File

@@ -0,0 +1,22 @@
extends CharacterBody2D
var angular_velocity:float = 0.0
func _process(delta: float) -> void:
velocity = velocity.lerp(Vector2.ZERO, delta * 5.0)
if angular_velocity > 0:
rotation += angular_velocity * delta
angular_velocity = lerp(angular_velocity, 0.0, delta * 2.0)
if abs(velocity.x) < 1.0 and abs(velocity.y) < 1.0:
await get_tree().create_timer(2.0).timeout
var fade_tween = create_tween()
fade_tween.set_trans(Tween.TRANS_CUBIC)
fade_tween.set_ease(Tween.EASE_OUT)
fade_tween.tween_property($Sprite2D, "modulate:a", 0.0, 2.0)
await fade_tween.finished
call_deferred("queue_free")
pass
move_and_slide()
pass

View File

@@ -0,0 +1 @@
uid://5ik7rqtmhcxb

View File

@@ -0,0 +1,624 @@
extends RefCounted # Using RefCounted instead of Node since this is a utility class
enum DUNGEON_ENTITY_TYPES {
ENEMY,
OBJECT,
TRAP
}
# Constants
const DOOR_MODIFIERS = [
{"name": "Locked Door", "type": "Locked"},
{"name": "Bomb Wall", "type": "Bombable"}
]
const FLOOR_TILES = [
7,8,9,10,11,12,
25,26,27,28,29,30,31,
44,45,46,47,48,49,50,
63,64,65,66,67,68,69
]
const WALL_VARIATIONS = [
0.45,
0.15,
0.15,
0.15,
0.1
]
const OBJECT_TYPES = [
{"name": "Barrel", "ti": [70], "ti2": [89], "openable": false, "liftable": true, "throwable": false, "hp": - 1, "pushable": true, "size": {"x": 1, "y": 1}},
{"name": "Pot", "ti": [13, 14, 15], "ti2": [51, 52, 53], "openable": false, "liftable": true, "throwable": true, "hp": 1, "pushable": true, "size": {"x": 1, "y": 1}},
{"name": "Chest", "ti": [108], "ti2": [127], "openable": true, "liftable": false, "throwable": false, "hp": - 1, "pushable": false, "size": {"x": 1, "y": 1}},
{"name": "Bench", "ti": [35, 36], "ti2": [16, 17], "openable": false, "liftable": false, "throwable": false, "hp": - 1, "pushable": false, "size": {"x": 2, "y": 1}}
]
const MONSTER_TYPES = [
{
"name": "Goblin",
},
{
"name": "Slime",
},
# ... other monster types similar to JS version
]
const TRAP_TYPES = [
{"name": "Spike Trap", "description": "Spikes shoot up from the floor when triggered."},
{"name": "Arrow Trap", "description": "Arrows fire from the walls when a player steps on a pressure plate."},
# ... other trap types
]
const ROOM_MODIFIERS = [
{"name": "Player Start", "description": "The players start here.", "type": "START", "negative_modifiers": {"min": 0, "max": 0}},
{"name": "Exit", "description": "Room contains an exit.", "type": "EXIT", "negative_modifiers": {"min": 0, "max": 0}},
# ... other room modifiers
]
# Main generation function
func generate_dungeon(map_size: Vector2, _num_rooms: int, min_room_size: int, max_room_size: int) -> Dictionary:
# Initialize grid
var grid = []
var randgrid = []
for x in range(map_size.x):
grid.append([])
randgrid.append([])
for y in range(map_size.y):
grid[x].append(0)
randgrid[x].append(0)
var all_rooms = []
var all_doors = []
# 1. Create first room at a random position
var first_w = rand_range_i(min_room_size, max_room_size)
var first_h = rand_range_i(min_room_size, max_room_size)
var first_room = {
"x": rand_range_i(4, map_size.x - first_w - 4), # Random position with buffer
"y": rand_range_i(4, map_size.y - first_h - 4),
"w": first_w,
"h": first_h,
"modifiers": []
}
set_floor(first_room, grid, map_size)
all_rooms.append(first_room)
var nrOfDoorErrors = 0
var nrOfRoomErrors = 0
# 2. Try to place rooms until we can't fit any more
var attempts = 1000 # Prevent infinite loops
while attempts > 0 and all_rooms.size() > 0:
# Pick a random existing room
var source_room = all_rooms[randi() % all_rooms.size()]
# Try to place a new room near it
var new_room = try_place_room_near(source_room, grid, map_size, min_room_size, max_room_size)
if new_room.w > 0: # Valid room created
set_floor(new_room, grid, map_size)
all_rooms.append(new_room)
attempts -= 1
if attempts <= 0:
print("Dungeon generator:Reached maximum attempts")
nrOfRoomErrors += 1
break
# 3. Connect rooms with corridors/doors
if all_rooms.size() > 1:
var connected_rooms = {}
for room in all_rooms:
connected_rooms[room] = []
# First pass: try to connect each room to its closest neighbors
for room in all_rooms:
var closest_rooms = find_closest_rooms(room, all_rooms)
#print("Connecting room at ", room.x, ",", room.y)
var connection_attempts = 0
var max_connection_attempts = 3 # Try to connect to multiple neighbors
for target_room in closest_rooms:
if connection_attempts >= max_connection_attempts:
break
if not rooms_are_connected(room, target_room, all_doors):
var door = create_corridor_between_rooms(room, target_room, grid)
if door.size() > 0:
#print("Created direct connection between rooms")
set_door(door, grid)
all_doors.append(door)
connected_rooms[room].append(target_room)
connected_rooms[target_room].append(room)
connection_attempts += 1
# Second pass: ensure all rooms are connected
var attempts2 = 100
while attempts2 > 0:
var reachable = find_reachable_rooms(all_rooms[0], all_rooms, all_doors)
#print("Reachable rooms: ", reachable.size(), "/", all_rooms.size())
if reachable.size() == all_rooms.size():
#print("All rooms connected!")
break
# Find an unreachable room and try to connect it
for room in all_rooms:
if not reachable.has(room):
print("Found unreachable room at ", room.x, ",", room.y)
var connected = false
# Try to connect to each reachable room until success
for target_room in reachable:
var door = create_corridor_between_rooms(room, target_room, grid)
if door.size() > 0:
print("Connected unreachable room")
set_door(door, grid)
all_doors.append(door)
connected = true
break
if not connected:
print("Failed to connect room directly, trying intermediate room")
# Try creating intermediate room with multiple positions
for offset_x in [-2, 0, 2]:
for offset_y in [-2, 0, 2]:
var mid_room = create_intermediate_room(room, reachable[0], offset_x, offset_y)
if is_valid_room_position(mid_room, grid, map_size):
set_floor(mid_room, grid, map_size)
all_rooms.append(mid_room)
var door1 = create_corridor_between_rooms(room, mid_room, grid)
var door2 = create_corridor_between_rooms(mid_room, reachable[0], grid)
if door1.size() > 0 and door2.size() > 0:
set_door(door1, grid)
set_door(door2, grid)
all_doors.append(door1)
all_doors.append(door2)
connected = true
break
if connected:
break
if connected:
break
attempts2 -= 1
if attempts2 <= 0:
print("Failed to connect all rooms after maximum attempts")
nrOfDoorErrors += 1
break
for x in range(map_size.x):
for y in range(map_size.y):
if grid[x][y] == 0: # wall
var rand = randf()
var sum:float = 0.0
for i in WALL_VARIATIONS.size():
sum += WALL_VARIATIONS[i];
if rand <= sum:
randgrid[x][y] = i
break
elif grid[x][y] == 1: # floor
if randf() < 0.6:
randgrid[x][y] = 0
else:
randgrid[x][y] = randi_range(1,FLOOR_TILES.size()-1)
elif grid[x][y] == 2: # door
randgrid[x][y] = 0 # we dont care about these... only have 1 variant
var startRoomIndex = randi_range(0,all_rooms.size()-1)
all_rooms[startRoomIndex].modifiers.push_back(ROOM_MODIFIERS[0])
var farthestRoom = null
var maxDistance = 0
var exitRoomIndex = -1
var roomIndex = 0
for r in all_rooms:
var distance = abs(r.x - all_rooms[startRoomIndex].x) + abs(r.y - all_rooms[startRoomIndex].y)
if (distance > maxDistance):
maxDistance = distance
farthestRoom = r
exitRoomIndex = roomIndex
roomIndex+=1
pass
farthestRoom.modifiers.push_back(ROOM_MODIFIERS[1])
var entities = []
var TILE_SIZE = 16
roomIndex = 0
#populate rooms and decide modifiers for rooms
for r in all_rooms:
if roomIndex != startRoomIndex and roomIndex != exitRoomIndex:
var validRoomLocations = []
var min_x = (r.x + 1)
var max_x = ((r.x + r.w) - 1)
var min_y = (r.y + 1)
var max_y = ((r.y + r.h) - 1)
for rw in range(min_x,max_x):
for rh in range(min_y, max_y):
validRoomLocations.push_back(Vector2(rw*TILE_SIZE - 8, rh*TILE_SIZE - 8)) # we assume entities are 16x16 are centered
# bigger rooms can have a larger content number!
var randNrOfEntities = randi_range(0, 4)
for entI in randNrOfEntities:
var enttype:DUNGEON_ENTITY_TYPES = randi_range(0, DUNGEON_ENTITY_TYPES.size()-1) as DUNGEON_ENTITY_TYPES
var entStats = {}
# hand code to only be enemies atm
if enttype == DUNGEON_ENTITY_TYPES.TRAP:
enttype = DUNGEON_ENTITY_TYPES.OBJECT
#enttype = DUNGEON_ENTITY_TYPES.OBJECT ## only objects now...
var subtype = "goblin"
if enttype == DUNGEON_ENTITY_TYPES.ENEMY:
var randType = randi_range(0, 1)
var cStats = CharacterStats.new()
if randType == 1:
cStats.hp = 2
subtype = "slime"
else:
cStats.hp = 3
cStats.skin = "res://assets/gfx/Puny-Characters/Layer 0 - Skins/Orc1.png"
cStats.skin = "res://assets/gfx/Puny-Characters/Layer 0 - Skins/Orc2.png"
var hair = 0
if randf() > 0.6:
hair = randi_range(1,13)
cStats.setHair(hair, randi_range(0,8))
var facialhair = 0
if randf() > 0.75: # very uncommon for facial hair on goblins
facialhair = randi_range(1,3)
cStats.setFacialHair(facialhair, randi_range(0, 4))
#cStats.add_on = "res://assets/gfx/Puny-Characters/Layer 7 - Add-ons/Orc Add-ons/GoblinEars1.png"
cStats.add_on = "res://assets/gfx/Puny-Characters/Layer 7 - Add-ons/Orc Add-ons/GoblinEars2.png"
#cStats.add_on = "res://assets/gfx/Puny-Characters/Layer 7 - Add-ons/Orc Add-ons/OrcJaw1.png"
#cStats.add_on = "res://assets/gfx/Puny-Characters/Layer 7 - Add-ons/Orc Add-ons/OrcJaw2.png"
# randomize if the goblin will have a weapon like dagger or sword
# randomize if the goblin will have bow and arrows also
# randomize if the goblin will have an armour and helmet etc.
entStats = cStats.save()
elif enttype == DUNGEON_ENTITY_TYPES.OBJECT:
subtype = "pot"
else:
subtype = "spike"
var posI = randi_range(0, validRoomLocations.size()-1)
var entity = {
"type": enttype,
"subtype": subtype,
"stats": entStats,
"position": {
"x": validRoomLocations[posI].x,
"y": validRoomLocations[posI].y
}
}
entities.push_back(entity)
validRoomLocations.remove_at(posI) # this is now occupied... don't allow anything else spawn on it.
# fill up modifiers per room
if ROOM_MODIFIERS.size() > 2:
r.modifiers.push_back(ROOM_MODIFIERS[randi_range(2, ROOM_MODIFIERS.size()-2)])
pass
roomIndex += 1
return {
"rooms": all_rooms,
"entities": entities,
"doors": all_doors,
"grid": grid,
"randgrid": randgrid, # grid containing actual tile index-ish(ish)
"mapSize": map_size,
"nrOfDoorErrors": nrOfDoorErrors,
"nrOfRoomErrors": nrOfRoomErrors
}
# Helper functions
func create_random_room(map_size: Vector2, min_size: int, max_size: int) -> Dictionary:
var x = randi() % (int(map_size.x) - max_size - 2) + 1
var y = randi() % (int(map_size.y) - max_size - 2) + 1
var w = rand_range_i(min_size, max_size)
var h = rand_range_i(min_size, max_size)
return {"x": x, "y": y, "w": w, "h": h, "modifiers": []}
func rand_range_i(min_val: int, max_val: int) -> int:
return min_val + (randi() % (max_val - min_val + 1))
func set_floor(room: Dictionary, grid: Array, map_size: Vector2) -> void:
for x in range(room.x, room.x + room.w):
for y in range(room.y, room.y + room.h):
if x >= 0 and x < map_size.x and y >= 0 and y < map_size.y:
grid[x][y] = 1 # Set as floor tile
# ... Additional helper functions and implementation details would follow ...
# ... previous code ...
func try_place_room_near(source_room: Dictionary, grid: Array, map_size: Vector2,
min_room_size: int, max_room_size: int) -> Dictionary:
var attempts = 20
while attempts > 0:
var w = rand_range_i(min_room_size, max_room_size)
var h = rand_range_i(min_room_size, max_room_size)
# Try all four sides of the source room
var sides = ["N", "S", "E", "W"]
sides.shuffle()
for side in sides:
var x = source_room.x
var y = source_room.y
match side:
"N":
x = source_room.x + (randi() % max(1, source_room.w - w))
y = source_room.y - h - 4 # 4 tiles away
"S":
x = source_room.x + (randi() % max(1, source_room.w - w))
y = source_room.y + source_room.h + 4
"W":
x = source_room.x - w - 4
y = source_room.y + (randi() % max(1, source_room.h - h))
"E":
x = source_room.x + source_room.w + 4
y = source_room.y + (randi() % max(1, source_room.h - h))
if is_valid_room_position({"x": x, "y": y, "w": w, "h": h}, grid, map_size):
return {"x": x, "y": y, "w": w, "h": h, "modifiers": []}
attempts -= 1
return {"x": 0, "y": 0, "w": 0, "h": 0, "modifiers": []}
func find_closest_rooms(room: Dictionary, all_rooms: Array) -> Array:
if all_rooms.size() <= 1:
return []
var distances = []
for other in all_rooms:
if other == room:
continue
var dist = abs(room.x - other.x) + abs(room.y - other.y)
distances.append({"room": other, "distance": dist})
# Sort by distance
if distances.size() > 0:
distances.sort_custom(func(a, b): return a.distance < b.distance)
# Return the rooms only, in order of distance
return distances.map(func(item): return item.room)
return []
func rooms_are_connected(room1: Dictionary, room2: Dictionary, doors: Array) -> bool:
for door in doors:
if (door.room1 == room1 and door.room2 == room2) or \
(door.room1 == room2 and door.room2 == room1):
return true
return false
func create_corridor_between_rooms(room1: Dictionary, room2: Dictionary, _grid: Array) -> Dictionary:
# Determine if rooms are more horizontal or vertical from each other
var dx = abs(room2.x - room1.x)
var dy = abs(room2.y - room1.y)
# Check if rooms are too far apart (more than 8 tiles)
if dx > 8 and dy > 8:
return {}
if dx > dy:
# Horizontal corridor
var leftRoom = room1 if room1.x < room2.x else room2
var rightRoom = room2 if room1.x < room2.x else room1
# Check if rooms are horizontally adjacent (gap should be reasonable)
if rightRoom.x - (leftRoom.x + leftRoom.w) > 8:
return {}
# Door must start at the right edge of left room plus 1 tile gap
var door_x = leftRoom.x + leftRoom.w
# Door y must be within both rooms' height ranges, accounting for walls
var min_y = max(leftRoom.y + 1, rightRoom.y + 1) # +1 to account for walls
var max_y = min(leftRoom.y + leftRoom.h - 2, rightRoom.y + rightRoom.h - 2) # -2 to ensure both tiles fit
# Make sure we have a valid range
if max_y < min_y:
return {}
# Pick a valid y position within the range
var door_y = min_y + (randi() % max(1, max_y - min_y + 1))
# Calculate actual width needed (distance between rooms)
var door_width = rightRoom.x - (leftRoom.x + leftRoom.w + 1)
# Use the larger of minimum width (4) or actual distance
door_width = max(4, door_width + 1)
# Create door with calculated width
var door = {
"x": door_x,
"y": door_y,
"w": door_width, # Use calculated width
"h": 2, # Fixed height for horizontal doors
"dir": "E" if leftRoom == room1 else "W",
"room1": room1,
"room2": room2
}
return door
else:
# Vertical corridor
var topRoom = room1 if room1.y < room2.y else room2
var bottomRoom = room2 if room1.y < room2.y else room1
# Check if rooms are vertically adjacent (gap should be reasonable)
if bottomRoom.y - (topRoom.y + topRoom.h) > 8:
return {}
# Door must start at the bottom edge of top room plus 1 tile gap
var door_y = topRoom.y + topRoom.h
# Door x must be within both rooms' width ranges, accounting for walls
var min_x = max(topRoom.x + 1, bottomRoom.x + 1) # +1 to account for walls
var max_x = min(topRoom.x + topRoom.w - 2, bottomRoom.x + bottomRoom.w - 2) # -2 to ensure both tiles fit
# Make sure we have a valid range
if max_x < min_x:
return {}
# Pick a valid x position within the range
var door_x = min_x + (randi() % max(1, max_x - min_x + 1))
# Calculate actual height needed (distance between rooms)
var door_height = bottomRoom.y - (topRoom.y + topRoom.h + 1)
# Use the larger of minimum height (4) or actual distance
door_height = max(4, door_height + 1)
# Create door with calculated height
var door = {
"x": door_x,
"y": door_y,
"w": 2, # Fixed width for vertical doors
"h": door_height, # Use calculated height
"dir": "S" if topRoom == room1 else "N",
"room1": room1,
"room2": room2
}
return door
func add_room_modifiers(rooms: Array) -> void:
# Add start room modifier to first room
rooms[0].modifiers.append(ROOM_MODIFIERS[0]) # START modifier
# Add exit to last room
rooms[-1].modifiers.append(ROOM_MODIFIERS[1]) # EXIT modifier
# Add random modifiers to other rooms
for i in range(1, rooms.size() - 1):
if randf() < 0.3: # 30% chance for a modifier
var available_modifiers = ROOM_MODIFIERS.slice(2, ROOM_MODIFIERS.size())
# Only add modifier if there are available ones
if available_modifiers.size() > 0:
rooms[i].modifiers.append(available_modifiers[randi() % available_modifiers.size()])
func generate_all_room_objects(rooms: Array, doors: Array) -> Array:
var room_objects = []
# Generate objects for each room
for room in rooms:
var objects = generate_room_objects(room)
room_objects.append_array(objects)
# Add door modifiers
for door in doors:
if randf() < 0.2: # 20% chance for door modifier
var modifier = DOOR_MODIFIERS[randi() % DOOR_MODIFIERS.size()]
room_objects.append({
"type": "Door",
"x": door.x,
"y": door.y,
"modifier": modifier
})
return room_objects
func generate_room_objects(room: Dictionary) -> Array:
var objects = []
var max_objects = int((room.w * room.h) / 16) # Roughly one object per 16 tiles
for _i in range(max_objects):
if randf() < 0.7: # 70% chance to place each potential object
var obj_type = OBJECT_TYPES[randi() % OBJECT_TYPES.size()]
var x = rand_range_i(room.x + 1, room.x + room.w - obj_type.size.x - 1)
var y = rand_range_i(room.y + 1, room.y + room.h - obj_type.size.y - 1)
# Check if position is free
var can_place = true
for obj in objects:
if abs(obj.x - x) < 2 and abs(obj.y - y) < 2:
can_place = false
break
if can_place:
objects.append({
"type": obj_type.name,
"x": x,
"y": y,
"properties": obj_type
})
return objects
func set_door(door: Dictionary, grid: Array) -> void:
match door.dir:
"N", "S":
if door.h > 4:
print("ns - larger door", door.h)
# Set 2x4 corridor
for dx in range(2):
for dy in range(door.h):
#if grid[door.x + dx][door.y + dy] != 1: # Don't overwrite room
grid[door.x + dx][door.y + dy] = 2
"E", "W":
if door.w > 4:
print("ew - larger door", door.w)
# Set 4x2 corridor
for dx in range(door.w):
for dy in range(2):
#if grid[door.x + dx][door.y + dy] != 1: # Don't overwrite room
grid[door.x + dx][door.y + dy] = 2
func is_valid_room_position(room: Dictionary, grid: Array, map_size: Vector2) -> bool:
# Check if room is within map bounds with buffer
if room.x < 4 or room.y < 4 or room.x + room.w >= map_size.x - 4 or room.y + room.h >= map_size.y - 4:
#print("Room outside map bounds")
return false
# Check if room overlaps with existing rooms or corridors
# Check the actual room area plus 4-tile buffer for spacing
for x in range(room.x - 4, room.x + room.w + 4):
for y in range(room.y - 4, room.y + room.h + 4):
if x >= 0 and x < map_size.x and y >= 0 and y < map_size.y:
if grid[x][y] != 0: # If tile is not empty
#print("Room overlaps at ", Vector2(x, y))
return false
return true
# Add this helper function to check room connectivity
func find_reachable_rooms(start_room: Dictionary, _all_rooms: Array, all_doors: Array) -> Array:
var reachable = [start_room]
var queue = [start_room]
while queue.size() > 0:
var current = queue.pop_front()
for door in all_doors:
var next_room = null
if door.room1 == current:
next_room = door.room2
elif door.room2 == current:
next_room = door.room1
if next_room != null and not reachable.has(next_room):
reachable.append(next_room)
queue.append(next_room)
return reachable
func create_intermediate_room(room1: Dictionary, room2: Dictionary, offset_x: int, offset_y: int) -> Dictionary:
return {
"x": room1.x + (room2.x - room1.x) / 2 + offset_x,
"y": room1.y + (room2.y - room1.y) / 2 + offset_y,
"w": 6,
"h": 6,
"modifiers": []
}

View File

@@ -0,0 +1 @@
uid://b0o8i0uuloh7d

View File

@@ -0,0 +1,661 @@
class_name CharacterStats
extends Resource
signal health_changed(new_health: float, max_health: float)
signal mana_changed(new_mana: float, max_mana: float)
signal level_changed(new_level: int)
signal xp_changed(new_xp: float, xp_to_next: float)
signal no_health
signal character_changed(char: CharacterStats)
signal signal_drop_item(item: Item)
var character_type: String = "enemy"
@export var level: int = 1
@export var character_name: String = ""
@export var xp: float = 0
@export var hp: float = 30.0
@export var mp: float = 20.0
# default skin is human1
var skin:String = "res://assets/gfx/Puny-Characters/Layer 0 - Skins/Human1.png"
# default no values for these:
var facial_hair:String = ""
var facial_hair_color:Color = Color.WHITE
var hairstyle:String = ""
var hair_color:Color = Color.WHITE
var eyes:String = ""
var eye_lashes:String = ""
var add_on:String = ""
var bonusmaxhp: float = 0.0
var bonusmaxmp: float = 0.0
@export var coin: int = 0
@export var is_invulnerable: bool = false
var kills: int = 0
var deaths: int = 0
#calculated values
var stats:Array = [
5,
4,
5,
3,
1,
1,
0,
10,
10
]
var inventory: Array = []
# mainhand, offhand, headgear, body, feet, accessory (6 total)
var equipment:Dictionary = {
"mainhand": null,
"offhand": null,
"headgear": null,
"armour": null,
"boots": null,
"accessory": null
}
@export var baseStats = {
"str": 10,
"dex": 10,
"int": 10,
"end": 10,
"wis": 10,
"cha": 10,
"lck": 10
}
@export var def: int = 0
@export var resistances = {
"fire": 0,
"cold": 0,
"lightning": 0,
"poison": 0,
"magic": 0,
"holy": 0,
"dark": 0
}
func getCalculatedStats():
var _res = {
"str": self.str,
"dex": self.dex,
"int": self.int,
"end": self.end,
"wis": self.wis,
"cha": self.cha,
"lck": self.lck,
"damage": self.damage,
"defense": self.defense
}
if equipment["mainhand"] != null:
pass
pass
func get_pass(iStr:String):
var cnt = 0
if equipment["mainhand"] != null:
for key in equipment["mainhand"].modifiers.keys():
if key == iStr:
cnt += equipment["mainhand"].modifiers[key]
pass
pass
if equipment["offhand"] != null:
for key in equipment["offhand"].modifiers.keys():
if key == iStr:
cnt += equipment["offhand"].modifiers[key]
pass
pass
if equipment["headgear"] != null:
for key in equipment["headgear"].modifiers.keys():
if key == iStr:
cnt += equipment["headgear"].modifiers[key]
pass
pass
if equipment["armour"] != null:
for key in equipment["armour"].modifiers.keys():
if key == iStr:
cnt += equipment["armour"].modifiers[key]
pass
pass
if equipment["boots"] != null:
for key in equipment["boots"].modifiers.keys():
if key == iStr:
cnt += equipment["boots"].modifiers[key]
pass
pass
if equipment["accessory"] != null:
for key in equipment["accessory"].modifiers.keys():
if key == iStr:
cnt += equipment["accessory"].modifiers[key]
pass
pass
return cnt
# Derived stats as properties
var maxhp: float:
get:
return (baseStats.end + get_pass("end")) * 3.0 + bonusmaxhp + get_pass("maxhp")
var maxmp: float:
get:
return (baseStats.wis + get_pass("wis")) * 2.0 + bonusmaxmp + get_pass("maxmp")
var damage: float:
get:
return (baseStats.str + get_pass("str")) * 0.2 + get_pass("dmg")
var defense: float:
get:
return ((baseStats.end + get_pass("end")) * 0.3) + get_pass("def")
var spell_amp: float:
get:
return (baseStats.int + get_pass("int")) * 0.5
var move_speed: float:
get:
return 2.0 + ((baseStats.dex + get_pass("dex")) * 0.01)
var attack_speed: float:
get:
return 1.0 + ((baseStats.dex + get_pass("dex")) * 0.04)
var sight: float:
get:
return 5.0 + ((baseStats.int + get_pass("int")) * 0.05)
var crit_chance: float:
get:
return (baseStats.lck + get_pass("lck")) * 1.2
var xp_to_next_level: float:
get:
return pow(level * 10, 1.5)
func _init() -> void:
hp = maxhp
mp = maxmp
func add_xp(amount: float) -> void:
xp += amount
xp_changed.emit(xp, xp_to_next_level)
while xp >= xp_to_next_level:
level_up()
# instead of automatically update all stats, maybe let the player choose which stats to level up.
func level_up() -> void:
level += 1
xp -= xp_to_next_level
# Increase stats
baseStats.str += 1
baseStats.dex += 1
baseStats.int += 1
baseStats.end += 1
baseStats.wis += 1
baseStats.cha += 1
baseStats.lck += 1
# Restore health and mana on level up
hp = maxhp
mp = maxmp
level_changed.emit(level)
health_changed.emit(hp, maxhp)
mana_changed.emit(mp, maxmp)
func modify_health(amount: float) -> void:
hp = clamp(hp + amount, 0, maxhp)
health_changed.emit(hp, maxhp)
character_changed.emit(self)
func modify_mana(amount: float) -> void:
mp = clamp(mp + amount, 0, maxmp)
mana_changed.emit(mp, maxmp)
character_changed.emit(self)
func calculate_damage(base_damage: float, is_magical: bool = false) -> float:
if is_magical:
return base_damage * (1 - (resistances.magic / 100.0))
return base_damage * (1 - (defense / 100.0))
func take_damage(amount: float, is_magical: bool = false) -> float:
var actual_damage = calculate_damage(amount, is_magical)
modify_health(-actual_damage)
if hp <= 0:
no_health.emit() # Emit when health reaches 0
character_changed.emit(self)
return actual_damage
func heal(amount: float) -> void:
modify_health(amount)
func use_mana(amount: float) -> bool:
if mp >= amount:
modify_mana(-amount)
return true
return false
func restore_mana(amount: float) -> void:
modify_mana(amount)
func saveInventory() -> Array:
var inventorySave = []
for it:Item in inventory:
inventorySave.push_back(it.save())
return inventorySave
func saveEquipment() -> Dictionary:
var eqSave = {
"mainhand": equipment["mainhand"].save() if equipment["mainhand"] != null else null,
"offhand": equipment["offhand"].save() if equipment["offhand"] != null else null,
"headgear": equipment["headgear"].save() if equipment["headgear"] != null else null,
"armour": equipment["armour"].save() if equipment["armour"] != null else null,
"boots": equipment["boots"].save() if equipment["boots"] != null else null,
"accessory": equipment["accessory"].save() if equipment["accessory"] != null else null
}
return eqSave
func loadInventory(iArr: Array):
inventory.clear() # remove previous content
for iDic in iArr:
if iDic != null:
inventory.push_back( Item.new(iDic) )
pass
func loadEquipment(iDic: Dictionary):
equipment["mainhand"] = Item.new(iDic.get("mainhand")) if iDic.has("mainhand") and iDic.get("mainhand") != null else null
equipment["offhand"] = Item.new(iDic.get("offhand")) if iDic.has("offhand") and iDic.get("offhand") != null else null
equipment["headgear"] = Item.new(iDic.get("headgear")) if iDic.has("headgear") and iDic.get("headgear") != null else null
equipment["armour"] = Item.new(iDic.get("armour")) if iDic.has("armour") and iDic.get("armour") != null else null
equipment["boots"] = Item.new(iDic.get("boots")) if iDic.has("boots") and iDic.get("boots") != null else null
equipment["accessory"] = Item.new(iDic.get("accessory")) if iDic.has("accessory") and iDic.get("accessory") != null else null
pass
func save() -> Dictionary:
var json = {
"level": level,
"character_type": character_type,
"character_name": character_name,
"baseStats": baseStats,
"hp": hp,
"mp": mp,
"bonusmaxhp": bonusmaxhp,
"bonusmaxmp": bonusmaxmp,
"exp": xp,
"coin": coin,
"kills": kills,
"deaths": deaths,
"skin": skin,
"facial_hair": facial_hair,
"hairstyle": hairstyle,
"eyes": eyes,
"eye_lashes": eye_lashes,
"add_on": add_on,
"facial_hair_color": facial_hair_color.to_html(true),
"hair_color": hair_color.to_html(true),
"inventory": saveInventory(),
"equipment": saveEquipment()
}
return json
func load(iDic: Dictionary) -> void:
if iDic.has("level"):
level = iDic.get("level")
if iDic.has("character_type"):
character_type = iDic.get("character_type")
if iDic.has("character_name"):
character_name = iDic.get("character_name")
if iDic.has("hp"):
hp = iDic.get("hp")
if iDic.has("mp"):
mp = iDic.get("mp")
if iDic.has("bonusmaxhp"):
bonusmaxhp = iDic.get("bonusmaxhp")
if iDic.has("bonusmaxmp"):
bonusmaxmp = iDic.get("bonusmaxmp")
if iDic.has("baseStats"):
baseStats = iDic.get("baseStats")
if iDic.has("coin"):
coin = iDic.get("coin")
if iDic.has("exp"):
xp = iDic.get("exp")
if iDic.has("kills"):
kills = iDic.get("kills")
if iDic.has("deaths"):
deaths = iDic.get("deaths")
inventory.clear()
if iDic.has("inventory"):
loadInventory(iDic.get("inventory"))
# reset equipment
equipment = {
"mainhand": null,
"offhand": null,
"headgear": null,
"armour": null,
"boots": null,
"accessory": null
}
if iDic.has("equipment"):
loadEquipment(iDic.get("equipment"))
if iDic.has("skin"):
skin = iDic.get("skin")
if iDic.has("facial_hair"):
facial_hair = iDic.get("facial_hair")
if iDic.has("hairstyle"):
hairstyle = iDic.get("hairstyle")
if iDic.has("eyes"):
eyes = iDic.get("eyes")
if iDic.has("eye_lashes"):
eye_lashes = iDic.get("eye_lashes")
if iDic.has("add_on"):
add_on = iDic.get("add_on")
if iDic.has("facial_hair_color"):
facial_hair_color = Color(iDic.get("facial_hair_color"))
if iDic.has("hair_color"):
hair_color = Color(iDic.get("hair_color"))
pass
'
func calculateStats():
for i in stats.size():
stats[i] = baseStats[i]
pass
stats[PlayerData.STAT.STAT_ATK] = 1 # defaults to 1
# add equipment modifiers:
for eq in equipped:
if eq >= 0:
for modifier in equipment[eq]["equipment"].modifiers:
stats[modifier["stat"] as PlayerData.STAT] += modifier["change"]
pass
pass
pass'
func add_coin(iAmount:int):
coin += iAmount
emit_signal("character_changed", self)
pass
func drop_item(iItem:Item):
var index = 0
for item in inventory:
if item == iItem:
break
index+=1
inventory.remove_at(index)
emit_signal("signal_drop_item", iItem)
emit_signal("character_changed", self)
pass
func drop_equipment(iItem:Item):
unequip_item(iItem, false)
# directly remove the item from the inventory
drop_item(iItem)
pass
func add_item(iItem:Item):
print("Adding item to player:", character_name, " item being added:", iItem)
self.inventory.push_back(iItem)
emit_signal("character_changed", self)
pass
func unequip_item(iItem:Item, updateChar:bool = true):
if iItem.equipment_type == Item.EquipmentType.NONE:
return
self.inventory.push_back(iItem)
match iItem.equipment_type:
Item.EquipmentType.MAINHAND:
equipment["mainhand"] = null
pass
Item.EquipmentType.OFFHAND:
equipment["offhand"] = null
pass
Item.EquipmentType.HEADGEAR:
equipment["headgear"] = null
pass
Item.EquipmentType.ARMOUR:
equipment["armour"] = null
pass
Item.EquipmentType.BOOTS:
equipment["boots"] = null
pass
Item.EquipmentType.ACCESSORY:
equipment["accessory"] = null
pass
pass
if updateChar:
emit_signal("character_changed", self)
pass
func forceUpdate():
emit_signal("character_changed", self)
pass
func equip_item(iItem:Item):
if iItem.equipment_type == Item.EquipmentType.NONE:
return
match iItem.equipment_type:
Item.EquipmentType.MAINHAND:
if equipment["mainhand"] != null:
self.inventory.push_back(equipment["mainhand"])
# If we equip different weapon than bow and we have ammunition in offhand, remove, the offhand.
# If we equip two handed weapon, remove offhand...
#if equipment["offhand"] != null:
#(equipment["offhand"] as Item).equipment_type == Item.WeaponType.AMMUNITION
#if iItem.WeaponType.BOW
equipment["mainhand"] = iItem
pass
pass
Item.EquipmentType.OFFHAND:
if equipment["offhand"] != null:
self.inventory.push_back(equipment["offhand"])
equipment["offhand"] = iItem
pass
pass
Item.EquipmentType.HEADGEAR:
if equipment["headgear"] != null:
self.inventory.push_back(equipment["headgear"])
equipment["headgear"] = iItem
pass
pass
Item.EquipmentType.ARMOUR:
if equipment["armour"] != null:
self.inventory.push_back(equipment["armour"])
equipment["armour"] = iItem
pass
pass
Item.EquipmentType.BOOTS:
if equipment["boots"] != null:
self.inventory.push_back(equipment["boots"])
equipment["boots"] = iItem
pass
pass
Item.EquipmentType.ACCESSORY:
if equipment["accessory"] != null:
self.inventory.push_back(equipment["accessory"])
equipment["accessory"] = iItem
pass
pass
self.inventory.remove_at(self.inventory.find(iItem))
emit_signal("character_changed", self)
pass
func setSkin(iValue:int):
if iValue < 0 or iValue > 6:
return
skin = "res://assets/gfx/Puny-Characters/Layer 0 - Skins/Human" + str(iValue+1) + ".png"
emit_signal("character_changed", self)
pass
func setFacialHair(iType:int):
if iType < 0 or iType > 3:
return
match iType:
0:
facial_hair = ""
emit_signal("character_changed", self)
return
1:
facial_hair = "res://assets/gfx/Puny-Characters/Layer 4 - Hairstyle/Facial Hairstyles/Beardstyle1"
pass
2:
facial_hair = "res://assets/gfx/Puny-Characters/Layer 4 - Hairstyle/Facial Hairstyles/Beardstyle2"
pass
3:
facial_hair = "res://assets/gfx/Puny-Characters/Layer 4 - Hairstyle/Facial Hairstyles/Mustache1"
pass
facial_hair += "White.png"
emit_signal("character_changed", self)
pass
func setHair(iType:int):
if iType < 0 or iType > 12:
return
if iType == 0:
hairstyle = ""
emit_signal("character_changed", self)
return
hairstyle = "res://assets/gfx/Puny-Characters/Layer 4 - Hairstyle/Hairstyles/FHairstyle" + str(iType)
if iType >= 5: # male hairstyles
hairstyle = "res://assets/gfx/Puny-Characters/Layer 4 - Hairstyle/Hairstyles/MHairstyle" + str(iType-4)
hairstyle += "White.png"
print("resulting hairstyle should be:", hairstyle)
emit_signal("character_changed", self)
pass
func setEyeLashes(iEyeLashes: int):
if iEyeLashes < 0 or iEyeLashes > 8:
print("Eye lash value out of range 0 to 9", iEyeLashes)
return
if iEyeLashes == 0:
eye_lashes = ""
else:
match iEyeLashes:
1:
eye_lashes = "res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eyelashes/FEyelash1.png"
pass
2:
eye_lashes = "res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eyelashes/FEyelash2.png"
pass
3:
eye_lashes = "res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eyelashes/FEyelash3.png"
pass
4:
eye_lashes = "res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eyelashes/MEyelash1.png"
pass
5:
eye_lashes = "res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eyelashes/MEyelash2.png"
pass
6:
eye_lashes = "res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eyelashes/NEyelash1.png"
pass
7:
eye_lashes = "res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eyelashes/NEyelash2.png"
pass
8:
eye_lashes = "res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eyelashes/NEyelash3.png"
pass
emit_signal("character_changed", self)
pass
func setEyes(iEyes: int):
if iEyes < 0 or iEyes > 14:
print("Eye color value out of range 0 to 14", iEyes)
return
if iEyes == 0:
eyes = ""
else:
match iEyes:
1:
eyes = "res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eye Color/EyecolorBlack.png"
pass
2:
eyes = "res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eye Color/EyecolorBlue.png"
pass
3:
eyes = "res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eye Color/EyecolorCyan.png"
pass
4:
eyes = "res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eye Color/EyecolorDarkBlue.png"
pass
5:
eyes = "res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eye Color/EyecolorDarkCyan.png"
pass
6:
eyes = "res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eye Color/EyecolorDarkLime.png"
pass
7:
eyes = "res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eye Color/EyecolorDarkRed.png"
pass
8:
eyes = "res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eye Color/EyecolorFullBlack.png"
pass
9:
eyes = "res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eye Color/EyecolorFullWhite.png"
pass
10:
eyes = "res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eye Color/EyecolorGray.png"
pass
11:
eyes = "res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eye Color/EyecolorLightLime.png"
pass
12:
eyes = "res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eye Color/EyecolorOrange.png"
pass
13:
eyes = "res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eye Color/EyecolorRed.png"
pass
14:
eyes = "res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eye Color/EyecolorYellow.png"
pass
emit_signal("character_changed", self)
pass
func setEars(iEars: int):
if iEars < 0 or iEars > 7:
print("Ear value out of range 0 to 7", iEars)
return
if iEars == 0:
add_on = ""
else:
add_on = "res://assets/gfx/Puny-Characters/Layer 7 - Add-ons/Elf Add-ons/ElfEars" + str(iEars) + ".png"
emit_signal("character_changed", self)
pass
func setFacialHairColor(iColor: Color):
facial_hair_color = iColor
emit_signal("character_changed", self)
pass
func setHairColor(iColor:Color):
hair_color = iColor
emit_signal("character_changed", self)
pass

View File

@@ -0,0 +1 @@
uid://qypk3dppiibf

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
uid://dhrlybbkwfyqr

View File

@@ -0,0 +1,383 @@
[gd_scene load_steps=41 format=3 uid="uid://b15qv06j2v5mq"]
[ext_resource type="Script" uid="uid://dhrlybbkwfyqr" path="res://assets/scripts/entities/enemies/goblin/goblin.gd" id="1_muqri"]
[ext_resource type="AudioStream" uid="uid://dtydo3gymnrcv" path="res://assets/audio/sfx/enemies/goblin/die1.mp3" id="2_jcncw"]
[ext_resource type="Texture2D" uid="uid://caq1ig4sdicos" path="res://assets/gfx/Puny-Characters/Layer 0 - Skins/Orc2.png" id="2_xx2fg"]
[ext_resource type="AudioStream" uid="uid://c3fqe3i3qbl8x" path="res://assets/audio/sfx/enemies/goblin/die2.mp3" id="3_6e00w"]
[ext_resource type="Texture2D" uid="uid://b3rba26046knv" path="res://assets/gfx/Puny-Characters/Layer 2 - Clothes/Armour Body/GoldArmour.png" id="3_876ij"]
[ext_resource type="Shader" uid="uid://b1k834hb0xm2w" path="res://assets/shaders/draw_sprite_above.gdshader" id="4_8og43"]
[ext_resource type="AudioStream" uid="uid://dlgavklpnx0rs" path="res://assets/audio/sfx/enemies/goblin/raargh.mp3" id="4_xx2fg"]
[ext_resource type="AudioStream" uid="uid://cvh7dfc4hshsb" path="res://assets/audio/sfx/enemies/goblin/raargh2.mp3" id="5_876ij"]
[ext_resource type="Texture2D" uid="uid://cxp2kxvigtcwi" path="res://assets/gfx/Puny-Characters/Layer 4 - Hairstyle/Facial Hairstyles/Beardstyle1Blond.png" id="5_u6mrb"]
[ext_resource type="AudioStream" uid="uid://cbvxokqp1bxar" path="res://assets/audio/sfx/enemies/goblin/raargh3.mp3" id="6_2t7lq"]
[ext_resource type="Texture2D" uid="uid://circuqey2gqgj" path="res://assets/gfx/Puny-Characters/Layer 4 - Hairstyle/Hairstyles/M Hairstyle 9/MHairstyle9Cyan.png" id="6_nift8"]
[ext_resource type="AudioStream" uid="uid://dscx61fdkejlt" path="res://assets/audio/sfx/enemies/goblin/ive_been_waiting_for_this.mp3" id="7_8og43"]
[ext_resource type="Texture2D" uid="uid://cmhi3ns2fgx7i" path="res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eye Color/EyecolorBlack.png" id="7_pococ"]
[ext_resource type="Texture2D" uid="uid://b4vh2v0x58v2f" path="res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eyelashes/MEyelash1.png" id="8_rsnib"]
[ext_resource type="AudioStream" uid="uid://ban8uv8hifsgc" path="res://assets/audio/sfx/enemies/goblin/stay_back_if_you_wanna_keep_your_head.mp3" id="8_v3qiy"]
[ext_resource type="AudioStream" uid="uid://dil4kftgybqcs" path="res://assets/audio/sfx/enemies/goblin/wait_til_i_blow_my_horn.mp3" id="9_jp84j"]
[ext_resource type="Texture2D" uid="uid://dx1fovugabbwc" path="res://assets/gfx/Puny-Characters/Layer 1 - Shoes/IronBoots.png" id="9_v458m"]
[ext_resource type="Texture2D" uid="uid://bkaam8riwwft4" path="res://assets/gfx/Puny-Characters/Layer 6 - Headgears/Basic Range/ArcherHatCyan.png" id="10_a3dd1"]
[ext_resource type="AudioStream" uid="uid://b0jm6abkgm1dv" path="res://assets/audio/sfx/enemies/goblin/your_mine.mp3" id="10_jqf8r"]
[ext_resource type="AudioStream" uid="uid://bhiqb5ppt3ktg" path="res://assets/audio/sfx/enemies/goblin/hey.mp3" id="11_6e00w"]
[ext_resource type="Texture2D" uid="uid://7ubmf453qlu" path="res://assets/gfx/Puny-Characters/Layer 7 - Add-ons/Orc Add-ons/OrcJaw2.png" id="11_vflxt"]
[ext_resource type="Texture2D" uid="uid://bloqx3mibftjn" path="res://assets/gfx/Puny-Characters/WeaponOverlayer.png" id="12_ry8ej"]
[ext_resource type="Texture2D" uid="uid://dxk8dcdqrft0v" path="res://assets/gfx/gibb_sprite.png" id="14_2t7lq"]
[sub_resource type="Shader" id="Shader_oa0y8"]
code = "shader_type canvas_item;
uniform float opacity;
uniform float r;
uniform float g;
uniform float b;
uniform float whitening;
void vertex() {
// Called for every vertex the material is visible on.
}
void fragment() {
// Called for every pixel the material is visible on.
vec4 texture_color = texture(TEXTURE, UV);
if (texture_color.a != 0.0)
COLOR = vec4(mix(texture_color.rgb, vec3(r,g,b), whitening), opacity);
}
void light() {
// Called for every pixel for every light affecting the CanvasItem.
float cNdotL = max(1.0, dot(NORMAL, LIGHT_DIRECTION));
LIGHT = vec4(LIGHT_COLOR.rgb * COLOR.rgb * LIGHT_ENERGY * cNdotL, LIGHT_COLOR.a);
}
"
[sub_resource type="ShaderMaterial" id="ShaderMaterial_nuww6"]
shader = SubResource("Shader_oa0y8")
shader_parameter/opacity = 1.0
shader_parameter/r = 0.0
shader_parameter/g = 0.0
shader_parameter/b = 0.0
shader_parameter/whitening = 0.0
[sub_resource type="ShaderMaterial" id="ShaderMaterial_v3qiy"]
shader = ExtResource("4_8og43")
[sub_resource type="CircleShape2D" id="CircleShape2D_xx2fg"]
radius = 1.0
[sub_resource type="Animation" id="Animation_obk05"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("RenderViewport/BodySprite:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [0]
}
[sub_resource type="Animation" id="Animation_u4t7j"]
resource_name = "idle_down"
length = 0.3
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("RenderViewport/BodySprite:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [0]
}
[sub_resource type="Animation" id="Animation_rnli0"]
resource_name = "idle_left"
length = 0.3
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("RenderViewport/BodySprite:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [9]
}
[sub_resource type="Animation" id="Animation_7qtya"]
resource_name = "idle_right"
length = 0.3
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("RenderViewport/BodySprite:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [6]
}
[sub_resource type="Animation" id="Animation_b5q0x"]
resource_name = "idle_up"
length = 0.3
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("RenderViewport/BodySprite:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [3]
}
[sub_resource type="Animation" id="Animation_twgw7"]
resource_name = "walk_down"
length = 0.8
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("RenderViewport/BodySprite:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.2, 0.4, 0.6),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 1,
"values": [1, 0, 2, 0]
}
[sub_resource type="Animation" id="Animation_iaftf"]
resource_name = "walk_left"
length = 0.8
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("RenderViewport/BodySprite:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.2, 0.4, 0.6),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 1,
"values": [10, 9, 11, 9]
}
[sub_resource type="Animation" id="Animation_vst1w"]
resource_name = "walk_right"
length = 0.8
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("RenderViewport/BodySprite:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.2, 0.4, 0.6),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 1,
"values": [7, 6, 8, 6]
}
[sub_resource type="Animation" id="Animation_it8wc"]
resource_name = "walk_up"
length = 0.8
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("RenderViewport/BodySprite:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.2, 0.4, 0.6),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 1,
"values": [4, 3, 5, 3]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_2y3xo"]
_data = {
&"RESET": SubResource("Animation_obk05"),
&"idle_down": SubResource("Animation_u4t7j"),
&"idle_left": SubResource("Animation_rnli0"),
&"idle_right": SubResource("Animation_7qtya"),
&"idle_up": SubResource("Animation_b5q0x"),
&"walk_down": SubResource("Animation_twgw7"),
&"walk_left": SubResource("Animation_iaftf"),
&"walk_right": SubResource("Animation_vst1w"),
&"walk_up": SubResource("Animation_it8wc")
}
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_sasld"]
streams_count = 2
stream_0/stream = ExtResource("2_jcncw")
stream_1/stream = ExtResource("3_6e00w")
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_1pe7g"]
streams_count = 8
stream_0/stream = ExtResource("4_xx2fg")
stream_1/stream = ExtResource("5_876ij")
stream_2/stream = ExtResource("6_2t7lq")
stream_3/stream = ExtResource("7_8og43")
stream_4/stream = ExtResource("8_v3qiy")
stream_5/stream = ExtResource("9_jp84j")
stream_6/stream = ExtResource("10_jqf8r")
stream_7/stream = ExtResource("11_6e00w")
[sub_resource type="RectangleShape2D" id="RectangleShape2D_876ij"]
size = Vector2(8, 11.5)
[node name="Goblin" type="CharacterBody2D"]
z_index = 10
z_as_relative = false
y_sort_enabled = true
collision_layer = 256
collision_mask = 576
script = ExtResource("1_muqri")
[node name="NavigationAgent2D" type="NavigationAgent2D" parent="."]
path_desired_distance = 27.73
target_desired_distance = 11.29
path_max_distance = 110.0
navigation_layers = 3
avoidance_enabled = true
radius = 7.0
neighbor_distance = 100.0
time_horizon_obstacles = 0.13
avoidance_mask = 128
[node name="CombinedSprite" type="Sprite2D" parent="."]
position = Vector2(0, -5)
texture = ExtResource("14_2t7lq")
[node name="RenderViewport" type="SubViewport" parent="."]
transparent_bg = true
size = Vector2i(32, 32)
[node name="BodySprite" type="Sprite2D" parent="RenderViewport"]
material = SubResource("ShaderMaterial_nuww6")
texture = ExtResource("2_xx2fg")
centered = false
hframes = 29
vframes = 8
[node name="ArmourSprite" type="Sprite2D" parent="RenderViewport"]
texture = ExtResource("3_876ij")
centered = false
hframes = 29
vframes = 8
[node name="FacialSprite" type="Sprite2D" parent="RenderViewport"]
texture = ExtResource("5_u6mrb")
centered = false
hframes = 29
vframes = 8
[node name="HairSprite" type="Sprite2D" parent="RenderViewport"]
texture = ExtResource("6_nift8")
centered = false
hframes = 29
vframes = 8
[node name="EyeSprite" type="Sprite2D" parent="RenderViewport"]
texture = ExtResource("7_pococ")
centered = false
hframes = 29
vframes = 8
[node name="EyeLashSprite" type="Sprite2D" parent="RenderViewport"]
texture = ExtResource("8_rsnib")
centered = false
hframes = 29
vframes = 8
[node name="BootsSprite" type="Sprite2D" parent="RenderViewport"]
texture = ExtResource("9_v458m")
centered = false
hframes = 29
vframes = 8
[node name="HeadgearSprite" type="Sprite2D" parent="RenderViewport"]
texture = ExtResource("10_a3dd1")
centered = false
hframes = 29
vframes = 8
[node name="AddonSprite" type="Sprite2D" parent="RenderViewport"]
texture = ExtResource("11_vflxt")
centered = false
hframes = 29
vframes = 8
[node name="AddonHornsSprite" type="Sprite2D" parent="RenderViewport"]
texture = ExtResource("11_vflxt")
centered = false
hframes = 29
vframes = 8
[node name="AddonJawSprite" type="Sprite2D" parent="RenderViewport"]
texture = ExtResource("11_vflxt")
centered = false
hframes = 29
vframes = 8
[node name="AttackSprite" type="Sprite2D" parent="RenderViewport"]
texture = ExtResource("12_ry8ej")
centered = false
hframes = 29
vframes = 8
[node name="BodyAboveSprite" type="Sprite2D" parent="."]
visible = false
z_index = 18
z_as_relative = false
material = SubResource("ShaderMaterial_v3qiy")
position = Vector2(0, -5)
texture = ExtResource("14_2t7lq")
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
shape = SubResource("CircleShape2D_xx2fg")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
&"": SubResource("AnimationLibrary_2y3xo")
}
[node name="SfxDie" type="AudioStreamPlayer2D" parent="."]
stream = SubResource("AudioStreamRandomizer_sasld")
max_polyphony = 4
[node name="SfxAlertFoundPlayer" type="AudioStreamPlayer2D" parent="."]
stream = SubResource("AudioStreamRandomizer_1pe7g")
max_polyphony = 8
[node name="Area2DTakeDamage" type="Area2D" parent="."]
collision_layer = 256
collision_mask = 0
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DTakeDamage"]
position = Vector2(0, -4)
shape = SubResource("RectangleShape2D_876ij")
debug_color = Color(0.7, 0, 0.0273481, 0.42)
[connection signal="velocity_computed" from="NavigationAgent2D" to="." method="_on_navigation_agent_2d_velocity_computed"]

View File

@@ -0,0 +1,121 @@
[gd_scene load_steps=19 format=3 uid="uid://wg3txryj23fv"]
[ext_resource type="Script" uid="uid://f7yt42uhe246" path="res://assets/scripts/entities/enemies/humanoid/humanoid.gd" id="1_ox25x"]
[ext_resource type="Texture2D" uid="uid://caq1ig4sdicos" path="res://assets/gfx/Puny-Characters/Layer 0 - Skins/Orc2.png" id="2_ox25x"]
[ext_resource type="Texture2D" uid="uid://dx1fovugabbwc" path="res://assets/gfx/Puny-Characters/Layer 1 - Shoes/IronBoots.png" id="3_1un2j"]
[ext_resource type="Texture2D" uid="uid://c23gdx52uxdsu" path="res://assets/gfx/Puny-Characters/Layer 2 - Clothes/Viking Body/JarlBody.png" id="4_qlq8y"]
[ext_resource type="Texture2D" uid="uid://0wyhap0ywxso" path="res://assets/gfx/Puny-Characters/Layer 3 - Gloves/GlovesMaple.png" id="5_ox25x"]
[ext_resource type="Texture2D" uid="uid://dnvh3mjkmxdfv" path="res://assets/gfx/Puny-Characters/Layer 4 - Hairstyle/Facial Hairstyles/Beardstyle2Brown.png" id="6_bt2gh"]
[ext_resource type="Texture2D" uid="uid://3yp6125ggjxp" path="res://assets/gfx/Puny-Characters/Layer 4 - Hairstyle/Hairstyles/M Hairstyle 2/MHairstyle2Red.png" id="7_x5lcf"]
[ext_resource type="Texture2D" uid="uid://dh3uvf05breb8" path="res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eye Color/EyecolorCyan.png" id="8_ap4nq"]
[ext_resource type="Texture2D" uid="uid://1mr6h7tkw80c" path="res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eyelashes/MEyelash2.png" id="9_77mwg"]
[ext_resource type="Texture2D" uid="uid://dxfp3lf1vck5p" path="res://assets/gfx/Puny-Characters/Layer 6 - Headgears/Basic Assasin/ThiefBandanaLime.png" id="10_4vah4"]
[ext_resource type="Texture2D" uid="uid://ds4dmxn8boxdq" path="res://assets/gfx/Puny-Characters/Layer 7 - Add-ons/Orc Add-ons/GoblinEars2.png" id="11_1phnd"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_ycatx"]
size = Vector2(8, 7)
[sub_resource type="Gradient" id="Gradient_iinuc"]
offsets = PackedFloat32Array(0.272727, 0.518519, 0.750842)
colors = PackedColorArray(0, 0, 0, 0.784314, 0, 0, 0, 0.615686, 0, 0, 0, 0)
[sub_resource type="GradientTexture2D" id="GradientTexture2D_ox25x"]
gradient = SubResource("Gradient_iinuc")
width = 32
height = 32
fill = 1
fill_from = Vector2(0.517391, 0.456522)
fill_to = Vector2(0.944444, 0.106838)
[sub_resource type="Gradient" id="Gradient_8cy7b"]
offsets = PackedFloat32Array(0)
colors = PackedColorArray(0, 0, 0, 0.466667)
[sub_resource type="GradientTexture1D" id="GradientTexture1D_ox25x"]
gradient = SubResource("Gradient_8cy7b")
width = 16
[sub_resource type="Gradient" id="Gradient_lehs0"]
offsets = PackedFloat32Array(1)
colors = PackedColorArray(0.960784, 0.0352941, 0.215686, 0.529412)
[sub_resource type="GradientTexture1D" id="GradientTexture1D_5grkw"]
gradient = SubResource("Gradient_lehs0")
width = 16
[node name="Humanoid" type="CharacterBody2D"]
script = ExtResource("1_ox25x")
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(0, 3.5)
shape = SubResource("RectangleShape2D_ycatx")
[node name="Sprite2DBody" type="Sprite2D" parent="."]
texture = ExtResource("2_ox25x")
hframes = 29
vframes = 8
[node name="Sprite2DShoes" type="Sprite2D" parent="."]
texture = ExtResource("3_1un2j")
hframes = 29
vframes = 8
[node name="Sprite2DClothes" type="Sprite2D" parent="."]
texture = ExtResource("4_qlq8y")
hframes = 29
vframes = 8
[node name="Sprite2DGloves" type="Sprite2D" parent="."]
texture = ExtResource("5_ox25x")
hframes = 29
vframes = 8
[node name="Sprite2DFacialHair" type="Sprite2D" parent="."]
texture = ExtResource("6_bt2gh")
hframes = 29
vframes = 8
[node name="Sprite2DHair" type="Sprite2D" parent="."]
texture = ExtResource("7_x5lcf")
hframes = 29
vframes = 8
[node name="Sprite2DEyes" type="Sprite2D" parent="."]
texture = ExtResource("8_ap4nq")
hframes = 29
vframes = 8
[node name="Sprite2DEyeLashes" type="Sprite2D" parent="."]
texture = ExtResource("9_77mwg")
hframes = 29
vframes = 8
[node name="Sprite2DHeadgear" type="Sprite2D" parent="."]
texture = ExtResource("10_4vah4")
hframes = 29
vframes = 8
[node name="Sprite2DAddOns" type="Sprite2D" parent="."]
texture = ExtResource("11_1phnd")
hframes = 29
vframes = 8
[node name="Shadow" type="Sprite2D" parent="."]
z_index = -1
position = Vector2(0, 7)
scale = Vector2(0.460937, 0.125)
texture = SubResource("GradientTexture2D_ox25x")
[node name="TextureProgressBarHealth" type="TextureProgressBar" parent="."]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -8.0
offset_top = -12.0
offset_right = 8.0
offset_bottom = -11.0
grow_horizontal = 2
grow_vertical = 2
value = 80.0
texture_under = SubResource("GradientTexture1D_ox25x")
texture_progress = SubResource("GradientTexture1D_5grkw")

View File

@@ -0,0 +1,9 @@
extends CharacterBody2D
func _ready() -> void:
pass
func _process(delta: float) -> void:
pass

View File

@@ -0,0 +1 @@
uid://f7yt42uhe246

View File

@@ -0,0 +1,675 @@
extends CharacterBody2D
@onready var coin_scene = preload("res://assets/scripts/entities/pickups/coin.tscn")
@onready var loot_scene = preload("res://assets/scripts/entities/pickups/loot.tscn")
@onready var blood_scene = preload("res://assets/scripts/components/blood_clot.tscn")
@onready var damage_number_scene = preload("res://assets/scripts/components/damage_number.tscn")
@onready var animation_player = $AnimationPlayer
@onready var navigation_agent: NavigationAgent2D = $NavigationAgent2D
@onready var sprite = $RenderViewport/Sprite2D
var above_texture: ImageTexture
var player_sprite_size = Vector2(32, 32)
@onready var render_viewport = $RenderViewport
@onready var combined_sprite = $CombinedSprite
var entity_id: int = 1
var chase_speed: float = 35.0 # Slightly slower than goblin
var patrol_speed: float = 18.0
var current_speed: float = 0.0
var acceleration: float = 100.0
var alert_radius: float = 70.0 # Distance to first notice player
var tracking_radius: float = 110.0 # Distance to keep chasing player
var vision_angle: float = 360.0 # Slimes see all around them
var stats = CharacterStats.new()
var taking_damage_timer: float = 0.0
var damage_flash_duration: float = 0.2
var has_spotted_player: bool = false
var knockback_timer: float = 0.0
var knockback_duration: float = 0.2
var minimum_chase_timer: float = 0.0
const MINIMUM_CHASE_DURATION: float = 4.0
# Add this near your other class variables
var _position_update_timer: float = 0.0
const POSITION_UPDATE_INTERVAL: float = 0.2
var network_update_timer := 0.0
const NETWORK_UPDATE_INTERVAL := 0.05 # 20 times per second
enum State {
IDLE,
CHASE,
INVESTIGATE,
PATROL,
DAMAGE
}
signal signal_died(enemy: Node2D)
var current_state = State.IDLE
var last_known_player_pos: Vector2
var idle_timer: float = 0.0
var patrol_timer: float = 0.0
var idle_duration: float = 2.0 # How long to idle between actions
var patrol_duration: float = 3.0 # How long to walk before idling
var patrol_point: Vector2
# Add these variables near the top with other variables
var positionZ = 0.0
var velocityZ = 0.0
var accelerationZ = -400.0 # Gravity
var bounceRestitution = 0.6
var minBounceVelocity = 50.0
var jumpVelocity = 120.0 # Initial upward velocity when jumping
var jumpCooldown = 0.8 # Time between jumps
var jumpTimer = 0.0 # Track time since last jump
var attack_radius: float = 30.0 # Distance at which slime will jump at player
# Add near the top with other variables
@onready var sync_next_path_position: Vector2
# Add near the top with other variables
@export var sync_position: Vector2
@export var sync_velocity: Vector2
@export var sync_state: int
@export var sync_hp: int
@export var sync_positionZ: float
@export var sync_velocityZ: float
# Add monitoring state to sync variables at the top
@export var sync_area2d_monitoring: bool = false
# Add near the top with other sync variables
@export var sync_animation: String = ""
var positionInt = Vector2i(0, 0)
var previousFramePosition = Vector2i(-1, 0)
var previousHadValue = -1
func update_above_texture():
positionInt = Vector2i(position)
if previousFramePosition == positionInt:
return
previousFramePosition = positionInt
var image: Image = null
# Loop over the 32x32 area and get tiles from the TileMapAbove
var tma: TileMapLayer = get_tree().current_scene.get_node("TileMapAbove")
if tma != null:
# Adjust the start position based on the player's global position and movement
var startPos = global_position - Vector2(16, 16)
var pieceX = int(global_position.x) % 16
var pieceY = int(global_position.y) % 16
var startTilePos = startPos
var extraX = 16 - pieceX
var extraY = 16 - pieceY
# Loop through 3x3 tile grid
for y in range(0, 32 + extraY, 16): # Step by 16 pixels (tile size)
for x in range(0, 32 + extraX, 16):
var pixel_pos = startTilePos + Vector2(x, y)
var tile_pos = tma.local_to_map(pixel_pos)
if get_tile_texture(tma, tile_pos):
if image == null:
image = above_texture.get_image()
image.fill(Color.from_rgba8(0, 0, 0, 0)) # fill with transparent pixels before we grab from the tilemaplayer
previousHadValue = 1
var tile_image = atlas_texture.get_image()
var dest_pos = Vector2(x - pieceX, y - pieceY)
image.blit_rect(tile_image, Rect2(Vector2.ZERO, tma.tile_set.tile_size), dest_pos)
if image == null and previousHadValue == 1:
previousHadValue = -1
image = above_texture.get_image()
image.fill(Color.from_rgba8(0, 0, 0, 0)) # fill with transparent pixels before we grab from the tilemaplayer
if image != null:
# Recreate the texture from the modified image
above_texture = ImageTexture.create_from_image(image)
$BodyAboveSprite.material.set_shader_parameter("above_texture", above_texture)
var atlas_texture = AtlasTexture.new()
# New function to get the tile texture
func get_tile_texture(tilemap: TileMapLayer, tile_pos: Vector2i) -> AtlasTexture:
var tile_id = tilemap.get_cell_source_id(tile_pos)
if tile_id == -1:
return null # Return null if no tile is present
var tile_atlas_coords = tilemap.get_cell_atlas_coords(tile_pos)
var tile_size = tilemap.tile_set.tile_size
var texture = tilemap.tile_set.get_source(tile_id).texture
var region = Rect2(tile_atlas_coords * tile_size, tile_size)
atlas_texture.atlas = texture
atlas_texture.region = region
return atlas_texture
func _ready() -> void:
add_to_group("enemies")
$BodyAboveSprite.visible = false
combined_sprite.texture = render_viewport.get_texture()
#$BodyAboveSprite.texture = render_viewport.get_texture()
#$BodyAboveSprite.visible = true
$Area2DDealDamage.set_deferred("monitoring", false)
var img: Image = Image.create(32, 32, false, Image.FORMAT_RGBA8)
img.fill(Color.from_rgba8(0, 0, 0, 0))
above_texture = ImageTexture.create_from_image(img)
var mat = $BodyAboveSprite.material.duplicate()
$BodyAboveSprite.material = mat
$BodyAboveSprite.material.set_shader_parameter("above_texture", above_texture)
stats.hp = 2
stats.maxhp = 2
stats.damage = 1
stats.defense = 0
# Configure NavigationAgent
navigation_agent.path_desired_distance = 4.0
navigation_agent.target_desired_distance = 4.0
navigation_agent.path_max_distance = 90.0
navigation_agent.avoidance_enabled = true
navigation_agent.neighbor_distance = 90.0
navigation_agent.max_neighbors = 10
navigation_agent.time_horizon = 1.0
navigation_agent.max_speed = chase_speed
# Start in idle state
current_state = State.IDLE
idle_timer = idle_duration
# Enable navigation debug in debug builds
if OS.is_debug_build():
navigation_agent.debug_enabled = true
func _draw() -> void:
if OS.is_debug_build():
# Draw alert radius
draw_arc(Vector2.ZERO, alert_radius, 0, TAU, 32, Color(1, 0, 0, 0.2), 2.0)
# Draw tracking radius
draw_arc(Vector2.ZERO, tracking_radius, 0, TAU, 32, Color(0, 1, 0, 0.2), 2.0)
func is_entity_in_camera_view() -> bool:
var camera = get_viewport().get_camera_2d()
if camera == null:
return false # No active camera
# Get the camera's visible rectangle in global coordinates
var camera_rect = Rect2(
camera.global_position - (camera.get_zoom() * camera.get_viewport_rect().size) / 2,
camera.get_zoom() * camera.get_viewport_rect().size
)
# Check if the player's position is within the camera's visible rectangle
return camera_rect.has_point(global_position)
func _physics_process(delta: float) -> void:
if multiplayer.is_server():
# Server-side logic
# ... existing movement/AI code ...
# Only send updates at fixed intervals and when there's meaningful change
network_update_timer += delta
if network_update_timer >= NETWORK_UPDATE_INTERVAL:
network_update_timer = 0.0
# Only sync if there's significant movement or state change
if (position.distance_squared_to(sync_position) > 1.0 or
velocity.length_squared() > 1.0 or
stats.hp != sync_hp):
# Send to all clients
sync_slime_movement.rpc(global_position, velocity, stats.hp, current_state)
# Update last synced values
sync_position = global_position
sync_hp = stats.hp
if !multiplayer.is_server():
# Clients update their position based on sync data
if sync_position != Vector2.ZERO:
position = position.lerp(sync_position, 0.5)
if sync_velocity != Vector2.ZERO:
velocity = sync_velocity
positionZ = sync_positionZ
velocityZ = sync_velocityZ
if stats.hp != sync_hp:
stats.hp = sync_hp
if current_state != sync_state:
current_state = sync_state as State
update_sprite_scale()
return
if knockback_timer > 0:
knockback_timer -= delta
if knockback_timer <= 0:
velocity = Vector2.ZERO
stats.is_invulnerable = false
knockback_timer = 0
if taking_damage_timer > 0:
taking_damage_timer -= delta
if taking_damage_timer <= 0:
taking_damage_timer = 0
if stats.hp > 0:
# Update jump timer
if jumpTimer > 0:
jumpTimer -= delta
# Update Z position
velocityZ += accelerationZ * delta
positionZ += velocityZ * delta
# Ground collision and bounce
if positionZ <= 0:
positionZ = 0
if animation_player.current_animation != "take_damage" and animation_player.current_animation != "die":
if abs(velocityZ) > minBounceVelocity:
velocityZ = -velocityZ * bounceRestitution
velocityZ = 0
animation_player.play("land")
animation_player.queue("idle")
$Area2DDealDamage.set_deferred("monitoring", false)
else:
velocityZ = 0
if current_state == State.CHASE and jumpTimer <= 0:
var closest_player = find_closest_player()
if closest_player and global_position.distance_to(closest_player.global_position) < attack_radius:
velocityZ = jumpVelocity
jumpTimer = jumpCooldown
$SfxJump.pitch_scale = randf_range(1.0, 1.2)
$SfxJump.play()
animation_player.play("jump")
$Area2DDealDamage.set_deferred("monitoring", true)
# Make sure idle animation is playing when not moving
if velocity.length() < 0.1 and current_state != State.DAMAGE and stats.hp > 0:
if not animation_player.is_playing() or animation_player.current_animation != "idle":
animation_player.play("idle")
match current_state:
State.IDLE:
handle_idle_state(delta)
State.PATROL:
handle_patrol_state(delta)
State.CHASE:
handle_chase_state(delta)
State.INVESTIGATE:
handle_investigate_state(delta)
State.DAMAGE:
handle_damage_state(delta)
move_and_slide()
update_sprite_scale()
func update_sprite_scale() -> void:
# Calculate scale based on height
# Maximum height will have scale 1.3, ground will have scale 1.0
var height_factor = positionZ / 50.0 # Assuming 50 is max height
var sc = 1.0 + (0.3 * height_factor)
$CombinedSprite.scale = Vector2(sc, sc)
$BodyAboveSprite.scale = Vector2(sc, sc)
# Update Y position based on height
$CombinedSprite.position.y = -positionZ # Negative because higher Y is down in Godot
$BodyAboveSprite.position.y = -positionZ
var shadowFactor = positionZ / 30.0
$Sprite2DShadow.modulate.a = 1 - shadowFactor
func handle_idle_state(delta: float) -> void:
var new_velocity = velocity.move_toward(Vector2.ZERO, acceleration * delta)
#navigation_agent.set_velocity_forced(new_velocity)
navigation_agent.set_velocity(new_velocity)
# Check for player first
var closest_player = find_closest_player()
if closest_player and global_position.distance_to(closest_player.global_position) < alert_radius:
current_state = State.CHASE
return
idle_timer -= delta
if idle_timer <= 0:
current_state = State.PATROL
patrol_timer = patrol_duration
# Set random patrol point within radius
var random_angle = randf() * TAU
var random_distance = randf_range(30, 100)
patrol_point = global_position + Vector2.from_angle(random_angle) * random_distance
navigation_agent.target_position = patrol_point
func handle_patrol_state(delta: float) -> void:
patrol_timer -= delta
# Check for player first
var closest_player = find_closest_player()
if closest_player and global_position.distance_to(closest_player.global_position) < alert_radius:
current_state = State.CHASE
return
if not navigation_agent.is_navigation_finished():
var next_path_position: Vector2 = navigation_agent.get_next_path_position()
var direction = global_position.direction_to(next_path_position)
var new_velocity = navigation_agent.velocity.move_toward(direction * patrol_speed, acceleration * delta)
navigation_agent.set_velocity(new_velocity)
else:
# Only go to idle when we've reached our destination
current_state = State.IDLE
idle_timer = idle_duration
func handle_chase_state(delta: float) -> void:
_position_update_timer += delta
#var res = navigation_agent.get_current_navigation_result()
#print("current nav result:", res.path)
if not navigation_agent.is_navigation_finished():
var next_path_position: Vector2 = navigation_agent.get_next_path_position()
var direction = global_position.direction_to(next_path_position)
var new_velocity = navigation_agent.velocity.move_toward(direction * chase_speed, acceleration * delta)
navigation_agent.set_velocity(new_velocity)
if _position_update_timer >= POSITION_UPDATE_INTERVAL:
_position_update_timer = 0.0
var closest_player = find_closest_player()
if closest_player:
navigation_agent.target_position = closest_player.global_position # update navigation agent pos
else:
current_state = State.IDLE
idle_timer = idle_duration
func handle_investigate_state(delta: float) -> void:
if not navigation_agent.is_navigation_finished():
var next_path_position: Vector2 = navigation_agent.get_next_path_position()
var direction = global_position.direction_to(next_path_position)
var new_velocity = navigation_agent.velocity.move_toward(direction * patrol_speed, acceleration * delta)
navigation_agent.set_velocity(new_velocity)
else:
current_state = State.IDLE
idle_timer = idle_duration
func handle_damage_state(_delta: float) -> void:
if knockback_timer <= 0:
var closest_player = find_closest_player()
if closest_player:
current_state = State.CHASE
else:
current_state = State.IDLE
idle_timer = idle_duration
func find_closest_player() -> Node2D:
var players = get_tree().get_nodes_in_group("players")
var closest_player = null
var closest_distance = tracking_radius
for player in players:
var distance = global_position.distance_to(player.global_position)
if distance < closest_distance:
closest_player = player
closest_distance = distance
if not has_spotted_player:
has_spotted_player = true
if closest_player and minimum_chase_timer > 0:
minimum_chase_timer -= get_physics_process_delta_time()
return closest_player
elif closest_distance <= tracking_radius:
return closest_player
return null
@rpc("any_peer")
func take_damage(iBody: Node2D, iByWhoOrWhat: Node2D) -> void:
if !stats.is_invulnerable and stats.hp > 0:
var damage_amount = 1.0
stats.take_damage(damage_amount)
stats.is_invulnerable = true
knockback_timer = knockback_duration
current_state = State.DAMAGE
taking_damage_timer = damage_flash_duration
# Calculate knockback direction from the damaging body
var knockback_direction = (global_position - iBody.global_position).normalized()
velocity = knockback_direction * 80.0
# Create damage number
if multiplayer.is_server():
spawn_damage_number(damage_amount)
spawn_damage_number.rpc(damage_amount)
if stats.hp <= 0:
if iByWhoOrWhat != null and iByWhoOrWhat is CharacterBody2D:
if "stats" in iByWhoOrWhat:
iByWhoOrWhat.stats.add_xp(1)
var exp_number = damage_number_scene.instantiate() as Label
if exp_number:
if "direction" in exp_number:
exp_number.direction = Vector2(0, -1)
exp_number.label = "+ 1 EXP"
exp_number.move_duration = 1.0
if "color" in exp_number:
exp_number.color = Color.WEB_GREEN
get_tree().current_scene.call_deferred("add_child", exp_number)
exp_number.global_position = global_position + Vector2(0, -16)
pass
if multiplayer.is_server():
$Area2DDealDamage.set_deferred("monitoring", false) # we should no longer be able to take damage from the slime.
signal_died.emit(self)
remove_enemy.rpc()
remove_enemy() # Call locally for server
else:
if multiplayer.is_server():
play_damage_animation()
play_damage_animation.rpc()
@rpc("reliable")
func remove_enemy():
if $SfxJump.playing:
$SfxJump.stop()
if multiplayer.is_server():
# Register this enemy as defeated before removing it
GameManager.register_defeated_enemy.rpc(entity_id)
# Generate loot items array
var loot_items = []
for i in range(randi_range(1, 2 + stats.coin)): # Random number of coins
var angle = randf_range(0, TAU)
var speed = randf_range(50, 100)
var velZ = randf_range(100, 200)
loot_items.append({
"type": 0, # Coin type
"angle": angle,
"speed": speed,
"velocityZ": velZ
})
# Randomly add item loot
if randf() < 0.4: # 40% chance for item
var angle = randf_range(0, TAU)
var speed = randf_range(50, 100)
var velZ = randf_range(100, 200)
loot_items.append({
"type": randi_range(1, 7), # Random item type
"angle": angle,
"speed": speed,
"velocityZ": velZ
})
# Spawn loot locally on server first
spawn_loot(loot_items)
# Then tell clients to spawn the same loot
spawn_loot.rpc(loot_items)
$AnimationPlayer.play("die")
$Sprite2DShadow.visible = false
$SfxDie.play()
for i in 6:
var angle = randf_range(0, TAU)
var speed = randf_range(50, 100)
var initial_velocityZ = randf_range(50, 90)
var b = blood_scene.instantiate() as CharacterBody2D
b.get_node("Sprite2D").modulate = Color(0, 0.8, 0, 1.0)
b.scale = Vector2(randf_range(0.3, 2), randf_range(0.3, 2))
b.global_position = global_position
# Set initial velocities from the synchronized data
var direction = Vector2.from_angle(angle)
b.velocity = direction * speed
b.velocityZ = initial_velocityZ
get_parent().call_deferred("add_child", b)
await $AnimationPlayer.animation_finished
if $SfxDie.playing:
$SfxDie.stop()
call_deferred("queue_free")
# Modify the sync_slime_state RPC to include monitoring state and animation
@rpc("authority", "unreliable")
func sync_slime_movement(pos: Vector2, vel: Vector2, hp: int, state: int):
if not multiplayer.is_server():
sync_position = pos
sync_velocity = vel
sync_hp = hp
sync_state = state
@rpc("unreliable")
func sync_path_position(pos: Vector2):
if not multiplayer.is_server():
sync_next_path_position = pos
func _on_area_2d_deal_damage_body_entered(body: Node2D) -> void:
if body is Area2D and body.get_parent().stats.is_invulnerable == false and body.get_parent().stats.hp > 0: # hit an enemy
body.take_damage(self, self)
pass
pass # Replace with function body.
@rpc("reliable")
func spawn_loot(loot_items: Array):
for lootItem in loot_items:
if lootItem.type == 0: # Coin
var coin = coin_scene.instantiate()
GameManager.get_node("Coins").call_deferred("add_child", coin)
#get_parent().call_deferred("add_child", coin)
coin.global_position = global_position
var direction = Vector2.from_angle(lootItem.angle)
coin.velocity = direction * lootItem.speed
coin.velocityZ = lootItem.velocityZ
else: # Item loot
var item = Item.new()
if lootItem.type == 1:
item.item_type = Item.ItemType.Equippable
item.equipment_type = Item.EquipmentType.ARMOUR
item.item_name = "Leather Armour"
item.description = "A nice leather armour"
item.spriteFrame = 12
item.modifiers["def"] = 2
item.equipmentPath = "res://assets/gfx/Puny-Characters/Layer 2 - Clothes/Tunic Body/BrownTunic.png"
elif lootItem.type == 2:
item.item_type = Item.ItemType.Equippable
item.equipment_type = Item.EquipmentType.HEADGEAR
item.item_name = "Leather helm"
item.description = "A nice leather helm"
item.spriteFrame = 31
item.modifiers["def"] = 1
item.equipmentPath = "res://assets/gfx/Puny-Characters/Layer 6 - Headgears/Basic Mage/MageHatRed.png"
elif lootItem.type == 3:
item.item_type = Item.ItemType.Equippable
item.equipment_type = Item.EquipmentType.MAINHAND
item.weapon_type = Item.WeaponType.SWORD
item.item_name = "Dagger"
item.description = "A sharp dagger"
item.spriteFrame = 5 * 20 + 10
item.modifiers["dmg"] = 2
elif lootItem.type == 4:
item.item_type = Item.ItemType.Equippable
item.equipment_type = Item.EquipmentType.MAINHAND
item.weapon_type = Item.WeaponType.AXE
item.item_name = "Hand Axe"
item.description = "A sharp hand axe"
item.spriteFrame = 5 * 20 + 11
item.modifiers["dmg"] = 4
elif lootItem.type == 5:
item.item_type = Item.ItemType.Equippable
item.equipment_type = Item.EquipmentType.OFFHAND
item.weapon_type = Item.WeaponType.AMMUNITION
item.quantity = 13
item.can_have_multiple_of = true
item.item_name = "Iron Arrow"
item.description = "A sharp arrow made of iron and feathers from pelican birds"
item.spriteFrame = 7 * 20 + 11
item.modifiers["dmg"] = 3
elif lootItem.type == 6:
item.item_type = Item.ItemType.Equippable
item.equipment_type = Item.EquipmentType.MAINHAND
item.weapon_type = Item.WeaponType.BOW
item.item_name = "Wooden Bow"
item.description = "A wooden bow made of elfish lembas trees"
item.spriteFrame = 6 * 20 + 16
item.modifiers["dmg"] = 3
elif lootItem.type == 7:
item.item_type = Item.ItemType.Equippable
item.equipment_type = Item.EquipmentType.BOOTS
item.weapon_type = Item.WeaponType.NONE
item.item_name = "Sandals"
item.description = "A pair of shitty sandals"
item.equipmentPath = "res://assets/gfx/Puny-Characters/Layer 1 - Shoes/ShoesBrown.png"
item.spriteFrame = 2 * 20 + 10
item.modifiers["def"] = 1
var loot = loot_scene.instantiate()
#get_parent().call_deferred("add_child", loot)
GameManager.get_node("Loot").call_deferred("add_child", loot)
loot.setItem(item)
loot.global_position = global_position
var direction = Vector2.from_angle(lootItem.angle)
loot.velocity = direction * lootItem.speed
loot.velocityZ = lootItem.velocityZ
@rpc("reliable")
func spawn_coins(coin_data: Array):
for data in coin_data:
var coin = coin_scene.instantiate()
GameManager.get_node("Coins").call_deferred("add_child", coin)
#get_parent().add_child(coin)
coin.global_position = global_position
# Set initial velocities from the synchronized data
var direction = Vector2.from_angle(data.angle)
coin.velocity = direction * data.speed
coin.velocityZ = data.velocityZ
# Add new RPCs for visual effects
@rpc("authority", "reliable")
func spawn_damage_number(damage_amount: float):
if damage_number_scene:
var damage_number = damage_number_scene.instantiate() as Label
if damage_number:
get_tree().current_scene.add_child(damage_number)
damage_number.global_position = global_position + Vector2(0, -16)
if "direction" in damage_number:
damage_number.direction = Vector2(0, -1)
if "label" in damage_number:
damage_number.label = str(damage_amount)
if "color" in damage_number:
damage_number.color = Color(1, 0.3, 0.3, 1)
@rpc("authority", "reliable")
func play_damage_animation():
$SfxDie.play()
$AnimationPlayer.play("take_damage")
$AnimationPlayer.queue("idle")
func _on_area_2d_deal_damage_area_entered(area: Area2D) -> void:
if area is Area2D and area.get_parent().stats.is_invulnerable == false and area.get_parent().stats.hp > 0: # hit an enemy
area.get_parent().take_damage(self, self)
pass
pass # Replace with function body.
func _on_navigation_agent_2d_velocity_computed(safe_velocity: Vector2) -> void:
velocity = safe_velocity
pass # Replace with function body.

View File

@@ -0,0 +1 @@
uid://djftsndq45u0a

View File

@@ -0,0 +1,235 @@
[gd_scene load_steps=22 format=3 uid="uid://b8etn6xqbg57o"]
[ext_resource type="Script" uid="uid://djftsndq45u0a" path="res://assets/scripts/entities/enemies/slime/slime.gd" id="1_w201s"]
[ext_resource type="Texture2D" uid="uid://csr5k0etreqbf" path="res://assets/gfx/enemies/Slime.png" id="1_ytere"]
[ext_resource type="Shader" uid="uid://b1k834hb0xm2w" path="res://assets/shaders/draw_sprite_above.gdshader" id="3_taldv"]
[ext_resource type="Texture2D" uid="uid://dxk8dcdqrft0v" path="res://assets/gfx/gibb_sprite.png" id="4_orljr"]
[ext_resource type="AudioStream" uid="uid://oly1occx067k" path="res://assets/audio/sfx/enemies/slime/slime_die.mp3" id="5_trpa5"]
[ext_resource type="AudioStream" uid="uid://dr5va4d7psjk6" path="res://assets/audio/sfx/enemies/slime/slime_die2.mp3" id="6_thd0o"]
[ext_resource type="AudioStream" uid="uid://c50k7hswlkf8r" path="res://assets/audio/sfx/enemies/slime/jump.mp3" id="7_thd0o"]
[sub_resource type="Gradient" id="Gradient_cjpjf"]
offsets = PackedFloat32Array(0.487589, 0.572695)
colors = PackedColorArray(0, 0, 0, 1, 0, 0, 0, 0)
[sub_resource type="GradientTexture2D" id="GradientTexture2D_w201s"]
gradient = SubResource("Gradient_cjpjf")
width = 32
height = 32
fill = 1
fill_from = Vector2(0.529915, 0.482906)
[sub_resource type="Animation" id="Animation_w201s"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("RenderViewport/Sprite2D:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [0]
}
[sub_resource type="Animation" id="Animation_trpa5"]
resource_name = "die"
length = 0.4
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("RenderViewport/Sprite2D:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.0666667, 0.133333, 0.2, 0.3),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1),
"update": 1,
"values": [9, 10, 11, 12, 13]
}
[sub_resource type="Animation" id="Animation_ytere"]
resource_name = "idle"
length = 0.8
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("RenderViewport/Sprite2D:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.2, 0.4, 0.6),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 1,
"values": [0, 1, 2, 1]
}
[sub_resource type="Animation" id="Animation_roai2"]
resource_name = "jump"
length = 0.3
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("RenderViewport/Sprite2D:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0.0666667, 0.166667),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [4, 5]
}
[sub_resource type="Animation" id="Animation_taldv"]
resource_name = "land"
length = 0.2
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("RenderViewport/Sprite2D:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.1),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [7, 8]
}
[sub_resource type="Animation" id="Animation_orljr"]
resource_name = "take_damage"
length = 0.2
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("RenderViewport/Sprite2D:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.133333),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [6, 9]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_roai2"]
_data = {
&"RESET": SubResource("Animation_w201s"),
&"die": SubResource("Animation_trpa5"),
&"idle": SubResource("Animation_ytere"),
&"jump": SubResource("Animation_roai2"),
&"land": SubResource("Animation_taldv"),
&"take_damage": SubResource("Animation_orljr")
}
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_w201s"]
radius = 3.0
height = 8.0
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_roai2"]
radius = 2.0
height = 8.0
[sub_resource type="RectangleShape2D" id="RectangleShape2D_w201s"]
size = Vector2(8, 8)
[sub_resource type="ShaderMaterial" id="ShaderMaterial_trpa5"]
shader = ExtResource("3_taldv")
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_1dxl4"]
streams_count = 2
stream_0/stream = ExtResource("5_trpa5")
stream_1/stream = ExtResource("6_thd0o")
[node name="Slime" type="CharacterBody2D"]
z_index = 10
z_as_relative = false
y_sort_enabled = true
collision_layer = 0
collision_mask = 192
script = ExtResource("1_w201s")
[node name="Sprite2DShadow" type="Sprite2D" parent="."]
z_index = 1
z_as_relative = false
position = Vector2(4.76837e-07, 5)
scale = Vector2(0.47, 0.157)
texture = SubResource("GradientTexture2D_w201s")
[node name="NavigationAgent2D" type="NavigationAgent2D" parent="."]
path_desired_distance = 4.0
target_desired_distance = 4.0
navigation_layers = 3
avoidance_enabled = true
radius = 4.0
neighbor_distance = 100.0
time_horizon_obstacles = 0.36
max_speed = 4000.0
avoidance_layers = 3
avoidance_mask = 128
[node name="CombinedSprite" type="Sprite2D" parent="."]
position = Vector2(0, -1)
texture = ExtResource("4_orljr")
[node name="RenderViewport" type="SubViewport" parent="."]
transparent_bg = true
size = Vector2i(32, 32)
[node name="Sprite2D" type="Sprite2D" parent="RenderViewport"]
texture = ExtResource("1_ytere")
centered = false
hframes = 15
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
&"": SubResource("AnimationLibrary_roai2")
}
next/land = &"idle"
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
visible = false
rotation = -1.5708
shape = SubResource("CapsuleShape2D_w201s")
[node name="Area2DDealDamage" type="Area2D" parent="."]
visible = false
collision_layer = 0
collision_mask = 512
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DDealDamage"]
rotation = -1.5708
shape = SubResource("CapsuleShape2D_roai2")
debug_color = Color(0.7, 0, 0.145721, 0.42)
[node name="Area2DTakeDamage" type="Area2D" parent="."]
visible = false
collision_layer = 256
collision_mask = 0
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DTakeDamage"]
shape = SubResource("RectangleShape2D_w201s")
debug_color = Color(0.7, 0, 0.0697005, 0.42)
[node name="BodyAboveSprite" type="Sprite2D" parent="."]
visible = false
z_index = 14
z_as_relative = false
material = SubResource("ShaderMaterial_trpa5")
position = Vector2(0, -1)
texture = ExtResource("4_orljr")
[node name="SfxDie" type="AudioStreamPlayer2D" parent="."]
stream = SubResource("AudioStreamRandomizer_1dxl4")
[node name="SfxJump" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("7_thd0o")
volume_db = -6.911
pitch_scale = 1.12
[connection signal="velocity_computed" from="NavigationAgent2D" to="." method="_on_navigation_agent_2d_velocity_computed"]
[connection signal="area_entered" from="Area2DDealDamage" to="." method="_on_area_2d_deal_damage_area_entered"]
[connection signal="body_entered" from="Area2DDealDamage" to="." method="_on_area_2d_deal_damage_body_entered"]

View File

@@ -0,0 +1,116 @@
class_name Item
func _init(iDic: Dictionary = {}):
if iDic != {}:
self.load(iDic)
enum ItemType {
Restoration,
Equippable,
Throwable,
Bomb,
}
# only relevant for equipment
enum EquipmentType {
NONE,
MAINHAND,
OFFHAND,
HEADGEAR,
ARMOUR,
BOOTS,
ACCESSORY
}
enum WeaponType {
NONE,
AMMUNITION,
BOW,
SWORD,
AXE
}
var use_function = null
var item_name: String = "Red Apple"
var description: String = "Restores 5 HP"
var spritePath: String = "res://assets/gfx/items_n_shit.png"
var equipmentPath: String = "res://assets/gfx/Puny-Characters/Layer 2 - Clothes/Basic Body/BasicRed.png"
var colorReplacements: Array = []
var spriteFrames:Vector2i = Vector2i(20,14)
var spriteFrame:int = 0
var modifiers: Dictionary = { "hp": +20 }
var duration: float = 0
var buy_cost: int = 10
var sell_worth: int = 3
var sellable:bool = true
var item_type: ItemType = ItemType.Restoration
var equipment_type: EquipmentType = EquipmentType.NONE
var weapon_type: WeaponType = WeaponType.NONE
var two_handed:bool = false
var quantity = 1
var can_have_multiple_of:bool = false
func save():
var json = {
"item_name": item_name,
"description": description,
"spritePath": spritePath,
"equipmentPath": equipmentPath,
"spriteFrame": spriteFrame,
"modifiers": modifiers,
"duration": duration,
"buy_cost": buy_cost,
"sell_worth": sell_worth,
"item_type": item_type,
"equipment_type": equipment_type,
"weapon_type": weapon_type,
"two_handed": two_handed,
"quantity": quantity,
"can_have_multiple_of": can_have_multiple_of
}
return json
func from_dict(iDic: Dictionary) -> Item:
self.load(iDic)
return self
func load(iDic: Dictionary):
if iDic.has("item_name"):
item_name = iDic.get("item_name")
if iDic.has("description"):
description = iDic.get("description")
if iDic.has("spritePath"):
spritePath = iDic.get("spritePath")
if iDic.has("equipmentPath"):
equipmentPath = iDic.get("equipmentPath")
#if iDic.has("spriteFrames"):
#spriteFrames = iDic.get("spriteFrames")
if iDic.has("spriteFrame"):
spriteFrame = iDic.get("spriteFrame")
if iDic.has("modifiers"):
modifiers = iDic.get("modifiers")
if iDic.has("duration"):
duration = iDic.get("duration")
if iDic.has("buy_cost"):
buy_cost = iDic.get("buy_cost")
if iDic.has("sell_worth"):
sell_worth = iDic.get("sell_worth")
if iDic.has("item_type"):
item_type = iDic.get("item_type")
if iDic.has("equipment_type"):
equipment_type = iDic.get("equipment_type")
if iDic.has("weapon_type"):
weapon_type = iDic.get("weapon_type")
if iDic.has("two_handed"):
two_handed = iDic.get("two_handed")
if iDic.has("quantity"):
quantity = iDic.get("quantity")
if iDic.has("can_have_multiple_of"):
can_have_multiple_of = iDic.get("can_have_multiple_of")
pass

View File

@@ -0,0 +1 @@
uid://d3vwfoc63u5fv

View File

@@ -0,0 +1,161 @@
extends CharacterBody2D
var friction = 8.0 # Lower values make the slowdown more gradual
var is_collected = false
var bounceTimer = 0.0
var timeBeforePickup = 0.8
@onready var damage_number_scene = preload("res://assets/scripts/components/damage_number.tscn")
# Z-axis variables
var positionZ = 4.0 # Start slightly in the air
var velocityZ = 10.0 # Initial upward velocity
var accelerationZ = -300.0 # Gravity
var bounceRestitution = 0.6 # How much bounce energy is retained (0-1)
var minBounceVelocity = 40.0 # Minimum velocity needed to bounce
var bodyToPickUp:Node2D = null
var sync_position := Vector2()
var sync_velocity := Vector2()
var sync_positionZ: float = 4.0
var sync_velocityZ: float = 10.0
func _ready() -> void:
add_to_group("coins")
$Area2DCollision.set_deferred("monitoring", false)
update_sprite_scale()
# Start animation
$AnimationPlayer.play("idle")
func _process(delta: float) -> void:
if bodyToPickUp != null and !is_collected and timeBeforePickup == 0 and positionZ < 5:
visible = false
$SfxCoinCollect.play()
is_collected = true
$Area2DCollision.set_deferred("monitoring", false)
var damage_number = damage_number_scene.instantiate() as Label
if damage_number:
get_tree().current_scene.add_child(damage_number)
damage_number.global_position = global_position + Vector2(0, -16)
if "direction" in damage_number:
damage_number.direction = Vector2(0, -1)
damage_number.move_duration = 1.0
if "label" in damage_number:
damage_number.label = "+1 COIN"
if "color" in damage_number:
damage_number.color = Color.YELLOW
if "stats" in bodyToPickUp:
bodyToPickUp.stats.add_coin(1)
await $SfxCoinCollect.finished
call_deferred("queue_free")
return
if is_collected:
return
if timeBeforePickup > 0.0:
timeBeforePickup -= delta
if timeBeforePickup < 0:
$Area2DCollision.set_deferred("monitoring", true)
timeBeforePickup = 0
if bounceTimer > 0.0:
bounceTimer -= delta
if bounceTimer < 0:
bounceTimer = 0
# Update vertical movement
velocityZ += accelerationZ * delta
positionZ += velocityZ * delta
# Ground collision and bounce
if positionZ <= 0:
velocity = velocity.lerp(Vector2.ZERO, 1.0 - exp(-friction * delta)) # only slow down if on floor
positionZ = 0
if abs(velocityZ) > minBounceVelocity:
#print(velocityZ)
$SfxCoinBounce.volume_db = -1 + (-10 - (velocityZ * 0.1))
$SfxCoinBounce.play()
velocityZ = -velocityZ * bounceRestitution
else:
velocityZ = 0
update_sprite_scale()
move_and_slide()
'
func _physics_process(delta: float) -> void:
if multiplayer.is_server():
for peer_id in multiplayer.get_peers():
sync_coin.rpc_id(peer_id, position, velocity, positionZ, velocityZ)
if !multiplayer.is_server():
position = position.lerp(sync_position, delta * 15.0)
velocity = velocity.lerp(sync_velocity, delta * 15.0)
positionZ = sync_positionZ
velocityZ = sync_velocityZ
if positionZ <= 0:
velocity = velocity.lerp(Vector2.ZERO, 1.0 - exp(-friction * delta)) # only slow down if on floor
positionZ = 0
if abs(velocityZ) > minBounceVelocity:
#print(velocityZ)
$SfxCoinBounce.volume_db = -1 + (-10 - (velocityZ * 0.1))
$SfxCoinBounce.play()
update_sprite_scale()
pass
'
@rpc("unreliable")
func sync_coin(pos: Vector2, vel: Vector2, posZ: float, velZ: float):
sync_position = pos
sync_velocity = vel
sync_positionZ = posZ
sync_velocityZ = velZ
pass
func update_sprite_scale() -> void:
# Calculate scale based on height
# Maximum height will have scale 1.3, ground will have scale 1.0
var height_factor = positionZ / 50.0 # Assuming 20 is max height
var posY = 0.0 + (2 * positionZ)
var sc = 1.0 + (0.8 * height_factor)
$Sprite2D.scale = Vector2(sc, sc)
$Sprite2D.position.y = -posY
func _on_area_2d_collision_body_entered(_body: Node2D) -> void:
if bounceTimer == 0:
$SfxCoinBounce.play()
bounceTimer = 0.08
# inverse the direction and slow down slightly
var collision_shape = $Area2DCollision.get_overlapping_bodies()
if collision_shape.size() > 0:
var collider = collision_shape[0]
var normal = (global_position - collider.global_position).normalized()
velocity = velocity.bounce(normal)
pass # Replace with function body.
@rpc("any_peer", "reliable")
func pick_up(_char: CharacterBody2D):
# does nothing... handled by coin itself!
return false
func _on_area_2d_pickup_body_entered(body: Node2D) -> void:
if !is_collected:
bodyToPickUp = body.get_parent()
pass # Replace with function body.
func _on_area_2d_pickup_body_exited(_body: Node2D) -> void:
bodyToPickUp = null
pass # Replace with function body.
func _on_area_2d_pickup_area_entered(area: Area2D) -> void:
if !is_collected:
bodyToPickUp = area.get_parent()
pass # Replace with function body.
func _on_area_2d_pickup_area_exited(_area: Area2D) -> void:
bodyToPickUp = null
pass # Replace with function body.

View File

@@ -0,0 +1 @@
uid://j4ww03kd5vmc

View File

@@ -0,0 +1,126 @@
[gd_scene load_steps=13 format=3 uid="uid://v1s8j8vtla1o"]
[ext_resource type="Script" uid="uid://j4ww03kd5vmc" path="res://assets/scripts/entities/pickups/coin.gd" id="1_1mphl"]
[ext_resource type="Texture2D" uid="uid://cimek2qjgoqa1" path="res://assets/gfx/pickups/gold_coin.png" id="1_lavav"]
[ext_resource type="AudioStream" uid="uid://b60bke4f5uw4v" path="res://assets/audio/sfx/pickups/coin_pickup.mp3" id="3_cjpjf"]
[ext_resource type="AudioStream" uid="uid://brl8ivwb1l5i7" path="res://assets/audio/sfx/pickups/coin_drop_01.wav.mp3" id="4_06bcn"]
[sub_resource type="Gradient" id="Gradient_06bcn"]
colors = PackedColorArray(0, 0, 0, 1, 0, 0, 0, 0)
[sub_resource type="GradientTexture2D" id="GradientTexture2D_06bcn"]
gradient = SubResource("Gradient_06bcn")
width = 8
height = 8
fill = 1
fill_from = Vector2(0.529915, 0.482906)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_1mphl"]
size = Vector2(3, 5)
[sub_resource type="Animation" id="Animation_06bcn"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [0]
}
[sub_resource type="Animation" id="Animation_cjpjf"]
resource_name = "idle"
length = 0.6
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.1, 0.2, 0.3, 0.4, 0.5),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
"update": 1,
"values": [0, 1, 2, 3, 4, 5]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_538um"]
_data = {
&"RESET": SubResource("Animation_06bcn"),
&"idle": SubResource("Animation_cjpjf")
}
[sub_resource type="RectangleShape2D" id="RectangleShape2D_cjpjf"]
size = Vector2(5, 7)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_lavav"]
size = Vector2(3, 5)
[node name="Coin" type="CharacterBody2D"]
z_index = 10
z_as_relative = false
y_sort_enabled = true
collision_layer = 0
collision_mask = 64
script = ExtResource("1_1mphl")
[node name="Sprite2DShadow" type="Sprite2D" parent="."]
z_index = 1
z_as_relative = false
position = Vector2(0, 3.5)
scale = Vector2(1, 0.125)
texture = SubResource("GradientTexture2D_06bcn")
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
visible = false
position = Vector2(0.5, 0.5)
shape = SubResource("RectangleShape2D_1mphl")
[node name="Sprite2D" type="Sprite2D" parent="."]
texture = ExtResource("1_lavav")
hframes = 6
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
root_node = NodePath("../Sprite2D")
libraries = {
&"": SubResource("AnimationLibrary_538um")
}
autoplay = "idle"
[node name="Area2DCollision" type="Area2D" parent="."]
visible = false
collision_layer = 0
collision_mask = 64
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DCollision"]
position = Vector2(0.5, 0.5)
shape = SubResource("RectangleShape2D_cjpjf")
[node name="Area2DPickup" type="Area2D" parent="."]
visible = false
collision_layer = 0
collision_mask = 768
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DPickup"]
position = Vector2(0.5, 0.5)
shape = SubResource("RectangleShape2D_lavav")
debug_color = Color(0.7, 0.682756, 0.184079, 0.42)
[node name="SfxCoinBounce" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("3_cjpjf")
max_polyphony = 6
[node name="SfxCoinCollect" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("4_06bcn")
[connection signal="body_entered" from="Area2DCollision" to="." method="_on_area_2d_collision_body_entered"]
[connection signal="area_entered" from="Area2DPickup" to="." method="_on_area_2d_pickup_area_entered"]
[connection signal="area_exited" from="Area2DPickup" to="." method="_on_area_2d_pickup_area_exited"]
[connection signal="body_entered" from="Area2DPickup" to="." method="_on_area_2d_pickup_body_entered"]
[connection signal="body_exited" from="Area2DPickup" to="." method="_on_area_2d_pickup_body_exited"]

View File

@@ -0,0 +1,174 @@
extends CharacterBody2D
var it: Item = null
@export var sync_has_been_picked_up: bool = false
var friction = 8.0 # Lower values make the slowdown more gradual
var bounceTimer = 0.0
# Z-axis variables
var positionZ = 4.0 # Start slightly in the air
var velocityZ = 10.0 # Initial upward velocity
var accelerationZ = -330.0 # Gravity
var bounceRestitution = 0.3 # How much bounce energy is retained (0-1)
var minBounceVelocity = 60.0 # Minimum velocity needed to bounce
var sync_position := Vector2()
var sync_velocity := Vector2()
var sync_positionZ: float = 4.0
func _ready() -> void:
add_to_group("loot")
# Initialize item if needed
if it == null:
setItem()
func _process(delta: float) -> void:
if multiplayer.is_server():
if bounceTimer > 0.0:
bounceTimer -= delta
if bounceTimer < 0:
bounceTimer = 0
# Update vertical movement
velocityZ += accelerationZ * delta
positionZ += velocityZ * delta
# Ground collision and bounce
if positionZ <= 0:
velocity = velocity.lerp(Vector2.ZERO, 1.0 - exp(-friction * delta)) # only slow down if on floor
positionZ = 0
if abs(velocityZ) > minBounceVelocity:
print(velocityZ)
#Bounce sound here for items:
#$SfxCoinBounce.volume_db = -1 + (-10-(velocityZ*0.1))
#$SfxCoinBounce.play()
velocityZ = -velocityZ * bounceRestitution
else:
velocityZ = 0
update_sprite_scale()
move_and_slide()
pass
func _physics_process(_delta: float) -> void:
if multiplayer.is_server():
for peer_id in multiplayer.get_peers():
sync_loot.rpc_id(peer_id, position, velocity, positionZ)
if !multiplayer.is_server():
position = sync_position
velocity = sync_velocity
positionZ = sync_positionZ
update_sprite_scale()
pass
@rpc("unreliable")
func sync_loot(pos: Vector2, vel: Vector2, posZ: float):
sync_position = pos
sync_velocity = vel
sync_positionZ = posZ
pass
func update_sprite_scale() -> void:
# Calculate scale based on height
# Maximum height will have scale 1.3, ground will have scale 1.0
var height_factor = positionZ / 50.0 # Assuming 20 is max height
var posY = 0.0 + (2 * positionZ)
var sc = 1.0 + (0.8 * height_factor)
$Sprite2D.scale = Vector2(sc, sc)
$Sprite2D.position.y = -posY
pass
func setItem(iItem: Item = null) -> void:
$Label.visible = false
if iItem != null:
it = iItem
else:
it = Item.new()
if $Sprite2D.texture != null or $Sprite2D.texture.resource_path != it.spritePath:
$Sprite2D.texture = load(it.spritePath)
$Sprite2D.frame = it.spriteFrame
pass
@rpc("any_peer", "reliable", "call_local")
func request_pickup(player_id: int):
print("[NETWORK] request_pickup called on ", "SERVER" if multiplayer.is_server() else "CLIENT", " for player: ", player_id)
if multiplayer.is_server():
print("WE are server... do stuff:")
sync_has_been_picked_up = true
visible = false
# Tell all clients to remove the loot
remove_loot.rpc()
$SfxPickup.play()
await $SfxPickup.finished
# Remove loot on server too
queue_free()
# Called locally by the player picking up the item
func pick_up_local(player_id: int):
if sync_has_been_picked_up:
return
print("[LOCAL] Picking up item for player: ", player_id)
var player = MultiplayerManager.playersNode.get_node(str(player_id))
if player:
print("[LOCAL] we have the player here")
sync_has_been_picked_up = true
visible = false
# Add item to local inventory
player.stats.add_item(it)
# Tell server about pickup
print("we are telling server about pickup", player_id)
if not multiplayer.is_server():
request_pickup.rpc_id(1, player_id)
else:
# Tell all clients to remove the loot
remove_loot.rpc()
$SfxPickup.play()
await $SfxPickup.finished
# Remove loot locally immediately
queue_free()
@rpc("authority", "reliable")
func remove_loot():
visible = false
sync_has_been_picked_up = true
print("[NETWORK] Removing loot from scene")
$SfxPickup.play()
await $SfxPickup.finished
queue_free()
func _on_area_2d_body_entered(_body: Node2D) -> void:
$Label.visible = true
pass # Replace with function body.
func _on_area_2d_body_exited(_body: Node2D) -> void:
$Label.visible = false
pass # Replace with function body.
func _on_area_2d_collision_body_entered(_body: Node2D) -> void:
if bounceTimer == 0:
#$SfxCoinBounce.play()
bounceTimer = 0.08
# inverse the direction and slow down slightly
var collision_shape = $Area2DCollision.get_overlapping_bodies()
if collision_shape.size() > 0:
var collider = collision_shape[0]
var normal = (global_position - collider.global_position).normalized()
velocity = velocity.bounce(normal)
pass # Replace with function body.
func _on_area_2d_pickup_area_entered(_area: Area2D) -> void:
$Label.visible = true
pass # Replace with function body.
func _on_area_2d_pickup_area_exited(_area: Area2D) -> void:
$Label.visible = false
pass # Replace with function body.

View File

@@ -0,0 +1 @@
uid://d2ngv2yvtmnaf

View File

@@ -0,0 +1,79 @@
[gd_scene load_steps=9 format=3 uid="uid://buoaism4nuooj"]
[ext_resource type="Script" uid="uid://d2ngv2yvtmnaf" path="res://assets/scripts/entities/pickups/loot.gd" id="1_ws6g6"]
[ext_resource type="Texture2D" uid="uid://hib38y541eog" path="res://assets/gfx/items_n_shit.png" id="2_1uy5x"]
[ext_resource type="AudioStream" uid="uid://umoxmryvbm01" path="res://assets/audio/sfx/cloth/leather_cloth_01.wav.mp3" id="3_4s0gc"]
[sub_resource type="Gradient" id="Gradient_4s0gc"]
colors = PackedColorArray(0, 0, 0, 1, 0, 0, 0, 0)
[sub_resource type="GradientTexture2D" id="GradientTexture2D_1uy5x"]
gradient = SubResource("Gradient_4s0gc")
width = 8
height = 8
fill = 1
fill_from = Vector2(0.529915, 0.482906)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_4s0gc"]
size = Vector2(14, 14)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_1uy5x"]
size = Vector2(14, 14)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_nu74k"]
size = Vector2(16, 16)
[node name="Loot" type="CharacterBody2D"]
z_index = 10
z_as_relative = false
y_sort_enabled = true
collision_layer = 1024
collision_mask = 64
script = ExtResource("1_ws6g6")
[node name="Sprite2DShadow" type="Sprite2D" parent="."]
z_index = 1
z_as_relative = false
position = Vector2(-2.38419e-07, 8)
scale = Vector2(2, 0.5)
texture = SubResource("GradientTexture2D_1uy5x")
[node name="Sprite2D" type="Sprite2D" parent="."]
texture = ExtResource("2_1uy5x")
hframes = 20
vframes = 14
[node name="SfxPickup" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("3_4s0gc")
[node name="Area2DPickup" type="Area2D" parent="."]
collision_layer = 0
collision_mask = 512
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DPickup"]
shape = SubResource("RectangleShape2D_4s0gc")
[node name="Label" type="Label" parent="."]
offset_left = -20.0
offset_top = -20.0
offset_right = 20.0
offset_bottom = 3.0
theme_override_font_sizes/font_size = 6
text = "Pick up"
horizontal_alignment = 1
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
shape = SubResource("RectangleShape2D_1uy5x")
[node name="Area2DCollision" type="Area2D" parent="."]
collision_layer = 0
collision_mask = 64
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DCollision"]
shape = SubResource("RectangleShape2D_nu74k")
[connection signal="area_entered" from="Area2DPickup" to="." method="_on_area_2d_pickup_area_entered"]
[connection signal="area_exited" from="Area2DPickup" to="." method="_on_area_2d_pickup_area_exited"]
[connection signal="body_entered" from="Area2DPickup" to="." method="_on_area_2d_body_entered"]
[connection signal="body_exited" from="Area2DPickup" to="." method="_on_area_2d_body_exited"]
[connection signal="body_entered" from="Area2DCollision" to="." method="_on_area_2d_collision_body_entered"]

View File

@@ -0,0 +1,66 @@
extends Camera2D
var targetResolution = Vector2i(320,200)
var targetZoom:float = 3.0
@export var minTimeToNextShake:float = 0.0
@export var maxTimeToNextShake:float = 4.0
var timeToNextShake:float = 0.0
var currentTimeToNextShake:float = 0.0
var lerpStrength:float = 0.07
@export var randomStrength:float = 4
@export var shakeFade:float = 2.0
@onready var previousShakeFade = shakeFade
@export var is_shaking = false
@export var diminish_shake = true
var shake_strength: float = 0
var rnd = RandomNumberGenerator.new()
func _process(delta: float) -> void:
#($"../CanvasLayer/LabelPlayerName" as Label).offset_top = $"..".position.y - 30
#($"../CanvasLayer/LabelPlayerName" as Label).offset_left = $"..".position.x - 30
var vp_rect:Rect2 = get_viewport_rect()
targetZoom = ceil(vp_rect.size.y / targetResolution.y)
zoom.x = targetZoom
zoom.y = targetZoom
if is_shaking:
currentTimeToNextShake+=delta
if currentTimeToNextShake>=timeToNextShake:
currentTimeToNextShake = 0
timeToNextShake = rnd.randf_range(minTimeToNextShake, maxTimeToNextShake)
apply_shake()
if shake_strength > 0:
shake_strength = lerpf(shake_strength, 0, shakeFade * delta)
offset = randomOffset()
if shake_strength == 0:
is_shaking = false
else:
offset = Vector2(0,0)
pass
func randomOffset() -> Vector2:
return Vector2(rnd.randf_range(-shake_strength, shake_strength), rnd.randf_range(-shake_strength, shake_strength))
func bombShake(iStrength:float = 4.0, iShakeFade:float = 2.0, iWaitTime:float = 0.4):
if !is_shaking:
previousShakeFade = shakeFade
shakeFade = iShakeFade
randomStrength = iStrength
shake_strength = iStrength
$Timer.wait_time = iWaitTime
$Timer.start(0.0)
is_shaking = true
pass
func apply_shake():
shake_strength = randomStrength
func _on_timer_timeout() -> void:
shakeFade = previousShakeFade
is_shaking = false
pass # Replace with function body.

View File

@@ -0,0 +1 @@
uid://yid4hjp68enj

View File

@@ -0,0 +1,32 @@
extends MultiplayerSynchronizer
var direction_vector = Vector2(0,0)
@onready var player = $".."
func _ready() -> void:
if get_multiplayer_authority() != multiplayer.get_unique_id():
set_process(false)
set_physics_process(false)
pass
func _physics_process(_delta: float) -> void:
pass
func _process(_delta: float) -> void:
if Input.is_action_just_pressed("Attack"):
attack.rpc()
if Input.is_action_just_pressed("Use"):
use.rpc()
grab.rpc()
$TimerGrab.start()
if Input.is_action_just_released("Use"):
not_use()
if not $TimerGrab.is_stopped():
lift.rpc()
else:
release.rpc()
pass

View File

@@ -0,0 +1 @@
uid://co7kkfmgjc54b

View File

@@ -0,0 +1,784 @@
extends CharacterBody2D
@onready var punch_scene = preload("res://scripts/attacks/punch.tscn")
@onready var axe_swing_scene = preload("res://scripts/attacks/axe_swing.tscn")
@onready var sword_slash_scene = preload("res://scripts/attacks/sword_slash.tscn")
@onready var arrow_scene = preload("res://scripts/attacks/arrow.tscn")
@onready var damage_number_scene = preload("res://scripts/components/damage_number.tscn")
@onready var loot_scene = preload("res://scripts/entities/pickups/loot.tscn")
@onready var body_sprite = $Sprite2DBody
@onready var armour_sprite = $Sprite2DArmour
@onready var facial_sprite = $Sprite2DFacialHair
@onready var hair_sprite = $Sprite2DHair
@onready var eye_sprite = $Sprite2DEyes
@onready var eyelash_sprite = $Sprite2DEyeLashes
@onready var boots_sprite = $Sprite2DBoots
@onready var headgear_sprite = $Sprite2DHeadgear
@onready var addon_sprite = $Sprite2DAddons
@onready var attack_sprite = $Sprite2DWeapon
const SPEED = 70.0
const JUMP_VELOCITY = -400.0
var held_entity = null
var grabbed_entity = null
var is_player = true
@export var direction_vector = Vector2(0,0)
const ANIMATIONS = {
"IDLE": {
"frames": [0, 1],
"frameDurations": [500, 500],
"loop": true,
"nextAnimation": null
},
"RUN": {
"frames": [3, 2, 3, 4],
"frameDurations": [140, 140, 140, 140],
"loop": true,
"nextAnimation": null
},
"SWORD": {
"frames": [5, 6, 7, 8],
"frameDurations": [40, 60, 90, 80],
"loop": false,
"nextAnimation": "IDLE"
},
"AXE": {
"frames": [5, 6, 7, 8],
"frameDurations": [50, 70, 100, 90],
"loop": false,
"nextAnimation": "IDLE"
},
"PUNCH": {
"frames": [16, 17, 18],
"frameDurations": [50, 70, 100],
"loop": false,
"nextAnimation": "IDLE"
},
"BOW": {
"frames": [9, 10, 11, 12],
"frameDurations": [80, 110, 110, 80],
"loop": false,
"nextAnimation": "IDLE"
},
"STAFF": {
"frames": [13, 14, 15],
"frameDurations": [200, 200, 400],
"loop": false,
"nextAnimation": "IDLE"
},
"THROW": {
"frames": [16, 17, 18],
"frameDurations": [80, 80, 300],
"loop": false,
"nextAnimation": "IDLE"
},
"CONJURE": {
"frames": [19],
"frameDurations": [400],
"loop": false,
"nextAnimation": "IDLE"
},
"DAMAGE": {
"frames": [20, 21],
"frameDurations": [150, 150],
"loop": false,
"nextAnimation": "IDLE"
},
"DIE": {
"frames": [21, 22, 23, 24],
"frameDurations": [200, 200, 200, 800],
"loop": false,
"nextAnimation": null
},
"IDLE_HOLD": {
"frames": [25],
"frameDurations": [500],
"loop": true,
"nextAnimation": null
},
"RUN_HOLD": {
"frames": [25, 26, 25, 27],
"frameDurations": [150, 150, 150, 150],
"loop": true,
"nextAnimation": null
},
"JUMP": {
"frames": [25, 26, 27, 28],
"frameDurations": [80, 80, 80, 800],
"loop": false,
"nextAnimation": "IDLE"
},
"LIFT": {
"frames": [19,30],
"frameDurations": [70,70],
"loop": false,
"nextAnimation": "IDLE_HOLD"
},
"IDLE_PUSH": {
"frames": [30],
"frameDurations": [10],
"loop": true,
"nextAnimation": null
},
"RUN_PUSH": {
"frames": [30,29,30,31],
"frameDurations": [260,260,260,260],
"loop": true,
"nextAnimation": null
}
}
enum Direction {
UP = 4,
UP_RIGHT = 3,
RIGHT = 2,
DOWN_RIGHT = 1,
DOWN = 0,
DOWN_LEFT = 7,
LEFT = 6,
UP_LEFT = 5
}
@export var direction = Vector2(0,0) # default down
@export var last_direction = Vector2(0,1)
@export var current_direction = Direction.DOWN
var current_frame = 0
var time_since_last_frame = 0.0
@export var current_animation:String = "IDLE":
set(iAnimation):
if current_animation != iAnimation:
current_frame = 0
time_since_last_frame = 0
current_animation = iAnimation
var liftable = true
var is_demo_character = false
var invul_timer:float = 0.0
var invul_duration:float = 2.0
var knockback_strength: float = 160.0
var knockback_duration: float = 0.4
var knockback_timer: float = 0.0
var knockback_direction: Vector2 = Vector2.ZERO
@export var is_attacking = false
@export var is_using = false
@export var is_grabbing = false
@export var is_lifting = false
@export var is_releasing = false
@export var use_button_down = false
@export var use_button_up = false
@export var attack_button_down = false
@export var attack_button_up = false
@export var is_moving = false
@export var isDemoCharacter = false
@export var stats:CharacterStats = CharacterStats.new()
signal player_died
func _ready() -> void:
body_sprite.material = body_sprite.material.duplicate()
boots_sprite.material = boots_sprite.material.duplicate()
armour_sprite.material = armour_sprite.material.duplicate()
facial_sprite.material = facial_sprite.material.duplicate()
hair_sprite.material = hair_sprite.material.duplicate()
eye_sprite.material = eye_sprite.material.duplicate()
eyelash_sprite.material = eyelash_sprite.material.duplicate()
addon_sprite.material = addon_sprite.material.duplicate()
headgear_sprite.material = headgear_sprite.material.duplicate()
attack_sprite.material = attack_sprite.material.duplicate()
if isDemoCharacter:
$Camera2D.enabled = false
return
if multiplayer.get_unique_id() == int(name):
#set_multiplayer_authority(player_id)
$Camera2D.make_current()
$Camera2D.enabled = true
else:
$Camera2D.enabled = false
#($CanvasLayer/LabelPlayerName as Label).offset_top = global_position.y - 30
#($CanvasLayer/LabelPlayerName as Label).offset_left = global_position.x - 30
pass
func _enter_tree() -> void:
#set_multiplayer_authority(player_id)
if !isDemoCharacter:
set_multiplayer_authority(int(str(name)))
print("we are setting multiplayer auth to:", name)
pass
func _handleInput() -> void:
direction_vector.x = Input.get_axis("ui_left", "ui_right")
direction_vector.y = Input.get_axis("ui_up", "ui_down")
direction_vector = direction_vector.normalized()
if Input.is_action_just_pressed("Attack"):
attack.rpc()
if Input.is_action_just_pressed("Use"):
use.rpc()
grab.rpc()
$TimerGrab.start()
if Input.is_action_just_released("Use"):
not_use()
if not $TimerGrab.is_stopped():
lift.rpc()
else:
release.rpc()
pass
func _physics_process(delta: float) -> void:
if isDemoCharacter:
pass
else:
if get_multiplayer_authority() == multiplayer.get_unique_id():
_handleInput()
if stats.hp > 0: # only allow to move if we are alive...
_apply_movement_from_input(delta)
else:
velocity = velocity.move_toward(Vector2.ZERO, 300 * delta)
if knockback_timer > 0:
velocity = velocity.move_toward(Vector2.ZERO, 300 * delta)
knockback_timer -= delta
if knockback_timer <= 0.0:
knockback_timer = 0
if stats.hp > 0:
#print("we are below", knockback_timer, ", delta was:", delta)
stats.is_invulnerable = false
move_and_collide(velocity * delta)
if is_moving:
# this only plays on server.... must play on client also somehow...
if !$SfxWalk.playing and $SfxWalk/TimerWalk.is_stopped():
$SfxWalk/TimerWalk.start()
$SfxWalk.play()
else:
if $SfxWalk.playing:
$SfxWalk.stop()
_apply_animations(delta)
pass
func _apply_movement_from_input(_delta: float) -> void:
direction = direction_vector
if current_animation == "THROW" or current_animation == "DIE" or current_animation == "SWORD" or current_animation == "BOW" or current_animation == "DAMAGE" or current_animation == "LIFT":
pass
else:
var extraString = "_HOLD" if held_entity != null else ""
extraString = "_PUSH" if grabbed_entity != null else extraString
if direction != Vector2.ZERO:
if current_animation != "RUN" + extraString:
time_since_last_frame = 0
current_frame = 0
current_animation = "RUN" + extraString
if grabbed_entity == null:
last_direction = direction
is_moving = true
else:
if current_animation != "IDLE" + extraString:
time_since_last_frame = 0
current_frame = 0
current_animation = "IDLE" + extraString
is_moving = false
var movespeed = SPEED
var terrainMultiplier = 1
var grabMultiplier = 1
# check if player is walking on stairs
if get_parent().get_parent() != null and get_parent().get_parent().has_node("TileMapLayerLower"):
var tile_map = get_parent().get_parent().get_node("TileMapLayerLower")
if tile_map != null:
var player_cell = tile_map.local_to_map(self.global_position)
var cell_tile_data = tile_map.get_cell_tile_data(player_cell)
if cell_tile_data != null:
var terrainData = cell_tile_data.get_custom_data("terrain")
if terrainData != null and terrainData == 8: # 8 = stairs
terrainMultiplier = 0.5
pass
pass
movespeed *= terrainMultiplier
if grabbed_entity != null:
grabMultiplier = 0.3
# set direction to only be last_direction or inverse last_direction
if direction != Vector2.ZERO:
var inverseLastDirection = last_direction*-1
if abs(direction.angle_to(last_direction)) > abs(direction.angle_to(inverseLastDirection)):
direction = inverseLastDirection
else:
direction = last_direction
movespeed *= grabMultiplier
if abs(direction.x) >= 0:
velocity.x = move_toward(velocity.x, direction.x * movespeed, 10)
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
if abs(direction.y) >= 0:
velocity.y = move_toward(velocity.y, direction.y * movespeed, 10)
else:
velocity.y = move_toward(velocity.y, 0, SPEED)
if grabbed_entity != null:
grabbed_entity.velocity = velocity
if is_lifting:
if held_entity == null:
var _a = 2
var _b = 3
pass
if is_attacking:
if grabbed_entity == null and held_entity == null and current_animation != "THROW" and current_animation != "DAMAGE" and current_animation != "DIE":
current_frame = 0
time_since_last_frame = 0
current_animation = "SWORD"
if held_entity != null:
# throw it:
held_entity.throw(last_direction)
current_animation = "THROW"
held_entity = null
is_releasing = false
is_grabbing = false
is_lifting = false
is_attacking = false
pass
pass
if use_button_up:
if grabbed_entity != null and "release" in grabbed_entity:
grabbed_entity.release()
grabbed_entity = null
is_releasing = false
is_grabbing = false
use_button_up = false
if is_releasing:
if held_entity != null:
if velocity.x != 0 or velocity.y != 0:
held_entity.throw(last_direction)
held_entity = null
current_animation = "THROW"
else:
if held_entity.put_down():
held_entity = null
if grabbed_entity != null and "release" in grabbed_entity:
grabbed_entity.release()
grabbed_entity = null
is_releasing = false
is_grabbing = false
if held_entity == null:
is_lifting = false
if held_entity == null and grabbed_entity == null and is_grabbing:
var areas:Array[Area2D] = $Area2DPickup.get_overlapping_areas()
if areas.size() != 0:
for a:Area2D in areas:
# make sure we are looking in direction of the entity
var player_to_pot = (a.get_parent().global_position - self.global_position).normalized()
if player_to_pot.dot(self.last_direction) > 0.78:
if "grab" in a.get_parent() and a.get_parent().grab(self) == true:
if held_entity == null:
is_lifting = false
grabbed_entity = a.get_parent()
current_animation = "IDLE_PUSH"
break
pass
#if held_entity == null:
#is_lifting = false
pass
if held_entity == null and is_lifting:
var areas:Array[Area2D] = $Area2DPickup.get_overlapping_areas()
if areas.size() != 0:
for a:Area2D in areas:
if "lift" in a.get_parent() and a.get_parent() != self and "liftable" in a.get_parent():
# make sure we are looking in direction of the entity
var player_to_pot = (a.get_parent().global_position - self.global_position).normalized()
if player_to_pot.dot(self.last_direction) > 0.78:
if grabbed_entity != null and "release" in grabbed_entity:
grabbed_entity.release()
grabbed_entity = null
is_grabbing = false
held_entity = a.get_parent()
held_entity.lift(self)
current_animation = "LIFT"
break # only allow 1 at a time :)
pass
pass
if grabbed_entity != null and "release" in grabbed_entity:
grabbed_entity.release()
grabbed_entity = null
if grabbed_entity == null:
is_grabbing = false
if held_entity == null:
is_lifting = false
elif held_entity != null and is_lifting == false:
if velocity.x != 0 or velocity.y != 0:
held_entity.throw(last_direction)
held_entity = null
current_animation = "THROW"
else:
if held_entity.put_down():
held_entity = null
else:
is_lifting = true
if grabbed_entity != null and "release" in grabbed_entity:
grabbed_entity.release()
grabbed_entity = null
is_grabbing = false
pass
if is_using:
is_using = false
pass
func _apply_animations(delta: float):
if grabbed_entity == null:
if last_direction.y < 0 and last_direction.x > 0:
current_direction = Direction.UP_RIGHT
elif last_direction.y < 0 and last_direction.x < 0:
current_direction = Direction.UP_LEFT
elif last_direction.y > 0 and last_direction.x > 0:
current_direction = Direction.DOWN_RIGHT
elif last_direction.y > 0 and last_direction.x < 0:
current_direction = Direction.DOWN_LEFT
elif last_direction.y < 0:
current_direction = Direction.UP
elif last_direction.x > 0:
current_direction = Direction.RIGHT
elif last_direction.y > 0:
current_direction = Direction.DOWN
elif last_direction.x < 0:
current_direction = Direction.LEFT
$Sprite2DBody.frame = current_direction * $Sprite2DBody.hframes + ANIMATIONS[current_animation]["frames"][current_frame]
$Sprite2DBoots.frame = $Sprite2DBody.frame
$Sprite2DArmour.frame = $Sprite2DBody.frame
$Sprite2DFacialHair.frame = $Sprite2DBody.frame
$Sprite2DHair.frame = $Sprite2DBody.frame
$Sprite2DEyes.frame = $Sprite2DBody.frame
$Sprite2DEyeLashes.frame = $Sprite2DBody.frame
$Sprite2DAddons.frame = $Sprite2DBody.frame
$Sprite2DHeadgear.frame = $Sprite2DBody.frame
$Sprite2DWeapon.frame = $Sprite2DBody.frame
time_since_last_frame += delta
if time_since_last_frame >= ANIMATIONS[current_animation]["frameDurations"][current_frame] / 1000.0:
current_frame += 1
if current_frame >= len(ANIMATIONS[current_animation]["frames"]):
current_frame -= 1 # so it doesnt bug out...
if ANIMATIONS[current_animation]["loop"]:
current_frame = 0
if ANIMATIONS[current_animation]["nextAnimation"] != null:
current_frame = 0
current_animation = ANIMATIONS[current_animation]["nextAnimation"]
time_since_last_frame = 0
pass
func _stats_changed(iStats: CharacterStats):
if not is_inside_tree():
return
if is_multiplayer_authority():
# Sync stats to other players
sync_player_stats.rpc(
iStats.save() # Convert stats to dictionary for network transfer
)
# check equipment if we have body armour
if iStats.equipment["armour"] == null:
armour_sprite.visible = false
else:
print("armour is:", iStats.equipment["armour"])
if armour_sprite.texture == null or (armour_sprite.texture as Texture2D).resource_path != iStats.equipment["armour"].equipmentPath:
armour_sprite.texture = load(iStats.equipment["armour"].equipmentPath)
armour_sprite.visible = true
for index in iStats.equipment["armour"].colorReplacements.size():
var colorReplacement: Dictionary = iStats.equipment["armour"].colorReplacements[index]
armour_sprite.material.set_shader_parameter("original_" + str(index), (colorReplacement["original"] as Color))
armour_sprite.material.set_shader_parameter("replace_" + str(index), (colorReplacement["replace"] as Color))
if iStats.equipment["headgear"] == null:
headgear_sprite.visible = false
else:
if headgear_sprite.texture == null or (headgear_sprite.texture as Texture2D).resource_path != iStats.equipment["headgear"].equipmentPath:
headgear_sprite.texture = load(iStats.equipment["headgear"].equipmentPath)
headgear_sprite.visible = true
for index in iStats.equipment["headgear"].colorReplacements.size():
var colorReplacement: Dictionary = iStats.equipment["headgear"].colorReplacements[index]
headgear_sprite.material.set_shader_parameter("original_" + str(index), (colorReplacement["original"] as Color))
headgear_sprite.material.set_shader_parameter("replace_" + str(index), (colorReplacement["replace"] as Color))
if iStats.equipment["boots"] == null:
boots_sprite.visible = false
else:
if boots_sprite.texture == null or (boots_sprite.texture as Texture2D).resource_path != iStats.equipment["boots"].equipmentPath:
boots_sprite.texture = load(iStats.equipment["boots"].equipmentPath)
boots_sprite.visible = true
for index in iStats.equipment["boots"].colorReplacements.size():
var colorReplacement: Dictionary = iStats.equipment["boots"].colorReplacements[index]
boots_sprite.material.set_shader_parameter("original_" + str(index), (colorReplacement["original"] as Color))
boots_sprite.material.set_shader_parameter("replace_" + str(index), (colorReplacement["replace"] as Color))
if body_sprite.texture == null or body_sprite.texture.resource_path != iStats.skin:
#var tex:Texture2D =
#print("The resoucre path is:", body_sprite.texture.resource_path)
body_sprite.texture = load(iStats.skin)
#print("now we change it: ", body_sprite.texture.resource_path)
if iStats.facial_hair == "":
facial_sprite.visible = false
elif facial_sprite.texture == null or facial_sprite.texture.resource_path != iStats.facial_hair:
facial_sprite.visible = true
facial_sprite.texture = load(iStats.facial_hair)
#print("facial hair color:", iStats.facial_hair_color)
#facial_sprite.modulate = iStats.facial_hair_color
facial_sprite.material.set_shader_parameter("tint", Vector4(iStats.facial_hair_color.r, iStats.facial_hair_color.g, iStats.facial_hair_color.b, iStats.facial_hair_color.a))
if iStats.hairstyle == "":
hair_sprite.visible = false
elif hair_sprite.texture == null or hair_sprite.texture.resource_path != iStats.hairstyle:
hair_sprite.visible = true
hair_sprite.texture = load(iStats.hairstyle)
hair_sprite.material.set_shader_parameter("tint", Vector4(iStats.hair_color.r, iStats.hair_color.g, iStats.hair_color.b, iStats.hair_color.a))
if iStats.eyes == "":
eye_sprite.visible = false
elif eye_sprite.texture == null or eye_sprite.texture.resource_path != iStats.eyes:
eye_sprite.visible = true
eye_sprite.texture = load(iStats.eyes)
if iStats.eye_lashes == "":
eyelash_sprite.visible = false
elif eyelash_sprite.texture == null or eyelash_sprite.texture.resource_path != iStats.eye_lashes:
eyelash_sprite.visible = true
eyelash_sprite.texture = load(iStats.eye_lashes)
if iStats.add_on == "":
addon_sprite.visible = false
elif addon_sprite.texture == null or addon_sprite.texture.resource_path != iStats.add_on:
addon_sprite.visible = true
addon_sprite.texture = load(iStats.add_on)
_updateHp()
pass
func _updateHp():
$TextureProgressBarHealth.value = stats.hp / stats.maxhp * 100
#print("is server?", multiplayer.is_server())
#print("compare multiplayer id:", multiplayer.get_unique_id(), " with", player_id)
if multiplayer.get_unique_id() == int(name):
(get_parent().get_parent().get_node("HUD/MarginContainer/HBoxContainer/VBoxContainerHearts/TextureProgressBarHearts") as TextureProgressBar).value = $TextureProgressBarHealth.value
(get_parent().get_parent().get_node("HUD/MarginContainer/HBoxContainer/VBoxContainerKills/LabelKillsValue") as Label).text = str(stats.kills)
(get_parent().get_parent().get_node("HUD/MarginContainer/HBoxContainer/VBoxContainerDeaths/LabelDeathsValue") as Label).text = str(stats.deaths)
pass
#$CanvasLayer/LabelPlayerName.text = stats.character_name
$LabelPlayerName.text = stats.character_name
pass
func initStats(iStats: CharacterStats):
stats = iStats
if stats.is_connected("character_changed", _stats_changed):
stats.disconnect("character_changed", _stats_changed)
stats.connect("character_changed", _stats_changed)
if stats.is_connected("signal_drop_item", _drop_item):
stats.disconnect("signal_drop_item", _drop_item)
stats.connect("signal_drop_item", _drop_item)
if grabbed_entity != null and "release" in grabbed_entity:
grabbed_entity.release()
grabbed_entity = null
if held_entity != null and "put_down" in held_entity:
held_entity.put_down()
held_entity = null
is_lifting = false
is_grabbing = false
_stats_changed(stats)
pass
func _drop_item(iItem: Item):
var loot = loot_scene.instantiate()
#GameManager.get_node("Loot").call_deferred("add_child", loot)
loot.setItem(iItem)
loot.global_position = global_position
var angle = last_direction.angle()
var speed = randf_range(50, 100)
var velZ = randf_range(100, 200)
var dir = Vector2.from_angle(angle)
loot.velocity = dir * speed
loot.velocityZ = velZ
pass
func lose_held_entity(_iBody: CharacterBody2D):
held_entity = null
is_lifting = false
is_grabbing = false
pass
@rpc("reliable")
func sync_player_stats(stats_dict: Dictionary):
if not is_multiplayer_authority(): # Only non-authority players should receive updates
# Load the received stats into our stats object
stats.load(stats_dict)
# Update visuals
_stats_changed(stats)
@rpc("any_peer", "reliable")
func take_dmg_sound():
$SfxTakeDamage.play()
pass
@rpc("call_local", "reliable")
func die_sound():
if $SfxTakeDamage.playing:
$SfxTakeDamage.stop()
$SfxDie.play()
pass
func take_damage(iBody: Node2D, _iByWhoOrWhat: Node2D) -> void:
if !stats.is_invulnerable:
take_dmg_sound.rpc()
stats.take_damage(13.0)
stats.is_invulnerable = true
knockback_timer = knockback_duration
if current_animation != "DAMAGE":
time_since_last_frame = 0
current_frame = 0
current_animation = "DAMAGE"
# Calculate knockback direction from the damaging body
knockback_direction = (global_position - iBody.global_position).normalized()
velocity = knockback_direction * knockback_strength
_updateHp()
if held_entity != null:
held_entity.throw(knockback_direction)
is_lifting = false
if grabbed_entity != null and "release" in grabbed_entity:
grabbed_entity.release()
grabbed_entity = null
is_grabbing = false
# Create damage number
if damage_number_scene:
var damage_number = damage_number_scene.instantiate()
get_tree().current_scene.call_deferred("add_child", damage_number)
damage_number.global_position = global_position + Vector2(0, -16)
damage_number.direction = Vector2(0, -1)
damage_number.label = "1"
if stats.hp <= 0:
stats.deaths += 1
sync_player_deaths.rpc(stats.deaths)
if _iByWhoOrWhat != null and _iByWhoOrWhat is CharacterBody2D:
_iByWhoOrWhat.stats.kills += 1
_iByWhoOrWhat.sync_player_kills.rpc(_iByWhoOrWhat.stats.kills) # run for everyone
'
if _iByWhoOrWhat.player_id != multiplayer.get_unique_id():
# Broadcast this character data to all other connected peers
#_iByWhoOrWhat.sync_player_kills.rpc_id(_iByWhoOrWhat.player_id, _iByWhoOrWhat.stats.kills)
pass
else:
_iByWhoOrWhat.stats.forceUpdate()
'
# give score to other player...
if current_animation != "DIE":
time_since_last_frame = 0
current_frame = 0
current_animation = "DIE"
die_sound.rpc()
# wait a bit so we can hear the die sound before removing the player
#_updateScore.rpc()
call_deferred("_on_died")
return
@rpc("call_local", "reliable")
func sync_player_kills(iKills: int):
stats.kills = iKills
stats.forceUpdate()
_updateHp()
MultiplayerManager.updateScore()
pass
@rpc("call_local", "reliable")
func sync_player_deaths(iDeaths: int):
stats.deaths = iDeaths
stats.forceUpdate()
_updateHp()
MultiplayerManager.updateScore()
pass
@rpc("reliable")
func _updateScore():
MultiplayerManager.updateScore()
pass
func _on_died():
emit_signal("player_died")
# remove collision
self.set_collision_layer_value(10, false)
await get_tree().create_timer(2.1).timeout
#reset hp:
# find spawn point:
var spointPouints = get_parent().get_parent().get_node("PlayerSpawnPoints")
var targetPos = null
for spawnP:Node2D in spointPouints.get_children():
var pos = spawnP.position
if targetPos == null:
targetPos = pos
else:
# find spawn position which is furthest from all players...
for pl:CharacterBody2D in get_parent().get_children():
if "is_player" in pl:
# compare
if pl.position.distance_to(pos) > pl.position.distance_to(targetPos):
targetPos = pos
pass
pass
pass
position = targetPos
stats.hp = stats.maxhp
stats.is_invulnerable = false
stats.forceUpdate()
current_animation = "IDLE"
self.set_collision_layer_value(10, true)
pass
@rpc("call_local")
func attack():
is_attacking = true
@rpc("call_local")
func use():
use_button_down = true
@rpc("call_local")
func not_use():
use_button_up = true
@rpc("call_local")
func grab():
is_grabbing = true
@rpc("call_local")
func lift():
is_lifting = !is_lifting
@rpc("call_local")
func release():
is_releasing = true

View File

@@ -0,0 +1 @@
uid://cvvy2s6620mcw

View File

@@ -0,0 +1,332 @@
[gd_scene load_steps=44 format=3 uid="uid://dgtfy455abe1t"]
[ext_resource type="Script" uid="uid://cvvy2s6620mcw" path="res://scripts/entities/player/player.gd" id="1_sgemx"]
[ext_resource type="Texture2D" uid="uid://bkninujaqqvb1" path="res://assets/gfx/Puny-Characters/Layer 0 - Skins/Human1_1.png" id="3_0818e"]
[ext_resource type="Shader" uid="uid://cfd38qf1ojmft" path="res://assets/shaders/cloth.gdshader" id="4_6nxnb"]
[ext_resource type="Script" uid="uid://yid4hjp68enj" path="res://scripts/entities/player/camera_2d.gd" id="4_n1hb6"]
[ext_resource type="Texture2D" uid="uid://dx1fovugabbwc" path="res://assets/gfx/Puny-Characters/Layer 1 - Shoes/IronBoots.png" id="5_2bw0v"]
[ext_resource type="Texture2D" uid="uid://bbqk2lcs772q3" path="res://assets/gfx/Puny-Characters/Layer 2 - Clothes/Armour Body/BronzeArmour.png" id="5_7drg4"]
[ext_resource type="Texture2D" uid="uid://bkiexfnpcaxwa" path="res://assets/gfx/Puny-Characters/Layer 4 - Hairstyle/Facial Hairstyles/Mustache1White.png" id="7_2bw0v"]
[ext_resource type="Texture2D" uid="uid://0lmhxwt7k3e4" path="res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eye Color/EyecolorLightLime.png" id="8_68eso"]
[ext_resource type="Texture2D" uid="uid://ccu5cpyo7jpdr" path="res://assets/gfx/Puny-Characters/Layer 4 - Hairstyle/Hairstyles/MHairstyle8White.png" id="8_pyh4g"]
[ext_resource type="Texture2D" uid="uid://b4vh2v0x58v2f" path="res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eyelashes/MEyelash1.png" id="9_cvm1n"]
[ext_resource type="Texture2D" uid="uid://jxo0e2x145rs" path="res://assets/gfx/Puny-Characters/Layer 7 - Add-ons/Elf Add-ons/ElfEars3.png" id="10_o8aek"]
[ext_resource type="Texture2D" uid="uid://cu5fkio3ajr5i" path="res://assets/gfx/Puny-Characters/Layer 6 - Headgears/French/MusketeerHatPurple.png" id="11_idlgo"]
[ext_resource type="Texture2D" uid="uid://bloqx3mibftjn" path="res://assets/gfx/Puny-Characters/WeaponOverlayer.png" id="12_0818e"]
[ext_resource type="AudioStream" uid="uid://cbio6f0ssxvd6" path="res://assets/audio/sfx/walk/stone/walk_stone_1.wav.mp3" id="14_0818e"]
[ext_resource type="AudioStream" uid="uid://dq1va2882v23v" path="res://assets/audio/sfx/walk/stone/walk_stone_2.wav.mp3" id="15_2bw0v"]
[ext_resource type="AudioStream" uid="uid://dsuf4oa710gi8" path="res://assets/audio/sfx/walk/stone/walk_stone_3.wav.mp3" id="16_pyh4g"]
[ext_resource type="AudioStream" uid="uid://fvhvmxtcq018" path="res://assets/audio/sfx/walk/stone/walk_stone_4.wav.mp3" id="17_jfw4q"]
[ext_resource type="AudioStream" uid="uid://cw74evef8fm0t" path="res://assets/audio/sfx/walk/stone/walk_stone_5.wav.mp3" id="18_fj670"]
[ext_resource type="AudioStream" uid="uid://c43fyqtos11fd" path="res://assets/audio/sfx/walk/stone/walk_stone_6.wav.mp3" id="19_0j5vc"]
[ext_resource type="FontFile" uid="uid://bajcvmidrnc33" path="res://assets/fonts/standard_font.png" id="21_pyh4g"]
[ext_resource type="AudioStream" uid="uid://b4ng0o2en2hkm" path="res://assets/audio/sfx/player/fall_out/player_fall_infinitely-02.wav.mp3" id="22_jfw4q"]
[ext_resource type="AudioStream" uid="uid://bi546r2d771yg" path="res://assets/audio/sfx/player/take_damage/player_damaged_01.wav.mp3" id="23_7puce"]
[ext_resource type="AudioStream" uid="uid://b8trgc0pbomud" path="res://assets/audio/sfx/player/take_damage/player_damaged_02.wav.mp3" id="24_3n1we"]
[ext_resource type="AudioStream" uid="uid://dsnvagvhs152x" path="res://assets/audio/sfx/player/take_damage/player_damaged_03.wav.mp3" id="25_h8vet"]
[ext_resource type="AudioStream" uid="uid://ce51n4tvvflro" path="res://assets/audio/sfx/player/take_damage/player_damaged_04.wav.mp3" id="26_1rlbx"]
[ext_resource type="AudioStream" uid="uid://caclaiagfnr2o" path="res://assets/audio/sfx/player/take_damage/player_damaged_05.wav.mp3" id="27_1sdav"]
[ext_resource type="AudioStream" uid="uid://dighi525ty7sl" path="res://assets/audio/sfx/player/take_damage/player_damaged_06.wav.mp3" id="28_x7koh"]
[ext_resource type="AudioStream" uid="uid://bdhmel5vyixng" path="res://assets/audio/sfx/player/take_damage/player_damaged_07.wav.mp3" id="29_jl8uc"]
[sub_resource type="Gradient" id="Gradient_n1hb6"]
offsets = PackedFloat32Array(0.742243, 0.75179)
colors = PackedColorArray(1, 1, 1, 1, 1, 1, 1, 0)
[sub_resource type="GradientTexture2D" id="GradientTexture2D_n1hb6"]
gradient = SubResource("Gradient_n1hb6")
fill = 1
fill_from = Vector2(0.508547, 0.487179)
fill_to = Vector2(0.961538, 0.034188)
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_fgrik"]
properties/0/path = NodePath(".:position")
properties/0/spawn = true
properties/0/replication_mode = 1
properties/1/path = NodePath(".:is_attacking")
properties/1/spawn = true
properties/1/replication_mode = 2
properties/2/path = NodePath(".:is_using")
properties/2/spawn = true
properties/2/replication_mode = 2
properties/3/path = NodePath(".:current_animation")
properties/3/spawn = true
properties/3/replication_mode = 2
properties/4/path = NodePath(".:last_direction")
properties/4/spawn = true
properties/4/replication_mode = 2
properties/5/path = NodePath(".:is_grabbing")
properties/5/spawn = true
properties/5/replication_mode = 2
properties/6/path = NodePath(".:is_lifting")
properties/6/spawn = true
properties/6/replication_mode = 2
properties/7/path = NodePath(".:use_button_up")
properties/7/spawn = true
properties/7/replication_mode = 2
properties/8/path = NodePath(".:use_button_down")
properties/8/spawn = true
properties/8/replication_mode = 2
properties/9/path = NodePath(".:is_moving")
properties/9/spawn = true
properties/9/replication_mode = 2
properties/10/path = NodePath(".:collision_layer")
properties/10/spawn = true
properties/10/replication_mode = 2
properties/11/path = NodePath(".:direction_vector")
properties/11/spawn = true
properties/11/replication_mode = 2
[sub_resource type="Gradient" id="Gradient_hsjxb"]
offsets = PackedFloat32Array(0.847255, 0.861575)
colors = PackedColorArray(0, 0, 0, 0.611765, 0, 0, 0, 0)
[sub_resource type="GradientTexture2D" id="GradientTexture2D_0818e"]
gradient = SubResource("Gradient_hsjxb")
width = 14
height = 6
fill = 1
fill_from = Vector2(0.504274, 0.478632)
fill_to = Vector2(0.897436, 0.0769231)
[sub_resource type="ShaderMaterial" id="ShaderMaterial_2bw0v"]
shader = ExtResource("4_6nxnb")
shader_parameter/original_0 = Color(0, 0, 0, 1)
shader_parameter/original_1 = Color(0, 0, 0, 1)
shader_parameter/original_2 = Color(0, 0, 0, 1)
shader_parameter/original_3 = Color(0, 0, 0, 1)
shader_parameter/original_4 = Color(0, 0, 0, 1)
shader_parameter/original_5 = Color(0, 0, 0, 1)
shader_parameter/original_6 = Color(0, 0, 0, 1)
shader_parameter/replace_0 = Color(0, 0, 0, 1)
shader_parameter/replace_1 = Color(0, 0, 0, 1)
shader_parameter/replace_2 = Color(0, 0, 0, 1)
shader_parameter/replace_3 = Color(0, 0, 0, 1)
shader_parameter/replace_4 = Color(0, 0, 0, 1)
shader_parameter/replace_5 = Color(0, 0, 0, 1)
shader_parameter/replace_6 = Color(0, 0, 0, 1)
shader_parameter/tint = Color(1, 1, 1, 1)
[sub_resource type="ShaderMaterial" id="ShaderMaterial_8ugno"]
shader = ExtResource("4_6nxnb")
shader_parameter/original_0 = Color(0, 0, 0, 1)
shader_parameter/original_1 = Color(0, 0, 0, 1)
shader_parameter/original_2 = Color(0, 0, 0, 1)
shader_parameter/original_3 = Color(0, 0, 0, 1)
shader_parameter/original_4 = Color(0, 0, 0, 1)
shader_parameter/original_5 = Color(0, 0, 0, 1)
shader_parameter/original_6 = Color(0, 0, 0, 1)
shader_parameter/replace_0 = Color(0, 0, 0, 1)
shader_parameter/replace_1 = Color(0, 0, 0, 1)
shader_parameter/replace_2 = Color(0, 0, 0, 1)
shader_parameter/replace_3 = Color(0, 0, 0, 1)
shader_parameter/replace_4 = Color(0, 0, 0, 1)
shader_parameter/replace_5 = Color(0, 0, 0, 1)
shader_parameter/replace_6 = Color(0, 0, 0, 1)
shader_parameter/tint = Color(1, 1, 1, 1)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_sgemx"]
size = Vector2(8, 6)
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_40ewq"]
streams_count = 6
stream_0/stream = ExtResource("14_0818e")
stream_1/stream = ExtResource("15_2bw0v")
stream_2/stream = ExtResource("16_pyh4g")
stream_3/stream = ExtResource("17_jfw4q")
stream_4/stream = ExtResource("18_fj670")
stream_5/stream = ExtResource("19_0j5vc")
[sub_resource type="RectangleShape2D" id="RectangleShape2D_0818e"]
size = Vector2(10, 8)
[sub_resource type="Gradient" id="Gradient_2bw0v"]
offsets = PackedFloat32Array(0)
colors = PackedColorArray(0, 0, 0, 1)
[sub_resource type="GradientTexture1D" id="GradientTexture1D_pyh4g"]
gradient = SubResource("Gradient_2bw0v")
width = 16
[sub_resource type="Gradient" id="Gradient_jfw4q"]
offsets = PackedFloat32Array(1)
colors = PackedColorArray(1, 0.231947, 0.351847, 1)
[sub_resource type="GradientTexture1D" id="GradientTexture1D_fj670"]
gradient = SubResource("Gradient_jfw4q")
width = 16
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_hnhes"]
streams_count = 7
stream_0/stream = ExtResource("23_7puce")
stream_1/stream = ExtResource("24_3n1we")
stream_2/stream = ExtResource("25_h8vet")
stream_3/stream = ExtResource("26_1rlbx")
stream_4/stream = ExtResource("27_1sdav")
stream_5/stream = ExtResource("28_x7koh")
stream_6/stream = ExtResource("29_jl8uc")
[node name="Player" type="CharacterBody2D"]
collision_layer = 512
collision_mask = 704
script = ExtResource("1_sgemx")
[node name="PlayerLight" type="PointLight2D" parent="."]
z_index = 10
position = Vector2(-1, -6)
blend_mode = 2
range_layer_max = 2
texture = SubResource("GradientTexture2D_n1hb6")
[node name="PlayerSynchronizer" type="MultiplayerSynchronizer" parent="."]
replication_config = SubResource("SceneReplicationConfig_fgrik")
[node name="Sprite2DShadow" type="Sprite2D" parent="."]
position = Vector2(0, 2)
texture = SubResource("GradientTexture2D_0818e")
[node name="Sprite2DBody" type="Sprite2D" parent="."]
material = SubResource("ShaderMaterial_2bw0v")
position = Vector2(0, -5)
texture = ExtResource("3_0818e")
hframes = 35
vframes = 8
[node name="Sprite2DBoots" type="Sprite2D" parent="."]
material = SubResource("ShaderMaterial_8ugno")
position = Vector2(0, -5)
texture = ExtResource("5_2bw0v")
hframes = 35
vframes = 8
[node name="Sprite2DArmour" type="Sprite2D" parent="."]
material = SubResource("ShaderMaterial_8ugno")
position = Vector2(0, -5)
texture = ExtResource("5_7drg4")
hframes = 35
vframes = 8
[node name="Sprite2DFacialHair" type="Sprite2D" parent="."]
material = SubResource("ShaderMaterial_8ugno")
position = Vector2(0, -5)
texture = ExtResource("7_2bw0v")
hframes = 35
vframes = 8
[node name="Sprite2DHair" type="Sprite2D" parent="."]
material = SubResource("ShaderMaterial_8ugno")
position = Vector2(0, -5)
texture = ExtResource("8_pyh4g")
hframes = 35
vframes = 8
[node name="Sprite2DEyes" type="Sprite2D" parent="."]
material = SubResource("ShaderMaterial_8ugno")
position = Vector2(0, -5)
texture = ExtResource("8_68eso")
hframes = 35
vframes = 8
[node name="Sprite2DEyeLashes" type="Sprite2D" parent="."]
material = SubResource("ShaderMaterial_8ugno")
position = Vector2(0, -5)
texture = ExtResource("9_cvm1n")
hframes = 35
vframes = 8
[node name="Sprite2DAddons" type="Sprite2D" parent="."]
material = SubResource("ShaderMaterial_8ugno")
position = Vector2(0, -5)
texture = ExtResource("10_o8aek")
hframes = 35
vframes = 8
[node name="Sprite2DHeadgear" type="Sprite2D" parent="."]
material = SubResource("ShaderMaterial_8ugno")
position = Vector2(0, -5)
texture = ExtResource("11_idlgo")
hframes = 35
vframes = 8
[node name="Sprite2DWeapon" type="Sprite2D" parent="."]
material = SubResource("ShaderMaterial_8ugno")
position = Vector2(0, -5)
texture = ExtResource("12_0818e")
hframes = 35
vframes = 8
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(0, -1)
shape = SubResource("RectangleShape2D_sgemx")
[node name="Camera2D" type="Camera2D" parent="."]
zoom = Vector2(3, 3)
position_smoothing_enabled = true
script = ExtResource("4_n1hb6")
[node name="Timer" type="Timer" parent="Camera2D"]
[node name="SfxWalk" type="AudioStreamPlayer2D" parent="."]
stream = SubResource("AudioStreamRandomizer_40ewq")
volume_db = -12.0
attenuation = 8.28211
bus = &"Sfx"
[node name="TimerWalk" type="Timer" parent="SfxWalk"]
wait_time = 0.3
one_shot = true
[node name="Area2DPickup" type="Area2D" parent="."]
collision_layer = 0
collision_mask = 1536
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DPickup"]
position = Vector2(0, -1)
shape = SubResource("RectangleShape2D_0818e")
debug_color = Color(0.7, 0.495943, 0.135446, 0.42)
[node name="LabelPlayerName" type="Label" parent="."]
z_index = 18
z_as_relative = false
offset_left = -29.82
offset_top = -26.39
offset_right = 30.18
offset_bottom = -20.39
size_flags_horizontal = 3
size_flags_vertical = 6
theme_override_constants/outline_size = 6
theme_override_fonts/font = ExtResource("21_pyh4g")
theme_override_font_sizes/font_size = 6
text = "Playername"
horizontal_alignment = 1
[node name="CanvasLayer" type="CanvasLayer" parent="."]
follow_viewport_enabled = true
[node name="TextureProgressBarHealth" type="TextureProgressBar" parent="."]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -8.0
offset_top = -16.0
offset_right = 8.0
offset_bottom = -15.0
grow_horizontal = 2
grow_vertical = 2
value = 100.0
texture_under = SubResource("GradientTexture1D_pyh4g")
texture_progress = SubResource("GradientTexture1D_fj670")
[node name="SfxDie" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("22_jfw4q")
bus = &"Sfx"
[node name="SfxTakeDamage" type="AudioStreamPlayer2D" parent="."]
stream = SubResource("AudioStreamRandomizer_hnhes")
bus = &"Sfx"
[node name="TimerGrab" type="Timer" parent="."]
wait_time = 0.2
one_shot = true
[connection signal="timeout" from="Camera2D/Timer" to="Camera2D" method="_on_timer_timeout"]

View File

@@ -0,0 +1,237 @@
[gd_scene load_steps=31 format=3 uid="uid://dgtfy455abe1t"]
[ext_resource type="Script" uid="uid://cvvy2s6620mcw" path="res://scripts/entities/player/player.gd" id="1_sgemx"]
[ext_resource type="Script" uid="uid://co7kkfmgjc54b" path="res://scripts/entities/player/input_synchronizer.gd" id="2_fgrik"]
[ext_resource type="Texture2D" uid="uid://bkninujaqqvb1" path="res://assets/gfx/Puny-Characters/Layer 0 - Skins/Human1_1.png" id="3_0818e"]
[ext_resource type="Shader" uid="uid://cfd38qf1ojmft" path="res://assets/shaders/cloth.gdshader" id="4_6nxnb"]
[ext_resource type="Script" uid="uid://yid4hjp68enj" path="res://scripts/entities/player/camera_2d.gd" id="4_n1hb6"]
[ext_resource type="Texture2D" uid="uid://dx1fovugabbwc" path="res://assets/gfx/Puny-Characters/Layer 1 - Shoes/IronBoots.png" id="5_2bw0v"]
[ext_resource type="Texture2D" uid="uid://bbqk2lcs772q3" path="res://assets/gfx/Puny-Characters/Layer 2 - Clothes/Armour Body/BronzeArmour.png" id="5_7drg4"]
[ext_resource type="Texture2D" uid="uid://cvraydpaetsmk" path="res://assets/gfx/Puny-Characters/Layer 4 - Hairstyle/Facial Hairstyles/Beardstyle1Brown.png" id="6_0iycr"]
[ext_resource type="Texture2D" uid="uid://cojaw33qd0lxj" path="res://assets/gfx/Puny-Characters/Layer 4 - Hairstyle/Hairstyles/M Hairstyle 3/MHairstyle3Black.png" id="7_o33e0"]
[ext_resource type="Texture2D" uid="uid://0lmhxwt7k3e4" path="res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eye Color/EyecolorLightLime.png" id="8_68eso"]
[ext_resource type="Texture2D" uid="uid://b4vh2v0x58v2f" path="res://assets/gfx/Puny-Characters/Layer 5 - Eyes/Eyelashes/MEyelash1.png" id="9_cvm1n"]
[ext_resource type="Texture2D" uid="uid://jxo0e2x145rs" path="res://assets/gfx/Puny-Characters/Layer 7 - Add-ons/Elf Add-ons/ElfEars3.png" id="10_o8aek"]
[ext_resource type="Texture2D" uid="uid://cu5fkio3ajr5i" path="res://assets/gfx/Puny-Characters/Layer 6 - Headgears/French/MusketeerHatPurple.png" id="11_idlgo"]
[ext_resource type="Texture2D" uid="uid://bloqx3mibftjn" path="res://assets/gfx/Puny-Characters/WeaponOverlayer.png" id="12_0818e"]
[ext_resource type="AudioStream" uid="uid://cbio6f0ssxvd6" path="res://assets/audio/sfx/walk/stone/walk_stone_1.wav.mp3" id="14_0818e"]
[ext_resource type="AudioStream" uid="uid://dq1va2882v23v" path="res://assets/audio/sfx/walk/stone/walk_stone_2.wav.mp3" id="15_2bw0v"]
[ext_resource type="AudioStream" uid="uid://dsuf4oa710gi8" path="res://assets/audio/sfx/walk/stone/walk_stone_3.wav.mp3" id="16_pyh4g"]
[ext_resource type="AudioStream" uid="uid://fvhvmxtcq018" path="res://assets/audio/sfx/walk/stone/walk_stone_4.wav.mp3" id="17_jfw4q"]
[ext_resource type="AudioStream" uid="uid://cw74evef8fm0t" path="res://assets/audio/sfx/walk/stone/walk_stone_5.wav.mp3" id="18_fj670"]
[ext_resource type="AudioStream" uid="uid://c43fyqtos11fd" path="res://assets/audio/sfx/walk/stone/walk_stone_6.wav.mp3" id="19_0j5vc"]
[sub_resource type="Gradient" id="Gradient_n1hb6"]
offsets = PackedFloat32Array(0.742243, 0.75179)
colors = PackedColorArray(1, 1, 1, 1, 1, 1, 1, 0)
[sub_resource type="GradientTexture2D" id="GradientTexture2D_n1hb6"]
gradient = SubResource("Gradient_n1hb6")
fill = 1
fill_from = Vector2(0.508547, 0.487179)
fill_to = Vector2(0.961538, 0.034188)
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_fgrik"]
properties/0/path = NodePath(".:player_id")
properties/0/spawn = true
properties/0/replication_mode = 2
properties/1/path = NodePath(".:position")
properties/1/spawn = true
properties/1/replication_mode = 1
properties/2/path = NodePath(".:is_attacking")
properties/2/spawn = true
properties/2/replication_mode = 2
properties/3/path = NodePath(".:is_using")
properties/3/spawn = true
properties/3/replication_mode = 2
properties/4/path = NodePath(".:current_animation")
properties/4/spawn = true
properties/4/replication_mode = 2
properties/5/path = NodePath(".:last_direction")
properties/5/spawn = true
properties/5/replication_mode = 2
properties/6/path = NodePath(".:is_grabbing")
properties/6/spawn = true
properties/6/replication_mode = 2
properties/7/path = NodePath(".:is_lifting")
properties/7/spawn = true
properties/7/replication_mode = 2
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_sgemx"]
properties/0/path = NodePath("InputSynchronizer:direction_vector")
properties/0/spawn = true
properties/0/replication_mode = 2
[sub_resource type="Gradient" id="Gradient_hsjxb"]
offsets = PackedFloat32Array(0.847255, 0.861575)
colors = PackedColorArray(0, 0, 0, 0.611765, 0, 0, 0, 0)
[sub_resource type="GradientTexture2D" id="GradientTexture2D_0818e"]
gradient = SubResource("Gradient_hsjxb")
width = 14
height = 6
fill = 1
fill_from = Vector2(0.504274, 0.478632)
fill_to = Vector2(0.897436, 0.0769231)
[sub_resource type="ShaderMaterial" id="ShaderMaterial_8ugno"]
shader = ExtResource("4_6nxnb")
shader_parameter/original_0 = Color(0, 0, 0, 1)
shader_parameter/original_1 = Color(0, 0, 0, 1)
shader_parameter/original_2 = Color(0, 0, 0, 1)
shader_parameter/original_3 = Color(0, 0, 0, 1)
shader_parameter/original_4 = Color(0, 0, 0, 1)
shader_parameter/original_5 = Color(0, 0, 0, 1)
shader_parameter/original_6 = Color(0, 0, 0, 1)
shader_parameter/replace_0 = Color(0, 0, 0, 1)
shader_parameter/replace_1 = Color(0, 0, 0, 1)
shader_parameter/replace_2 = Color(0, 0, 0, 1)
shader_parameter/replace_3 = Color(0, 0, 0, 1)
shader_parameter/replace_4 = Color(0, 0, 0, 1)
shader_parameter/replace_5 = Color(0, 0, 0, 1)
shader_parameter/replace_6 = Color(0, 0, 0, 1)
shader_parameter/tint = Color(1, 1, 1, 1)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_sgemx"]
size = Vector2(8, 6)
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_40ewq"]
streams_count = 6
stream_0/stream = ExtResource("14_0818e")
stream_1/stream = ExtResource("15_2bw0v")
stream_2/stream = ExtResource("16_pyh4g")
stream_3/stream = ExtResource("17_jfw4q")
stream_4/stream = ExtResource("18_fj670")
stream_5/stream = ExtResource("19_0j5vc")
[sub_resource type="RectangleShape2D" id="RectangleShape2D_0818e"]
size = Vector2(10, 8)
[node name="Player" type="CharacterBody2D"]
collision_layer = 512
collision_mask = 704
script = ExtResource("1_sgemx")
[node name="PlayerLight" type="PointLight2D" parent="."]
z_index = 10
position = Vector2(-1, -6)
blend_mode = 2
range_layer_max = 2
texture = SubResource("GradientTexture2D_n1hb6")
[node name="PlayerSynchronizer" type="MultiplayerSynchronizer" parent="."]
replication_config = SubResource("SceneReplicationConfig_fgrik")
[node name="InputSynchronizer" type="MultiplayerSynchronizer" parent="."]
replication_config = SubResource("SceneReplicationConfig_sgemx")
script = ExtResource("2_fgrik")
[node name="TimerGrab" type="Timer" parent="InputSynchronizer"]
wait_time = 0.3
one_shot = true
[node name="Sprite2DShadow" type="Sprite2D" parent="."]
position = Vector2(0, 2)
texture = SubResource("GradientTexture2D_0818e")
[node name="Sprite2DBody" type="Sprite2D" parent="."]
position = Vector2(0, -5)
texture = ExtResource("3_0818e")
hframes = 35
vframes = 8
[node name="Sprite2DBoots" type="Sprite2D" parent="."]
material = SubResource("ShaderMaterial_8ugno")
position = Vector2(0, -5)
texture = ExtResource("5_2bw0v")
hframes = 35
vframes = 8
[node name="Sprite2DArmour" type="Sprite2D" parent="."]
material = SubResource("ShaderMaterial_8ugno")
position = Vector2(0, -5)
texture = ExtResource("5_7drg4")
hframes = 35
vframes = 8
[node name="Sprite2DFacialHair" type="Sprite2D" parent="."]
material = SubResource("ShaderMaterial_8ugno")
position = Vector2(0, -5)
texture = ExtResource("6_0iycr")
hframes = 35
vframes = 8
[node name="Sprite2DHair" type="Sprite2D" parent="."]
material = SubResource("ShaderMaterial_8ugno")
position = Vector2(0, -5)
texture = ExtResource("7_o33e0")
hframes = 35
vframes = 8
[node name="Sprite2DEyes" type="Sprite2D" parent="."]
material = SubResource("ShaderMaterial_8ugno")
position = Vector2(0, -5)
texture = ExtResource("8_68eso")
hframes = 35
vframes = 8
[node name="Sprite2DEyeLashes" type="Sprite2D" parent="."]
material = SubResource("ShaderMaterial_8ugno")
position = Vector2(0, -5)
texture = ExtResource("9_cvm1n")
hframes = 35
vframes = 8
[node name="Sprite2DAddons" type="Sprite2D" parent="."]
material = SubResource("ShaderMaterial_8ugno")
position = Vector2(0, -5)
texture = ExtResource("10_o8aek")
hframes = 35
vframes = 8
[node name="Sprite2DHeadgear" type="Sprite2D" parent="."]
visible = false
material = SubResource("ShaderMaterial_8ugno")
position = Vector2(0, -5)
texture = ExtResource("11_idlgo")
hframes = 35
vframes = 8
[node name="Sprite2DWeapon" type="Sprite2D" parent="."]
material = SubResource("ShaderMaterial_8ugno")
position = Vector2(0, -5)
texture = ExtResource("12_0818e")
hframes = 35
vframes = 8
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(0, -1)
shape = SubResource("RectangleShape2D_sgemx")
[node name="Camera2D" type="Camera2D" parent="."]
zoom = Vector2(3, 3)
position_smoothing_enabled = true
script = ExtResource("4_n1hb6")
[node name="Timer" type="Timer" parent="Camera2D"]
[node name="SfxWalk" type="AudioStreamPlayer2D" parent="."]
stream = SubResource("AudioStreamRandomizer_40ewq")
volume_db = -13.28
attenuation = 8.28211
bus = &"Sfx"
[node name="TimerWalk" type="Timer" parent="SfxWalk"]
wait_time = 0.3
one_shot = true
[node name="Area2DPickup" type="Area2D" parent="."]
collision_layer = 0
collision_mask = 1536
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DPickup"]
position = Vector2(0, -1)
shape = SubResource("RectangleShape2D_0818e")
debug_color = Color(0.7, 0.495943, 0.135446, 0.42)
[connection signal="timeout" from="Camera2D/Timer" to="Camera2D" method="_on_timer_timeout"]

View File

@@ -0,0 +1,51 @@
[gd_scene load_steps=8 format=3 uid="uid://dgtfy455abe1t"]
[ext_resource type="Texture2D" uid="uid://7r43xnr812km" path="res://assets/gfx/Puny-Characters/Layer 0 - Skins/Human1.png" id="1_kwarp"]
[ext_resource type="Script" uid="uid://cvvy2s6620mcw" path="res://scripts/entities/player/player.gd" id="1_sgemx"]
[ext_resource type="Script" uid="uid://co7kkfmgjc54b" path="res://scripts/entities/player/input_synchronizer.gd" id="2_fgrik"]
[ext_resource type="Script" uid="uid://yid4hjp68enj" path="res://scripts/entities/player/camera_2d.gd" id="4_n1hb6"]
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_fgrik"]
properties/0/path = NodePath(".:player_id")
properties/0/spawn = true
properties/0/replication_mode = 2
properties/1/path = NodePath(".:position")
properties/1/spawn = true
properties/1/replication_mode = 2
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_sgemx"]
properties/0/path = NodePath("InputSynchronizer:direction_vector")
properties/0/spawn = true
properties/0/replication_mode = 2
[sub_resource type="RectangleShape2D" id="RectangleShape2D_sgemx"]
size = Vector2(8, 6)
[node name="Player" type="CharacterBody2D"]
collision_layer = 512
collision_mask = 64
script = ExtResource("1_sgemx")
[node name="PlayerSynchronizer" type="MultiplayerSynchronizer" parent="."]
replication_config = SubResource("SceneReplicationConfig_fgrik")
[node name="InputSynchronizer" type="MultiplayerSynchronizer" parent="."]
replication_config = SubResource("SceneReplicationConfig_sgemx")
script = ExtResource("2_fgrik")
[node name="Sprite2D" type="Sprite2D" parent="."]
position = Vector2(0, -4)
texture = ExtResource("1_kwarp")
hframes = 29
vframes = 8
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
shape = SubResource("RectangleShape2D_sgemx")
[node name="Camera2D" type="Camera2D" parent="."]
zoom = Vector2(3, 3)
script = ExtResource("4_n1hb6")
[node name="Timer" type="Timer" parent="Camera2D"]
[connection signal="timeout" from="Camera2D/Timer" to="Camera2D" method="_on_timer_timeout"]

View File

@@ -0,0 +1,504 @@
extends CharacterBody2D
var tileParticleScene = preload("res://scripts/components/TileParticle.tscn")
var liftable = true
var thrown_by = null
var entity_id = ""
var object_name = "pot"
@export var is_being_thrown = false
@export var is_being_lifted = false
@export var is_being_put_down = false
@export var is_being_grabbed = false
@export var is_moving = false
@export var is_spawning = false
var throw_speed = 200
var throw_height = 30
var current_height = 0
var gravity = 800
var holder = null
var flipFromWall = false
# Add Z-axis variables similar to loot.gd
@export var positionZ = 0.0
var velocityZ = 0.0
var accelerationZ = -330.0 # Gravity
var bounceRestitution = 0.3
var minBounceVelocity = 60.0
var destroy_initiated = false
@export var is_destroyed = false
# Smooth lifting variables
var target_position = Vector2.ZERO
var lift_height = 12.0 # Height above player's head
var lift_speed = 10.0 # Speed of smooth movement
var put_down_start_pos = Vector2.ZERO
var put_down_target_pos = Vector2.ZERO
@export var lift_progress = 0.0
var re_enable_collision_after_time = 0.0
var re_enable_time = 0.17
var previousFrameVel = Vector2.ZERO
var hasShownSmokePuffs = false
func _ready() -> void:
if is_spawning:
liftable = false
$Area2DCollision.set_deferred("monitoring", false)
self.set_collision_layer_value(8, false)
self.set_collision_mask_value(9, false)
self.set_collision_mask_value(10, false)
self.set_collision_mask_value(8, false)
update_sprite_scale()
pass
indicate(false)
pass
func _physics_process(delta: float) -> void:
if multiplayer.is_server():
if is_being_thrown:
re_enable_collision_after_time -= delta
if re_enable_collision_after_time <= 0.0:
# enable collisions again
self.set_collision_layer_value(8, true)
self.set_collision_mask_value(9, true)
self.set_collision_mask_value(10, true)
self.set_collision_mask_value(8, true)
re_enable_collision_after_time = 0
# Apply gravity to vertical movement
velocityZ += accelerationZ * delta
positionZ += velocityZ * delta
if positionZ <= 0:
# Pot has hit the ground
positionZ = 0
$SfxLand.play()
$GPUParticles2D.emitting = true
$GPUParticles2D/TimerSmokeParticles.start()
if abs(velocityZ) > minBounceVelocity:
velocityZ = -velocityZ * bounceRestitution
else:
velocityZ = 0
is_being_thrown = false
velocity = velocity.lerp(Vector2.ZERO, 0.5)
if velocity.x == 0 and velocity.y == 0:
thrown_by = null
# Move horizontally
var collision = move_and_collide(velocity * delta)
if collision:
if positionZ == 0:
is_being_thrown = false
update_sprite_scale()
elif is_being_put_down:
lift_progress -= delta * lift_speed
if lift_progress <= 0.0:
$SfxLand.play()
$GPUParticles2D.emitting = true
$GPUParticles2D/TimerSmokeParticles.start()
lift_progress = 0
is_being_put_down = false
is_being_lifted = false
holder = null
positionZ = 0
# enable collisions again
self.set_collision_layer_value(8, true)
self.set_collision_mask_value(9, true)
self.set_collision_mask_value(10, true)
self.set_collision_mask_value(7, true)
self.set_collision_mask_value(8, true)
$Area2DCollision.set_deferred("monitoring", true)
else:
global_position = put_down_start_pos.lerp(put_down_target_pos, 1.0 - lift_progress)
positionZ = lift_height * lift_progress
update_sprite_scale()
elif is_being_lifted:
# Smooth lifting animation
if holder:
$GPUParticles2D.emitting = false
target_position = holder.global_position
#target_position.y -= 2
if lift_progress < 1.0:
lift_progress += delta * lift_speed
lift_progress = min(lift_progress, 1.0)
global_position = global_position.lerp(target_position, lift_progress)
positionZ = lift_height * lift_progress
else:
lift_progress = 1.0
global_position = target_position
positionZ = lift_height
update_sprite_scale()
pass
elif is_being_grabbed:
#if velocity != Vector2.ZERO and velocity != previousFrameVel and hasShownSmokePuffs == false:
if velocity != Vector2.ZERO:
is_moving = true
#hasShownSmokePuffs = true
$GPUParticles2D.emitting = true
$GPUParticles2D/TimerSmokeParticles.start()
if !$SfxDrag2.playing:
$SfxDrag2.play()
else:
is_moving = false
if $SfxDrag2.playing:
$SfxDrag2.stop()
move_and_collide(velocity * delta)
previousFrameVel = velocity
pass
else: # it just spawned:
# Apply gravity to vertical movement
velocityZ += accelerationZ * delta
positionZ += velocityZ * delta
if positionZ <= 0:
if is_spawning:
is_spawning = false
liftable = true
$Area2DCollision.set_deferred("monitoring", true)
self.set_collision_layer_value(8, true)
self.set_collision_mask_value(9, true)
self.set_collision_mask_value(10, true)
self.set_collision_mask_value(8, true)
# Pot has hit the ground
positionZ = 0
if abs(velocityZ) > 30:
$SfxLand.play()
$GPUParticles2D.emitting = true
$GPUParticles2D/TimerSmokeParticles.start()
if abs(velocityZ) > minBounceVelocity:
velocityZ = -velocityZ * bounceRestitution
else:
velocityZ = 0
velocity = velocity.lerp(Vector2.ZERO, 0.5)
move_and_collide(velocity * delta)
update_sprite_scale()
pass
else:
# for client:'
if is_being_thrown:
if $SfxDrag2.playing:
$SfxDrag2.stop()
if positionZ <= 0:
if !$SfxLand.playing:
$SfxLand.play()
$GPUParticles2D.emitting = true
$GPUParticles2D/TimerSmokeParticles.start()
elif is_being_put_down:
if $SfxDrag2.playing:
$SfxDrag2.stop()
if !$SfxLand.playing:
$SfxLand.play()
$GPUParticles2D.emitting = true
$GPUParticles2D/TimerSmokeParticles.start()
elif is_being_lifted:
if $SfxDrag2.playing:
$SfxDrag2.stop()
$GPUParticles2D.emitting = false
elif is_being_grabbed:
if is_moving:
$GPUParticles2D.emitting = true
$GPUParticles2D/TimerSmokeParticles.start()
if !$SfxDrag2.playing:
$SfxDrag2.play()
else:
if $SfxDrag2.playing:
$SfxDrag2.stop()
else:
if is_spawning:
if positionZ <= 0:
$SfxLand.play()
$GPUParticles2D.emitting = true
$GPUParticles2D/TimerSmokeParticles.start()
else:
if $SfxLand.playing:
$SfxLand.stop()
if $SfxDrag2.playing:
$SfxDrag2.stop()
pass
update_sprite_scale()
if is_destroyed and !destroy_initiated:
destroy_initiated = true
show_destroy_effect()
pass
pass
func update_sprite_scale() -> void:
# Calculate scale based on height
# Maximum height will have scale 1.3, ground will have scale 1.0
var height_factor = positionZ / 50.0 # Assuming 50 is max height
var posY = positionZ # Direct mapping of Z to Y offset
var sc = 1.0 + (0.1 * height_factor) # Slightly less scale change than loot (0.3 instead of 0.8)
$Sprite2D.scale = Vector2(sc, sc)
$Sprite2D.offset.y = -posY
# Also update shadow position and scale
if is_being_lifted:
$Sprite2D.z_as_relative = false
$Sprite2D.z_index = 12
$Sprite2DShadow.offset.y = 0 # Base shadow position
else:
$Sprite2D.z_as_relative = true
$Sprite2D.z_index = 0
$Sprite2DShadow.offset.y = 0
#$Sprite2DShadow.scale = Vector2(1.125 * sc, 0.5 * sc) # Scale shadow with height
$Sprite2DShadow.scale = Vector2(1,1)
#$Sprite2DShadow.modulate.
func throw(direction: Vector2, initial_velocity: float = 200):
self.set_collision_mask_value(7, true)
$Area2DCollision.set_deferred("monitoring", true)
$SfxThrow.play()
is_being_lifted = false
is_being_thrown = true
is_being_put_down = false
thrown_by = holder
holder = null
velocity = direction * initial_velocity
velocityZ = throw_height
positionZ = lift_height
current_height = 0
re_enable_collision_after_time = re_enable_time
func grab(new_holder: CharacterBody2D) -> bool:
if positionZ <= 0 and holder == null: # only allow grab if no previous owner and position is 0
$GPUParticles2D/TimerSmokeParticles.stop() #reset...
holder = new_holder
is_being_grabbed = true
indicate(false)
return true
return false
func release():
holder = null
is_being_grabbed = false
hasShownSmokePuffs = false
indicate(true)
if $SfxDrag2.playing:
$SfxDrag2.stop()
pass
func lift(new_holder: CharacterBody2D):
if (new_holder != holder and holder != null) and "lose_held_entity" in holder:
# steal from holder
holder.lose_held_entity(self)
indicate(false)
$Area2DCollision.set_deferred("monitoring", false)
thrown_by = null
holder = new_holder
# disable collisions
self.set_collision_layer_value(8, false)
self.set_collision_mask_value(7, false)
self.set_collision_mask_value(8, false)
self.set_collision_mask_value(9, false)
self.set_collision_mask_value(10, false)
is_being_lifted = true
is_being_grabbed = false
is_being_thrown = false
is_being_put_down = false
lift_progress = 0.0
velocityZ = 0
$SfxLand.play()
func put_down() -> bool:
if not is_being_lifted or is_being_put_down:
return false
var dropDir = holder.last_direction
dropDir.x *= 12
if dropDir.y > 0:
dropDir.y *= 10
else:
dropDir.y *= 10
put_down_target_pos = holder.global_position + dropDir
# First check: Direct space state query for walls
var space_state = get_world_2d().direct_space_state
var params = PhysicsPointQueryParameters2D.new()
params.position = put_down_target_pos
params.collision_mask = 64 # Layer for walls (usually layer 7)
params.collide_with_areas = true
params.collide_with_bodies = true
var results = space_state.intersect_point(params)
if results.size() > 0:
# Found overlapping walls at target position
print("Cannot place pot: Wall in the way")
return false
# Second check: Line of sight between player and target position
var query = PhysicsRayQueryParameters2D.create(
holder.global_position,
put_down_target_pos,
64 # Wall collision mask
)
query.collide_with_areas = true
query.collide_with_bodies = true
var result = space_state.intersect_ray(query)
if result:
# Hit something between player and target position
print("Cannot place pot: Path blocked")
return false
# Third check: Make sure we're not placing on top of another pot or object
params.collision_mask = 128 # Layer for pots/objects
results = space_state.intersect_point(params)
if results.size() > 0:
# Found overlapping objects at target position
print("Cannot place pot: Object in the way")
return false
$Area2DCollision.set_deferred("monitoring", false)
# Position is valid, proceed with putting down
self.set_collision_mask_value(7, true) # instantly reenenable collision with wall
is_being_put_down = true
is_being_lifted = false
put_down_start_pos = global_position
thrown_by = null
holder = null
indicate(true)
return true
func remove():
var fade_tween = create_tween()
fade_tween.set_trans(Tween.TRANS_CUBIC)
fade_tween.set_ease(Tween.EASE_OUT)
fade_tween.tween_property($Sprite2D, "modulate:a", 0.0, 0.6)
#await fade_tween.finished
await $SfxShatter.finished
if $SfxLand.playing:
$SfxLand.stop()
if $SfxDrag2.playing:
$SfxDrag2.stop()
$GPUParticles2D.emitting = false
#$SfxShatter.stop()
if multiplayer.is_server():
call_deferred("queue_free")
pass
func create4TileParticles():
var sprite_texture = $Sprite2D.texture
var frame_width = sprite_texture.get_width() / $Sprite2D.hframes
var frame_height = sprite_texture.get_height() / $Sprite2D.vframes
var frame_x = ($Sprite2D.frame % $Sprite2D.hframes) * frame_width
var frame_y = ($Sprite2D.frame / $Sprite2D.hframes) * frame_height
# Create 4 particles with different directions and different parts of the texture
var directions = [
Vector2(-1, -1).normalized(), # Top-left
Vector2(1, -1).normalized(), # Top-right
Vector2(-1, 1).normalized(), # Bottom-left
Vector2(1, 1).normalized() # Bottom-right
]
var regions = [
Rect2(frame_x, frame_y, frame_width / 2, frame_height / 2), # Top-left
Rect2(frame_x + frame_width / 2, frame_y, frame_width / 2, frame_height / 2), # Top-right
Rect2(frame_x, frame_y + frame_height / 2, frame_width / 2, frame_height / 2), # Bottom-left
Rect2(frame_x + frame_width / 2, frame_y + frame_height / 2, frame_width / 2, frame_height / 2) # Bottom-right
]
for i in range(4):
var tp = tileParticleScene.instantiate() as CharacterBody2D
var spr2D = tp.get_node("Sprite2D") as Sprite2D
tp.global_position = global_position
# Set up the sprite's texture and region
spr2D.texture = sprite_texture
spr2D.region_enabled = true
spr2D.region_rect = regions[i]
# Add some randomness to the velocity
var speed = randf_range(170, 200)
var dir = directions[i] + Vector2(randf_range(-0.2, 0.2), randf_range(-0.2, 0.2))
tp.velocity = dir * speed
# Add some rotation
tp.angular_velocity = randf_range(-7, 7)
get_parent().call_deferred("add_child", tp)
func indicate(iIndicate: bool):
$Indicator.visible = iIndicate
if !liftable or is_being_lifted:
$Indicator.visible = false
pass
func _on_area_2d_collision_body_entered(body: Node2D) -> void:
if is_being_thrown == false or body == self or body == thrown_by:
return
if multiplayer.is_server():
var collision_shape = $Area2DCollision.get_overlapping_bodies()
if collision_shape.size() > 0:
var collider = collision_shape[0]
var normal = (global_position - collider.global_position).normalized()
if abs(velocity.x) > 0.05 or abs(velocity.y) > 0.05:
if "take_damage" in body or body is TileMapLayer or collider is TileMapLayer:
if "take_damage" in body:
body.take_damage(self, thrown_by)
elif collider != self and "breakPot" in collider:
collider.take_damage(self, thrown_by)
# create particles from pot:
print("ye body is:", body)
take_damage.rpc(null, null)
pass
normal = velocity.normalized()
velocity = velocity.bounce(normal) * 0.4 # slow down
pass # Replace with function body.
func show_destroy_effect():
$GPUParticles2D.emitting = true
$Sprite2D.frame = 13 + 19 + 19
$Sprite2DShadow.visible = false
liftable = false
indicate(false)
create4TileParticles()
is_being_thrown = false
$Sprite2DShadow.visible = false
# Play shatter sound
$SfxShatter.play()
self.call_deferred("remove")
pass
@rpc("call_local")
func take_damage(_iBody: Node2D, _iByWhoOrWhat: Node2D) -> void:
is_destroyed = true # will trigger show_destroy_effect for clients...
show_destroy_effect()
# remove all kind of collision since it's broken now...
self.set_deferred("monitoring", false)
self.set_collision_layer_value(8, false)
self.set_collision_mask_value(7, false)
self.set_collision_mask_value(8, false)
self.set_collision_mask_value(9, false)
self.set_collision_mask_value(10, false)
pass
func _on_area_2d_collision_body_exited(_body: Node2D) -> void:
pass # Replace with function body.
func _on_area_2d_pickup_body_entered(_body: Node2D) -> void:
indicate(true)
pass # Replace with function body.
func _on_area_2d_pickup_body_exited(_body: Node2D) -> void:
indicate(false)
pass # Replace with function body.
func _on_timer_smoke_particles_timeout() -> void:
$GPUParticles2D.emitting = false
pass # Replace with function body.

View File

@@ -0,0 +1 @@
uid://k2287cw2fdes

View File

@@ -0,0 +1,904 @@
[gd_scene load_steps=60 format=3 uid="uid://d2ijcp7chc0hu"]
[ext_resource type="Script" uid="uid://bj0ueurl3vovc" path="res://scripts/entities/world/pot.gd" id="1_hsjxb"]
[ext_resource type="Texture2D" uid="uid://ceitcsfb2fq6m" path="res://assets/gfx/fx/big-explosion.png" id="2_8u6fk"]
[ext_resource type="Texture2D" uid="uid://bknascfv4twmi" path="res://assets/gfx/smoke_puffs.png" id="2_cmff4"]
[ext_resource type="Texture2D" uid="uid://b82ej8cgwsd6u" path="res://assets/gfx/pickups/bomb.png" id="4_c3n38"]
[ext_resource type="AudioStream" uid="uid://c880tw8ix4las" path="res://assets/audio/sfx/ambience/rock_rubble_01.wav.mp3" id="5_7nchq"]
[ext_resource type="Texture2D" uid="uid://b1twy68vd7f20" path="res://assets/gfx/pickups/indicator.png" id="10_nb533"]
[ext_resource type="AudioStream" uid="uid://bcy4qh0j2yuss" path="res://assets/audio/sfx/z3/lift.wav" id="11_lq20m"]
[ext_resource type="AudioStream" uid="uid://x0hhwyr2e1u7" path="res://assets/audio/sfx/environment/pot/pot_sweep_move_01.mp3" id="13_hd4fl"]
[ext_resource type="AudioStream" uid="uid://cc6clnct61uk7" path="res://assets/audio/sfx/environment/pot/pot_sweep_move_02.mp3" id="14_0qg0s"]
[ext_resource type="AudioStream" uid="uid://cdjtqf2gbagra" path="res://assets/audio/sfx/environment/pot/pot_sweep_move_03.mp3" id="15_p028i"]
[ext_resource type="AudioStream" uid="uid://bxsowyqt7v637" path="res://assets/audio/sfx/environment/pot/pot_place_01.mp3" id="16_fvw42"]
[ext_resource type="AudioStream" uid="uid://b8x1clggitcoa" path="res://assets/audio/sfx/environment/pot/pot_place_02.mp3" id="17_qjm0l"]
[ext_resource type="AudioStream" uid="uid://bgfvvwyvn128g" path="res://assets/audio/sfx/environment/pot/pot_place_03.mp3" id="18_xfa6j"]
[ext_resource type="AudioStream" uid="uid://67u74sfddmd6" path="res://assets/audio/sfx/environment/pot/pot_place_04.mp3" id="19_3e0oi"]
[ext_resource type="AudioStream" uid="uid://2w73l4k3704x" path="res://assets/audio/sfx/environment/pot/pot_drag1.mp3" id="19_p028i"]
[ext_resource type="AudioStream" uid="uid://cy740ysgtt5n7" path="res://assets/audio/sfx/environment/pot/pot_place_05.mp3" id="20_v2r3y"]
[ext_resource type="AudioStream" uid="uid://bnuh7ima5cq0n" path="res://assets/audio/sfx/environment/pot/pot_drag2.mp3" id="20_wv4em"]
[ext_resource type="AudioStream" uid="uid://b88qwpaix6gjk" path="res://assets/audio/sfx/ambience/explode_01.wav.mp3" id="21_0g7xm"]
[ext_resource type="AudioStream" uid="uid://co7i1f4t8qtqp" path="res://assets/audio/sfx/environment/pot/pot_place_06.mp3" id="21_0qg0s"]
[ext_resource type="AudioStream" uid="uid://ohm0t5c7hw0w" path="res://assets/audio/sfx/player/throw/throw_01.wav.mp3" id="21_hd4fl"]
[ext_resource type="AudioStream" uid="uid://d4dweg04wrw6a" path="res://assets/audio/sfx/sub_weapons/bomb_fuse.mp3" id="22_1n54r"]
[ext_resource type="Texture2D" uid="uid://bd4wdplgk7es5" path="res://assets/gfx/fx/kenney_particle_pack/smoke_01.png" id="26_c3n38"]
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_hsjxb"]
properties/0/path = NodePath(".:position")
properties/0/spawn = true
properties/0/replication_mode = 2
properties/1/path = NodePath(".:positionZ")
properties/1/spawn = true
properties/1/replication_mode = 2
properties/2/path = NodePath(".:is_being_thrown")
properties/2/spawn = true
properties/2/replication_mode = 2
properties/3/path = NodePath(".:is_being_lifted")
properties/3/spawn = true
properties/3/replication_mode = 2
properties/4/path = NodePath(".:is_being_put_down")
properties/4/spawn = true
properties/4/replication_mode = 2
properties/5/path = NodePath(".:collision_mask")
properties/5/spawn = true
properties/5/replication_mode = 2
properties/6/path = NodePath(".:collision_layer")
properties/6/spawn = true
properties/6/replication_mode = 2
properties/7/path = NodePath("Area2DCollision:monitoring")
properties/7/spawn = true
properties/7/replication_mode = 2
properties/8/path = NodePath(".:is_destroyed")
properties/8/spawn = true
properties/8/replication_mode = 2
properties/9/path = NodePath(".:is_being_grabbed")
properties/9/spawn = true
properties/9/replication_mode = 2
properties/10/path = NodePath(".:is_moving")
properties/10/spawn = true
properties/10/replication_mode = 2
properties/11/path = NodePath(".:is_spawning")
properties/11/spawn = true
properties/11/replication_mode = 2
properties/12/path = NodePath(".:is_fused")
properties/12/spawn = true
properties/12/replication_mode = 2
[sub_resource type="Animation" id="Animation_0uxu3"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("ExplosionSprite:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [8]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("ExplosionSprite:visible")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Sprite2DShadow:visible")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("Sprite2D:visible")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
tracks/4/type = "value"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath(".:rotation")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
tracks/5/type = "value"
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/path = NodePath("GlowLight:enabled")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
tracks/6/type = "value"
tracks/6/imported = false
tracks/6/enabled = true
tracks/6/path = NodePath("GlowLight:texture_scale")
tracks/6/interp = 1
tracks/6/loop_wrap = true
tracks/6/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [1.0]
}
tracks/7/type = "value"
tracks/7/imported = false
tracks/7/enabled = true
tracks/7/path = NodePath("GlowLight:energy")
tracks/7/interp = 1
tracks/7/loop_wrap = true
tracks/7/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [2.55]
}
tracks/8/type = "value"
tracks/8/imported = false
tracks/8/enabled = true
tracks/8/path = NodePath("FuseParticles:emitting")
tracks/8/interp = 1
tracks/8/loop_wrap = true
tracks/8/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
tracks/9/type = "value"
tracks/9/imported = false
tracks/9/enabled = true
tracks/9/path = NodePath("GlowLight:position")
tracks/9/interp = 1
tracks/9/loop_wrap = true
tracks/9/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(0, 0)]
}
tracks/10/type = "value"
tracks/10/imported = false
tracks/10/enabled = true
tracks/10/path = NodePath("GlowLight:scale")
tracks/10/interp = 1
tracks/10/loop_wrap = true
tracks/10/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(1, 1)]
}
tracks/11/type = "value"
tracks/11/imported = false
tracks/11/enabled = true
tracks/11/path = NodePath("SmokeParticles:emitting")
tracks/11/interp = 1
tracks/11/loop_wrap = true
tracks/11/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
[sub_resource type="Animation" id="Animation_5mm6m"]
resource_name = "explosion"
length = 0.9
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("ExplosionSprite:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.0333333, 0.0610968, 0.0930812, 0.120627, 0.149375, 0.185276, 0.219713, 0.25692),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1),
"update": 1,
"values": [0, 1, 2, 3, 4, 5, 6, 7, 8]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("ExplosionSprite:visible")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.280232),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [true, false]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Sprite2DShadow:visible")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("Sprite2D:visible")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/4/type = "value"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath(".:rotation")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
tracks/5/type = "value"
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/path = NodePath("GlowLight:enabled")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
tracks/6/type = "value"
tracks/6/imported = false
tracks/6/enabled = true
tracks/6/path = NodePath("GlowLight:energy")
tracks/6/interp = 1
tracks/6/loop_wrap = true
tracks/6/keys = {
"times": PackedFloat32Array(0, 0.0666667, 0.533333),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [2.55, 0.49, 0.0]
}
tracks/7/type = "value"
tracks/7/imported = false
tracks/7/enabled = true
tracks/7/path = NodePath("GlowLight:texture_scale")
tracks/7/interp = 1
tracks/7/loop_wrap = true
tracks/7/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.5]
}
tracks/8/type = "value"
tracks/8/imported = false
tracks/8/enabled = true
tracks/8/path = NodePath("FuseParticles:emitting")
tracks/8/interp = 1
tracks/8/loop_wrap = true
tracks/8/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/9/type = "value"
tracks/9/imported = false
tracks/9/enabled = true
tracks/9/path = NodePath("GlowLight:position")
tracks/9/interp = 1
tracks/9/loop_wrap = true
tracks/9/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(0, 0)]
}
tracks/10/type = "value"
tracks/10/imported = false
tracks/10/enabled = true
tracks/10/path = NodePath("SmokeParticles:emitting")
tracks/10/interp = 1
tracks/10/loop_wrap = true
tracks/10/keys = {
"times": PackedFloat32Array(0, 0.2, 0.9),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 1,
"values": [false, true, false]
}
[sub_resource type="Animation" id="Animation_c3n38"]
resource_name = "fused"
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("FuseParticles:emitting")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite2D:visible")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("GlowLight:enabled")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("GlowLight:texture_scale")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.17]
}
tracks/4/type = "value"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath("GlowLight:position")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(7, -6.5)]
}
tracks/5/type = "value"
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/path = NodePath("GlowLight:scale")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(1, 1)]
}
tracks/6/type = "value"
tracks/6/imported = false
tracks/6/enabled = true
tracks/6/path = NodePath("ExplosionSprite:visible")
tracks/6/interp = 1
tracks/6/loop_wrap = true
tracks/6/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
[sub_resource type="Animation" id="Animation_8u6fk"]
resource_name = "idle"
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("FuseParticles:emitting")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite2D:visible")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("GlowLight:enabled")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("GlowLight:texture_scale")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.17]
}
tracks/4/type = "value"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath("GlowLight:position")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(7, -6.5)]
}
tracks/5/type = "value"
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/path = NodePath("GlowLight:scale")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(0.24, 0.24)]
}
tracks/6/type = "value"
tracks/6/imported = false
tracks/6/enabled = true
tracks/6/path = NodePath("ExplosionSprite:visible")
tracks/6/interp = 1
tracks/6/loop_wrap = true
tracks/6/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_1uhwj"]
_data = {
&"RESET": SubResource("Animation_0uxu3"),
&"explosion": SubResource("Animation_5mm6m"),
&"fused": SubResource("Animation_c3n38"),
&"idle": SubResource("Animation_8u6fk")
}
[sub_resource type="Gradient" id="Gradient_nb533"]
offsets = PackedFloat32Array(0.847255, 0.861575)
colors = PackedColorArray(0, 0, 0, 0.764706, 0, 0, 0, 0)
[sub_resource type="GradientTexture2D" id="GradientTexture2D_87nuj"]
gradient = SubResource("Gradient_nb533")
width = 16
height = 6
fill = 1
fill_from = Vector2(0.504274, 0.478632)
fill_to = Vector2(0.897436, 0.0769231)
[sub_resource type="CanvasItemMaterial" id="CanvasItemMaterial_lq20m"]
particles_animation = true
particles_anim_h_frames = 4
particles_anim_v_frames = 2
particles_anim_loop = false
[sub_resource type="Curve" id="Curve_76fyq"]
_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(0.780549, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0]
point_count = 3
[sub_resource type="CurveTexture" id="CurveTexture_m11t2"]
curve = SubResource("Curve_76fyq")
[sub_resource type="Curve" id="Curve_sb38x"]
_limits = [0.0, 100.0, 0.0, 1.0]
_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(0.733167, 4.55855), 0.0, 0.0, 0, 0, Vector2(0.815461, 91.8906), 0.0, 0.0, 0, 0, Vector2(0.892768, 100), 0.0, 0.0, 0, 0]
point_count = 4
[sub_resource type="CurveTexture" id="CurveTexture_ui3li"]
curve = SubResource("Curve_sb38x")
[sub_resource type="Curve" id="Curve_dtubv"]
_limits = [0.0, 1.0, -1.0, 1.0]
_data = [Vector2(-1, 0), 0.0, 0.0, 0, 0, Vector2(0.0124688, 1), 0.0, 0.0, 0, 0, Vector2(0.516209, 1), 0.0, 0.0, 0, 0, Vector2(0.947631, 0), 0.0, 0.0, 0, 0]
point_count = 4
[sub_resource type="CurveXYZTexture" id="CurveXYZTexture_tjjlx"]
curve_x = SubResource("Curve_dtubv")
[sub_resource type="Curve" id="Curve_1webc"]
_data = [Vector2(0, 0), 0.0, 0.0, 0, 0, Vector2(0.0224439, 1), 0.0, 0.0, 0, 0, Vector2(0.880299, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0]
point_count = 4
[sub_resource type="CurveTexture" id="CurveTexture_sp8mg"]
curve = SubResource("Curve_1webc")
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_iw3no"]
particle_flag_disable_z = true
direction = Vector3(1, 0.2, 0)
spread = 62.79
initial_velocity_min = -30.0
initial_velocity_max = 30.0
directional_velocity_min = -25.0
directional_velocity_max = 25.0
directional_velocity_curve = SubResource("CurveXYZTexture_tjjlx")
gravity = Vector3(0, 0, 0)
damping_max = 100.0
damping_curve = SubResource("CurveTexture_ui3li")
scale_min = 0.8
scale_max = 1.2
scale_curve = SubResource("CurveTexture_sp8mg")
color = Color(1, 1, 1, 0.709804)
alpha_curve = SubResource("CurveTexture_m11t2")
anim_offset_max = 1.0
[sub_resource type="Gradient" id="Gradient_1oak7"]
colors = PackedColorArray(1, 1, 1, 1, 0, 0, 0, 0)
[sub_resource type="GradientTexture1D" id="GradientTexture1D_jcrig"]
gradient = SubResource("Gradient_1oak7")
[sub_resource type="Curve" id="Curve_whlmf"]
_limits = [-1.0, 1.0, 0.0, 1.0]
_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(1, 1), 0.0, 0.0, 0, 0]
point_count = 2
[sub_resource type="CurveTexture" id="CurveTexture_vvkl4"]
curve = SubResource("Curve_whlmf")
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_ayymp"]
particle_flag_disable_z = true
direction = Vector3(1, -1, 0)
spread = 96.695
initial_velocity_min = 8.0
initial_velocity_max = 29.0
gravity = Vector3(0, 0, 0)
linear_accel_min = -15.28
linear_accel_max = 5.3
radial_accel_min = 12.62
radial_accel_max = 13.95
tangential_accel_min = -4.65
tangential_accel_max = 7.28
color = Color(1, 0.564706, 0, 1)
color_ramp = SubResource("GradientTexture1D_jcrig")
hue_variation_min = -0.14
hue_variation_max = 0.14
hue_variation_curve = SubResource("CurveTexture_vvkl4")
[sub_resource type="RectangleShape2D" id="RectangleShape2D_hsjxb"]
size = Vector2(12, 8)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_87nuj"]
size = Vector2(18, 15)
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_wv4em"]
streams_count = 2
stream_0/stream = ExtResource("19_p028i")
stream_1/stream = ExtResource("20_wv4em")
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_fvw42"]
streams_count = 3
stream_0/stream = ExtResource("13_hd4fl")
stream_1/stream = ExtResource("14_0qg0s")
stream_2/stream = ExtResource("15_p028i")
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_icnv3"]
streams_count = 6
stream_0/stream = ExtResource("16_fvw42")
stream_1/stream = ExtResource("17_qjm0l")
stream_2/stream = ExtResource("18_xfa6j")
stream_3/stream = ExtResource("19_3e0oi")
stream_4/stream = ExtResource("20_v2r3y")
stream_5/stream = ExtResource("21_0qg0s")
[sub_resource type="Animation" id="Animation_lq20m"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:offset")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(0, 0)]
}
[sub_resource type="Animation" id="Animation_cmff4"]
resource_name = "indicate"
length = 0.8
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:offset")
tracks/0/interp = 2
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.4, 0.8),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [Vector2(0, 0), Vector2(0, -1), Vector2(0, 0)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_76fyq"]
_data = {
&"RESET": SubResource("Animation_lq20m"),
&"indicate": SubResource("Animation_cmff4")
}
[sub_resource type="RectangleShape2D" id="RectangleShape2D_nb533"]
size = Vector2(14, 10)
[sub_resource type="Gradient" id="Gradient_ccs6w"]
offsets = PackedFloat32Array(0.202864, 1)
colors = PackedColorArray(1, 1, 1, 1, 0, 0, 0, 1)
[sub_resource type="GradientTexture2D" id="GradientTexture2D_mqeoh"]
gradient = SubResource("Gradient_ccs6w")
fill = 1
fill_from = Vector2(0.508547, 0.478632)
fill_to = Vector2(0.854701, 0.145299)
[sub_resource type="Gradient" id="Gradient_5mm6m"]
offsets = PackedFloat32Array(0.0506667, 0.592, 1)
colors = PackedColorArray(0.137255, 0.0470588, 0.0156863, 0.886275, 0.266667, 0.258824, 0.254902, 0.443137, 0, 0, 0, 0)
[sub_resource type="GradientTexture1D" id="GradientTexture1D_0uxu3"]
gradient = SubResource("Gradient_5mm6m")
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_1uhwj"]
particle_flag_disable_z = true
angle_min = -47.8
angle_max = 52.5
inherit_velocity_ratio = 0.226
direction = Vector3(1, -1, 0)
spread = 180.0
initial_velocity_min = 5.0
initial_velocity_max = 14.0
angular_velocity_min = -4.00002
angular_velocity_max = 3.99998
radial_velocity_min = -1.00002
radial_velocity_max = 0.999978
gravity = Vector3(0, -10, 0)
linear_accel_min = -5.13
linear_accel_max = 5.0
radial_accel_min = -4.0
radial_accel_max = 5.0
tangential_accel_min = -2.0
tangential_accel_max = 2.0
damping_max = 0.1
scale_min = 0.05
scale_max = 0.1
color_ramp = SubResource("GradientTexture1D_0uxu3")
[node name="Bomb" type="CharacterBody2D"]
collision_layer = 128
collision_mask = 960
script = ExtResource("1_hsjxb")
[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."]
replication_config = SubResource("SceneReplicationConfig_hsjxb")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
&"": SubResource("AnimationLibrary_1uhwj")
}
autoplay = "idle"
[node name="ExplosionSprite" type="Sprite2D" parent="."]
position = Vector2(0, -19)
texture = ExtResource("2_8u6fk")
hframes = 9
frame = 8
[node name="Sprite2DShadow" type="Sprite2D" parent="."]
z_index = -1
position = Vector2(0, 3)
texture = SubResource("GradientTexture2D_87nuj")
[node name="GPUParticles2D" type="GPUParticles2D" parent="."]
material = SubResource("CanvasItemMaterial_lq20m")
emitting = false
amount = 16
texture = ExtResource("2_cmff4")
interp_to_end = 0.026
preprocess = 0.16
explosiveness = 0.5
randomness = 0.48
use_fixed_seed = true
seed = 1565624367
process_material = SubResource("ParticleProcessMaterial_iw3no")
[node name="TimerSmokeParticles" type="Timer" parent="GPUParticles2D"]
wait_time = 0.12
[node name="FuseParticles" type="GPUParticles2D" parent="."]
position = Vector2(6, -10)
amount = 12
lifetime = 0.4
process_material = SubResource("ParticleProcessMaterial_ayymp")
[node name="Sprite2D" type="Sprite2D" parent="."]
position = Vector2(0, -4)
texture = ExtResource("4_c3n38")
metadata/_edit_lock_ = true
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
visible = false
position = Vector2(0, -1)
shape = SubResource("RectangleShape2D_hsjxb")
[node name="Area2DPickup" type="Area2D" parent="."]
visible = false
collision_layer = 1024
collision_mask = 512
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DPickup"]
position = Vector2(0, -1)
shape = SubResource("RectangleShape2D_87nuj")
debug_color = Color(0.688142, 0.7, 0.0440007, 0.42)
[node name="SfxShatter" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("5_7nchq")
attenuation = 9.84915
panning_strength = 1.46
bus = &"Sfx"
metadata/_edit_lock_ = true
[node name="SfxDrag" type="AudioStreamPlayer2D" parent="."]
stream = SubResource("AudioStreamRandomizer_wv4em")
volume_db = -10.142
bus = &"Sfx"
metadata/_edit_lock_ = true
[node name="SfxDrag2" type="AudioStreamPlayer2D" parent="."]
stream = SubResource("AudioStreamRandomizer_fvw42")
volume_db = -9.703
pitch_scale = 0.77
max_distance = 749.0
attenuation = 10.1965
panning_strength = 1.5
bus = &"Sfx"
metadata/_edit_lock_ = true
[node name="SfxLand" type="AudioStreamPlayer2D" parent="."]
stream = SubResource("AudioStreamRandomizer_icnv3")
attenuation = 6.9644
panning_strength = 1.25
bus = &"Sfx"
metadata/_edit_lock_ = true
[node name="SfxThrow" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("21_hd4fl")
volume_db = -4.708
pitch_scale = 0.54
bus = &"Sfx"
metadata/_edit_lock_ = true
[node name="SfxDrop" type="AudioStreamPlayer2D" parent="."]
bus = &"Sfx"
metadata/_edit_lock_ = true
[node name="SfxPickup" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("11_lq20m")
metadata/_edit_lock_ = true
[node name="Indicator" type="Sprite2D" parent="."]
visible = false
position = Vector2(0, -11)
texture = ExtResource("10_nb533")
[node name="AnimationPlayer" type="AnimationPlayer" parent="Indicator"]
libraries = {
&"": SubResource("AnimationLibrary_76fyq")
}
autoplay = "indicate"
[node name="Area2DCollision" type="Area2D" parent="."]
visible = false
collision_layer = 1024
collision_mask = 704
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DCollision"]
position = Vector2(0, -1)
shape = SubResource("RectangleShape2D_nb533")
debug_color = Color(0.7, 0.132592, 0.232379, 0.42)
[node name="GlowLight" type="PointLight2D" parent="."]
energy = 2.55
texture = SubResource("GradientTexture2D_mqeoh")
[node name="SmokeParticles" type="GPUParticles2D" parent="."]
position = Vector2(0, -18)
amount = 16
texture = ExtResource("26_c3n38")
lifetime = 2.0
explosiveness = 0.93
randomness = 0.75
process_material = SubResource("ParticleProcessMaterial_1uhwj")
[node name="SfxExplosion" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("21_0g7xm")
attenuation = 6.72717
panning_strength = 1.39
bus = &"Sfx"
[node name="SfxBombFuse" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("22_1n54r")
max_distance = 1648.0
attenuation = 6.72717
panning_strength = 1.42
bus = &"Sfx"
[connection signal="timeout" from="GPUParticles2D/TimerSmokeParticles" to="." method="_on_timer_smoke_particles_timeout"]
[connection signal="body_entered" from="Area2DPickup" to="." method="_on_area_2d_pickup_body_entered"]
[connection signal="body_exited" from="Area2DPickup" to="." method="_on_area_2d_pickup_body_exited"]
[connection signal="body_entered" from="Area2DCollision" to="." method="_on_area_2d_collision_body_entered"]
[connection signal="body_exited" from="Area2DCollision" to="." method="_on_area_2d_collision_body_exited"]

View File

@@ -0,0 +1,35 @@
[gd_scene load_steps=5 format=3 uid="uid://bptbhvomylpn"]
[ext_resource type="Texture2D" uid="uid://b2umirwiauk7p" path="res://assets/gfx/pickups/chest.png" id="1_08kib"]
[ext_resource type="AudioStream" uid="uid://cyvxb4c5k75mn" path="res://assets/audio/sfx/player/pickup/item_collect_01.wav" id="2_5eugl"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_3kvu5"]
size = Vector2(16, 11)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_08kib"]
size = Vector2(10, 1)
[node name="Chest" type="CharacterBody2D"]
collision_layer = 128
collision_mask = 64
[node name="Sprite2D" type="Sprite2D" parent="."]
texture = ExtResource("1_08kib")
hframes = 2
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(0, 1.5)
shape = SubResource("RectangleShape2D_3kvu5")
[node name="SfxOpen" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("2_5eugl")
volume_db = -14.205
[node name="Area2DInteraction" type="Area2D" parent="."]
collision_layer = 2048
collision_mask = 512
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DInteraction"]
position = Vector2(0, 7.5)
shape = SubResource("RectangleShape2D_08kib")
debug_color = Color(0.7, 0.673001, 0.190349, 0.42)

View File

@@ -0,0 +1,509 @@
extends CharacterBody2D
var tileParticleScene = preload("res://scripts/components/TileParticle.tscn")
var liftable = true
var thrown_by = null
var entity_id = ""
var object_name = "bomb"
@export var is_being_thrown = false
@export var is_being_lifted = false
@export var is_being_put_down = false
@export var is_being_grabbed = false
@export var is_moving = false
@export var is_spawning = false
@export var is_fused = false
var throw_speed = 200
var throw_height = 30
var current_height = 0
var gravity = 800
var holder = null
var flipFromWall = false
# Add Z-axis variables similar to loot.gd
@export var positionZ = 0.0
var velocityZ = 0.0
var accelerationZ = -330.0 # Gravity
var bounceRestitution = 0.3
var minBounceVelocity = 60.0
var destroy_initiated = false
@export var is_destroyed = false
# Smooth lifting variables
var target_position = Vector2.ZERO
var lift_height = 12.0 # Height above player's head
var lift_speed = 10.0 # Speed of smooth movement
var put_down_start_pos = Vector2.ZERO
var put_down_target_pos = Vector2.ZERO
@export var lift_progress = 0.0
var re_enable_collision_after_time = 0.0
var re_enable_time = 0.17
var previousFrameVel = Vector2.ZERO
var hasShownSmokePuffs = false
func _ready() -> void:
if is_spawning:
liftable = false
$Area2DCollision.set_deferred("monitoring", false)
self.set_collision_layer_value(8, false)
self.set_collision_mask_value(9, false)
self.set_collision_mask_value(10, false)
self.set_collision_mask_value(8, false)
update_sprite_scale()
pass
indicate(false)
pass
func _physics_process(delta: float) -> void:
if multiplayer.is_server():
if is_being_thrown:
re_enable_collision_after_time -= delta
if re_enable_collision_after_time <= 0.0:
# enable collisions again
self.set_collision_layer_value(8, true)
self.set_collision_mask_value(9, true)
self.set_collision_mask_value(10, true)
self.set_collision_mask_value(8, true)
re_enable_collision_after_time = 0
# Apply gravity to vertical movement
velocityZ += accelerationZ * delta
positionZ += velocityZ * delta
if positionZ <= 0:
# Pot has hit the ground
positionZ = 0
$SfxLand.play()
$GPUParticles2D.emitting = true
$GPUParticles2D/TimerSmokeParticles.start()
if abs(velocityZ) > minBounceVelocity:
velocityZ = -velocityZ * bounceRestitution
else:
velocityZ = 0
is_being_thrown = false
velocity = velocity.lerp(Vector2.ZERO, 0.5)
if velocity.x == 0 and velocity.y == 0:
thrown_by = null
# Move horizontally
var collision = move_and_collide(velocity * delta)
if collision:
if positionZ == 0:
is_being_thrown = false
update_sprite_scale()
elif is_being_put_down:
lift_progress -= delta * lift_speed
if lift_progress <= 0.0:
$SfxLand.play()
$GPUParticles2D.emitting = true
$GPUParticles2D/TimerSmokeParticles.start()
lift_progress = 0
is_being_put_down = false
is_being_lifted = false
holder = null
positionZ = 0
# enable collisions again
self.set_collision_layer_value(8, true)
self.set_collision_mask_value(9, true)
self.set_collision_mask_value(10, true)
self.set_collision_mask_value(7, true)
self.set_collision_mask_value(8, true)
$Area2DCollision.set_deferred("monitoring", true)
else:
global_position = put_down_start_pos.lerp(put_down_target_pos, 1.0 - lift_progress)
positionZ = lift_height * lift_progress
update_sprite_scale()
elif is_being_lifted:
# Smooth lifting animation
if holder:
$GPUParticles2D.emitting = false
target_position = holder.global_position
#target_position.y -= 2
if lift_progress < 1.0:
lift_progress += delta * lift_speed
lift_progress = min(lift_progress, 1.0)
global_position = global_position.lerp(target_position, lift_progress)
positionZ = lift_height * lift_progress
else:
lift_progress = 1.0
global_position = target_position
positionZ = lift_height
update_sprite_scale()
pass
elif is_being_grabbed:
#if velocity != Vector2.ZERO and velocity != previousFrameVel and hasShownSmokePuffs == false:
if velocity != Vector2.ZERO:
is_moving = true
#hasShownSmokePuffs = true
$GPUParticles2D.emitting = true
$GPUParticles2D/TimerSmokeParticles.start()
if !$SfxDrag2.playing:
$SfxDrag2.play()
else:
is_moving = false
if $SfxDrag2.playing:
$SfxDrag2.stop()
move_and_collide(velocity * delta)
previousFrameVel = velocity
pass
else: # it just spawned:
# Apply gravity to vertical movement
velocityZ += accelerationZ * delta
positionZ += velocityZ * delta
if positionZ <= 0:
if is_spawning:
is_spawning = false
liftable = true
$Area2DCollision.set_deferred("monitoring", true)
self.set_collision_layer_value(8, true)
self.set_collision_mask_value(9, true)
self.set_collision_mask_value(10, true)
self.set_collision_mask_value(8, true)
# Pot has hit the ground
positionZ = 0
if abs(velocityZ) > 30:
$SfxLand.play()
$GPUParticles2D.emitting = true
$GPUParticles2D/TimerSmokeParticles.start()
if abs(velocityZ) > minBounceVelocity:
velocityZ = -velocityZ * bounceRestitution
else:
velocityZ = 0
velocity = velocity.lerp(Vector2.ZERO, 0.5)
move_and_collide(velocity * delta)
update_sprite_scale()
pass
else:
if is_fused and $AnimationPlayer.current_animation == "idle":
if $SfxBombFuse.playing:
$SfxBombFuse.play()
$AnimationPlayer.play("fused")
# for client:'
if is_being_thrown:
if $SfxDrag2.playing:
$SfxDrag2.stop()
if positionZ <= 0:
if !$SfxLand.playing:
$SfxLand.play()
$GPUParticles2D.emitting = true
$GPUParticles2D/TimerSmokeParticles.start()
elif is_being_put_down:
if $SfxDrag2.playing:
$SfxDrag2.stop()
if !$SfxLand.playing:
$SfxLand.play()
$GPUParticles2D.emitting = true
$GPUParticles2D/TimerSmokeParticles.start()
elif is_being_lifted:
if $SfxDrag2.playing:
$SfxDrag2.stop()
$GPUParticles2D.emitting = false
elif is_being_grabbed:
if is_moving:
$GPUParticles2D.emitting = true
$GPUParticles2D/TimerSmokeParticles.start()
if !$SfxDrag2.playing:
$SfxDrag2.play()
else:
if $SfxDrag2.playing:
$SfxDrag2.stop()
else:
if is_spawning:
if positionZ <= 0:
$SfxLand.play()
$GPUParticles2D.emitting = true
$GPUParticles2D/TimerSmokeParticles.start()
else:
if $SfxLand.playing:
$SfxLand.stop()
if $SfxDrag2.playing:
$SfxDrag2.stop()
pass
update_sprite_scale()
if is_destroyed and !destroy_initiated:
destroy_initiated = true
show_destroy_effect()
pass
pass
func update_sprite_scale() -> void:
# Calculate scale based on height
# Maximum height will have scale 1.3, ground will have scale 1.0
var height_factor = positionZ / 50.0 # Assuming 50 is max height
var posY = positionZ # Direct mapping of Z to Y offset
var sc = 1.0 + (0.1 * height_factor) # Slightly less scale change than loot (0.3 instead of 0.8)
$Sprite2D.scale = Vector2(sc, sc)
$Sprite2D.offset.y = -posY
# Also update shadow position and scale
if is_being_lifted:
$Sprite2D.z_as_relative = false
$Sprite2D.z_index = 12
$Sprite2DShadow.offset.y = 0 # Base shadow position
else:
$Sprite2D.z_as_relative = true
$Sprite2D.z_index = 0
$Sprite2DShadow.offset.y = 0
#$Sprite2DShadow.scale = Vector2(1.125 * sc, 0.5 * sc) # Scale shadow with height
$Sprite2DShadow.scale = Vector2(1,1)
#$Sprite2DShadow.modulate.
func throw(direction: Vector2, initial_velocity: float = 200):
self.set_collision_mask_value(7, true)
$Area2DCollision.set_deferred("monitoring", true)
$SfxThrow.play()
is_being_lifted = false
is_being_thrown = true
is_being_put_down = false
thrown_by = holder
holder = null
velocity = direction * initial_velocity
velocityZ = throw_height
positionZ = lift_height
current_height = 0
re_enable_collision_after_time = re_enable_time
func grab(new_holder: CharacterBody2D) -> bool:
if positionZ <= 0 and holder == null: # only allow grab if no previous owner and position is 0
$GPUParticles2D/TimerSmokeParticles.stop() #reset...
holder = new_holder
is_being_grabbed = true
indicate(false)
return true
return false
func release():
holder = null
is_being_grabbed = false
hasShownSmokePuffs = false
indicate(true)
if $SfxDrag2.playing:
$SfxDrag2.stop()
pass
func lift(new_holder: CharacterBody2D):
if (new_holder != holder and holder != null) and "lose_held_entity" in holder:
# steal from holder
holder.lose_held_entity(self)
indicate(false)
$Area2DCollision.set_deferred("monitoring", false)
thrown_by = null
holder = new_holder
# disable collisions
self.set_collision_layer_value(8, false)
self.set_collision_mask_value(7, false)
self.set_collision_mask_value(8, false)
self.set_collision_mask_value(9, false)
self.set_collision_mask_value(10, false)
is_being_lifted = true
is_being_grabbed = false
is_being_thrown = false
is_being_put_down = false
lift_progress = 0.0
velocityZ = 0
$SfxLand.play()
func put_down() -> bool:
if not is_being_lifted or is_being_put_down:
return false
var dropDir = holder.last_direction
dropDir.x *= 12
if dropDir.y > 0:
dropDir.y *= 10
else:
dropDir.y *= 10
put_down_target_pos = holder.global_position + dropDir
# First check: Direct space state query for walls
var space_state = get_world_2d().direct_space_state
var params = PhysicsPointQueryParameters2D.new()
params.position = put_down_target_pos
params.collision_mask = 64 # Layer for walls (usually layer 7)
params.collide_with_areas = true
params.collide_with_bodies = true
var results = space_state.intersect_point(params)
if results.size() > 0:
# Found overlapping walls at target position
print("Cannot place pot: Wall in the way")
return false
# Second check: Line of sight between player and target position
var query = PhysicsRayQueryParameters2D.create(
holder.global_position,
put_down_target_pos,
64 # Wall collision mask
)
query.collide_with_areas = true
query.collide_with_bodies = true
var result = space_state.intersect_ray(query)
if result:
# Hit something between player and target position
print("Cannot place pot: Path blocked")
return false
# Third check: Make sure we're not placing on top of another pot or object
params.collision_mask = 128 # Layer for pots/objects
results = space_state.intersect_point(params)
if results.size() > 0:
# Found overlapping objects at target position
print("Cannot place pot: Object in the way")
return false
$Area2DCollision.set_deferred("monitoring", false)
# Position is valid, proceed with putting down
self.set_collision_mask_value(7, true) # instantly reenenable collision with wall
is_being_put_down = true
is_being_lifted = false
put_down_start_pos = global_position
thrown_by = null
holder = null
indicate(true)
return true
func remove():
var fade_tween = create_tween()
fade_tween.set_trans(Tween.TRANS_CUBIC)
fade_tween.set_ease(Tween.EASE_OUT)
fade_tween.tween_property($Sprite2D, "modulate:a", 0.0, 0.6)
#await fade_tween.finished
await $SfxShatter.finished
if $SfxLand.playing:
$SfxLand.stop()
if $SfxDrag2.playing:
$SfxDrag2.stop()
$GPUParticles2D.emitting = false
#$SfxShatter.stop()
if multiplayer.is_server():
call_deferred("queue_free")
pass
func create4TileParticles():
var sprite_texture = $Sprite2D.texture
var frame_width = sprite_texture.get_width() / $Sprite2D.hframes
var frame_height = sprite_texture.get_height() / $Sprite2D.vframes
var frame_x = ($Sprite2D.frame % $Sprite2D.hframes) * frame_width
var frame_y = ($Sprite2D.frame / $Sprite2D.hframes) * frame_height
# Create 4 particles with different directions and different parts of the texture
var directions = [
Vector2(-1, -1).normalized(), # Top-left
Vector2(1, -1).normalized(), # Top-right
Vector2(-1, 1).normalized(), # Bottom-left
Vector2(1, 1).normalized() # Bottom-right
]
var regions = [
Rect2(frame_x, frame_y, frame_width / 2, frame_height / 2), # Top-left
Rect2(frame_x + frame_width / 2, frame_y, frame_width / 2, frame_height / 2), # Top-right
Rect2(frame_x, frame_y + frame_height / 2, frame_width / 2, frame_height / 2), # Bottom-left
Rect2(frame_x + frame_width / 2, frame_y + frame_height / 2, frame_width / 2, frame_height / 2) # Bottom-right
]
for i in range(4):
var tp = tileParticleScene.instantiate() as CharacterBody2D
var spr2D = tp.get_node("Sprite2D") as Sprite2D
tp.global_position = global_position
# Set up the sprite's texture and region
spr2D.texture = sprite_texture
spr2D.region_enabled = true
spr2D.region_rect = regions[i]
# Add some randomness to the velocity
var speed = randf_range(170, 200)
var dir = directions[i] + Vector2(randf_range(-0.2, 0.2), randf_range(-0.2, 0.2))
tp.velocity = dir * speed
# Add some rotation
tp.angular_velocity = randf_range(-7, 7)
get_parent().call_deferred("add_child", tp)
func indicate(iIndicate: bool):
$Indicator.visible = iIndicate
if !liftable or is_being_lifted:
$Indicator.visible = false
pass
func _on_area_2d_collision_body_entered(body: Node2D) -> void:
if is_being_thrown == false or body == self or body == thrown_by:
return
if multiplayer.is_server():
var collision_shape = $Area2DCollision.get_overlapping_bodies()
if collision_shape.size() > 0:
var collider = collision_shape[0]
var normal = (global_position - collider.global_position).normalized()
if abs(velocity.x) > 0.05 or abs(velocity.y) > 0.05:
if "take_damage" in body or body is TileMapLayer or collider is TileMapLayer:
if "take_damage" in body:
body.take_damage(self, thrown_by)
elif collider != self and "breakPot" in collider:
collider.take_damage(self, thrown_by)
# create particles from pot:
print("ye body is:", body)
take_damage.rpc(null, null)
pass
normal = velocity.normalized()
velocity = velocity.bounce(normal) * 0.4 # slow down
pass # Replace with function body.
func show_destroy_effect():
$GPUParticles2D.emitting = true
$Sprite2D.frame = 13 + 19 + 19
$Sprite2DShadow.visible = false
liftable = false
indicate(false)
create4TileParticles()
is_being_thrown = false
$Sprite2DShadow.visible = false
# Play shatter sound
$SfxShatter.play()
self.call_deferred("remove")
pass
@rpc("call_local")
func take_damage(_iBody: Node2D, _iByWhoOrWhat: Node2D) -> void:
is_destroyed = true # will trigger show_destroy_effect for clients...
show_destroy_effect()
# remove all kind of collision since it's broken now...
self.set_deferred("monitoring", false)
self.set_collision_layer_value(8, false)
self.set_collision_mask_value(7, false)
self.set_collision_mask_value(8, false)
self.set_collision_mask_value(9, false)
self.set_collision_mask_value(10, false)
pass
func _on_area_2d_collision_body_exited(_body: Node2D) -> void:
pass # Replace with function body.
func _on_area_2d_pickup_body_entered(_body: Node2D) -> void:
indicate(true)
pass # Replace with function body.
func _on_area_2d_pickup_body_exited(_body: Node2D) -> void:
indicate(false)
pass # Replace with function body.
func _on_timer_smoke_particles_timeout() -> void:
$GPUParticles2D.emitting = false
pass # Replace with function body.

View File

@@ -0,0 +1 @@
uid://bj0ueurl3vovc

View File

@@ -0,0 +1,323 @@
[gd_scene load_steps=48 format=3 uid="uid://bdlg5orah64m5"]
[ext_resource type="Script" uid="uid://bj0ueurl3vovc" path="res://scripts/entities/world/pot.gd" id="1_hsjxb"]
[ext_resource type="Texture2D" uid="uid://bu4dq78f8lgj5" path="res://assets/gfx/sheet_18.png" id="1_rxnv2"]
[ext_resource type="Texture2D" uid="uid://bknascfv4twmi" path="res://assets/gfx/smoke_puffs.png" id="2_cmff4"]
[ext_resource type="AudioStream" uid="uid://fl0rfi4in3n4" path="res://assets/audio/sfx/environment/pot/Drunk lad destroys plant pot.mp3" id="3_vktry"]
[ext_resource type="AudioStream" uid="uid://dejjc0uqthi1b" path="res://assets/audio/sfx/environment/pot/pot_destroy_sound1.mp3" id="4_nb533"]
[ext_resource type="AudioStream" uid="uid://iuxunaogc8xr" path="res://assets/audio/sfx/environment/pot/pot_destroy_sound2.mp3" id="5_cmff4"]
[ext_resource type="AudioStream" uid="uid://bfqusej0pbxem" path="res://assets/audio/sfx/environment/pot/pot_destroy_sound3.mp3" id="6_lq20m"]
[ext_resource type="AudioStream" uid="uid://dq461vpiih3lc" path="res://assets/audio/sfx/environment/pot/pot_destroy_sound4.mp3" id="7_76fyq"]
[ext_resource type="AudioStream" uid="uid://cg1ndvx4t7xtd" path="res://assets/audio/sfx/environment/pot/pot_destroy_sound5.mp3" id="8_m11t2"]
[ext_resource type="AudioStream" uid="uid://bt5npaenq15h2" path="res://assets/audio/sfx/environment/pot/smaller_pot_crash.mp3" id="9_sb38x"]
[ext_resource type="Texture2D" uid="uid://b1twy68vd7f20" path="res://assets/gfx/pickups/indicator.png" id="10_nb533"]
[ext_resource type="AudioStream" uid="uid://bcy4qh0j2yuss" path="res://assets/audio/sfx/z3/lift.wav" id="11_lq20m"]
[ext_resource type="AudioStream" uid="uid://x0hhwyr2e1u7" path="res://assets/audio/sfx/environment/pot/pot_sweep_move_01.mp3" id="13_hd4fl"]
[ext_resource type="AudioStream" uid="uid://cc6clnct61uk7" path="res://assets/audio/sfx/environment/pot/pot_sweep_move_02.mp3" id="14_0qg0s"]
[ext_resource type="AudioStream" uid="uid://cdjtqf2gbagra" path="res://assets/audio/sfx/environment/pot/pot_sweep_move_03.mp3" id="15_p028i"]
[ext_resource type="AudioStream" uid="uid://bxsowyqt7v637" path="res://assets/audio/sfx/environment/pot/pot_place_01.mp3" id="16_fvw42"]
[ext_resource type="AudioStream" uid="uid://b8x1clggitcoa" path="res://assets/audio/sfx/environment/pot/pot_place_02.mp3" id="17_qjm0l"]
[ext_resource type="AudioStream" uid="uid://bgfvvwyvn128g" path="res://assets/audio/sfx/environment/pot/pot_place_03.mp3" id="18_xfa6j"]
[ext_resource type="AudioStream" uid="uid://67u74sfddmd6" path="res://assets/audio/sfx/environment/pot/pot_place_04.mp3" id="19_3e0oi"]
[ext_resource type="AudioStream" uid="uid://2w73l4k3704x" path="res://assets/audio/sfx/environment/pot/pot_drag1.mp3" id="19_p028i"]
[ext_resource type="AudioStream" uid="uid://cy740ysgtt5n7" path="res://assets/audio/sfx/environment/pot/pot_place_05.mp3" id="20_v2r3y"]
[ext_resource type="AudioStream" uid="uid://bnuh7ima5cq0n" path="res://assets/audio/sfx/environment/pot/pot_drag2.mp3" id="20_wv4em"]
[ext_resource type="AudioStream" uid="uid://co7i1f4t8qtqp" path="res://assets/audio/sfx/environment/pot/pot_place_06.mp3" id="21_0qg0s"]
[ext_resource type="AudioStream" uid="uid://ohm0t5c7hw0w" path="res://assets/audio/sfx/player/throw/throw_01.wav.mp3" id="21_hd4fl"]
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_hsjxb"]
properties/0/path = NodePath(".:position")
properties/0/spawn = true
properties/0/replication_mode = 2
properties/1/path = NodePath(".:positionZ")
properties/1/spawn = true
properties/1/replication_mode = 2
properties/2/path = NodePath(".:is_being_thrown")
properties/2/spawn = true
properties/2/replication_mode = 2
properties/3/path = NodePath(".:is_being_lifted")
properties/3/spawn = true
properties/3/replication_mode = 2
properties/4/path = NodePath(".:is_being_put_down")
properties/4/spawn = true
properties/4/replication_mode = 2
properties/5/path = NodePath(".:collision_mask")
properties/5/spawn = true
properties/5/replication_mode = 2
properties/6/path = NodePath(".:collision_layer")
properties/6/spawn = true
properties/6/replication_mode = 2
properties/7/path = NodePath("Area2DCollision:monitoring")
properties/7/spawn = true
properties/7/replication_mode = 2
properties/8/path = NodePath(".:is_destroyed")
properties/8/spawn = true
properties/8/replication_mode = 2
properties/9/path = NodePath(".:is_being_grabbed")
properties/9/spawn = true
properties/9/replication_mode = 2
properties/10/path = NodePath(".:is_moving")
properties/10/spawn = true
properties/10/replication_mode = 2
properties/11/path = NodePath(".:is_spawning")
properties/11/spawn = true
properties/11/replication_mode = 2
[sub_resource type="Gradient" id="Gradient_nb533"]
offsets = PackedFloat32Array(0.847255, 0.861575)
colors = PackedColorArray(0, 0, 0, 0.764706, 0, 0, 0, 0)
[sub_resource type="GradientTexture2D" id="GradientTexture2D_87nuj"]
gradient = SubResource("Gradient_nb533")
width = 16
height = 6
fill = 1
fill_from = Vector2(0.504274, 0.478632)
fill_to = Vector2(0.897436, 0.0769231)
[sub_resource type="CanvasItemMaterial" id="CanvasItemMaterial_lq20m"]
particles_animation = true
particles_anim_h_frames = 4
particles_anim_v_frames = 2
particles_anim_loop = false
[sub_resource type="Curve" id="Curve_76fyq"]
_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(0.780549, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0]
point_count = 3
[sub_resource type="CurveTexture" id="CurveTexture_m11t2"]
curve = SubResource("Curve_76fyq")
[sub_resource type="Curve" id="Curve_sb38x"]
_limits = [0.0, 100.0, 0.0, 1.0]
_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(0.733167, 4.55855), 0.0, 0.0, 0, 0, Vector2(0.815461, 91.8906), 0.0, 0.0, 0, 0, Vector2(0.892768, 100), 0.0, 0.0, 0, 0]
point_count = 4
[sub_resource type="CurveTexture" id="CurveTexture_ui3li"]
curve = SubResource("Curve_sb38x")
[sub_resource type="Curve" id="Curve_dtubv"]
_limits = [0.0, 1.0, -1.0, 1.0]
_data = [Vector2(-1, 0), 0.0, 0.0, 0, 0, Vector2(0.0124688, 1), 0.0, 0.0, 0, 0, Vector2(0.516209, 1), 0.0, 0.0, 0, 0, Vector2(0.947631, 0), 0.0, 0.0, 0, 0]
point_count = 4
[sub_resource type="CurveXYZTexture" id="CurveXYZTexture_tjjlx"]
curve_x = SubResource("Curve_dtubv")
[sub_resource type="Curve" id="Curve_1webc"]
_data = [Vector2(0, 0), 0.0, 0.0, 0, 0, Vector2(0.0224439, 1), 0.0, 0.0, 0, 0, Vector2(0.880299, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0]
point_count = 4
[sub_resource type="CurveTexture" id="CurveTexture_sp8mg"]
curve = SubResource("Curve_1webc")
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_iw3no"]
particle_flag_disable_z = true
direction = Vector3(1, 0.2, 0)
spread = 62.79
initial_velocity_min = -30.0
initial_velocity_max = 30.0
directional_velocity_min = -25.0
directional_velocity_max = 25.0
directional_velocity_curve = SubResource("CurveXYZTexture_tjjlx")
gravity = Vector3(0, 0, 0)
damping_max = 100.0
damping_curve = SubResource("CurveTexture_ui3li")
scale_min = 0.8
scale_max = 1.2
scale_curve = SubResource("CurveTexture_sp8mg")
color = Color(1, 1, 1, 0.709804)
alpha_curve = SubResource("CurveTexture_m11t2")
anim_offset_max = 1.0
[sub_resource type="RectangleShape2D" id="RectangleShape2D_hsjxb"]
size = Vector2(12, 8)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_87nuj"]
size = Vector2(18, 15)
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_ui3li"]
streams_count = 7
stream_0/stream = ExtResource("3_vktry")
stream_1/stream = ExtResource("4_nb533")
stream_2/stream = ExtResource("5_cmff4")
stream_3/stream = ExtResource("6_lq20m")
stream_4/stream = ExtResource("7_76fyq")
stream_5/stream = ExtResource("8_m11t2")
stream_6/stream = ExtResource("9_sb38x")
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_wv4em"]
streams_count = 2
stream_0/stream = ExtResource("19_p028i")
stream_1/stream = ExtResource("20_wv4em")
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_fvw42"]
streams_count = 3
stream_0/stream = ExtResource("13_hd4fl")
stream_1/stream = ExtResource("14_0qg0s")
stream_2/stream = ExtResource("15_p028i")
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_icnv3"]
streams_count = 6
stream_0/stream = ExtResource("16_fvw42")
stream_1/stream = ExtResource("17_qjm0l")
stream_2/stream = ExtResource("18_xfa6j")
stream_3/stream = ExtResource("19_3e0oi")
stream_4/stream = ExtResource("20_v2r3y")
stream_5/stream = ExtResource("21_0qg0s")
[sub_resource type="Animation" id="Animation_lq20m"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:offset")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(0, 0)]
}
[sub_resource type="Animation" id="Animation_cmff4"]
resource_name = "indicate"
length = 0.8
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:offset")
tracks/0/interp = 2
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.4, 0.8),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [Vector2(0, 0), Vector2(0, -1), Vector2(0, 0)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_76fyq"]
_data = {
&"RESET": SubResource("Animation_lq20m"),
&"indicate": SubResource("Animation_cmff4")
}
[sub_resource type="RectangleShape2D" id="RectangleShape2D_nb533"]
size = Vector2(14, 10)
[node name="Pot" type="CharacterBody2D"]
collision_layer = 128
collision_mask = 960
script = ExtResource("1_hsjxb")
[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."]
replication_config = SubResource("SceneReplicationConfig_hsjxb")
[node name="Sprite2DShadow" type="Sprite2D" parent="."]
z_index = -1
position = Vector2(0, 3)
texture = SubResource("GradientTexture2D_87nuj")
[node name="GPUParticles2D" type="GPUParticles2D" parent="."]
material = SubResource("CanvasItemMaterial_lq20m")
emitting = false
amount = 16
texture = ExtResource("2_cmff4")
interp_to_end = 0.026
preprocess = 0.16
explosiveness = 0.5
randomness = 0.48
use_fixed_seed = true
seed = 1565624367
process_material = SubResource("ParticleProcessMaterial_iw3no")
[node name="TimerSmokeParticles" type="Timer" parent="GPUParticles2D"]
wait_time = 0.12
[node name="Sprite2D" type="Sprite2D" parent="."]
position = Vector2(0, -4)
texture = ExtResource("1_rxnv2")
hframes = 19
vframes = 19
frame = 14
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
visible = false
position = Vector2(0, -1)
shape = SubResource("RectangleShape2D_hsjxb")
[node name="Area2DPickup" type="Area2D" parent="."]
visible = false
collision_layer = 1024
collision_mask = 512
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DPickup"]
position = Vector2(0, -1)
shape = SubResource("RectangleShape2D_87nuj")
debug_color = Color(0.688142, 0.7, 0.0440007, 0.42)
[node name="SfxShatter" type="AudioStreamPlayer2D" parent="."]
stream = SubResource("AudioStreamRandomizer_ui3li")
attenuation = 9.84915
panning_strength = 1.46
bus = &"Sfx"
[node name="SfxDrag" type="AudioStreamPlayer2D" parent="."]
stream = SubResource("AudioStreamRandomizer_wv4em")
volume_db = -10.142
bus = &"Sfx"
[node name="SfxDrag2" type="AudioStreamPlayer2D" parent="."]
stream = SubResource("AudioStreamRandomizer_fvw42")
volume_db = -9.703
pitch_scale = 0.77
max_distance = 749.0
attenuation = 10.1965
panning_strength = 1.5
bus = &"Sfx"
[node name="SfxLand" type="AudioStreamPlayer2D" parent="."]
stream = SubResource("AudioStreamRandomizer_icnv3")
attenuation = 6.9644
panning_strength = 1.25
bus = &"Sfx"
[node name="SfxThrow" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("21_hd4fl")
volume_db = -4.708
pitch_scale = 0.54
bus = &"Sfx"
[node name="SfxDrop" type="AudioStreamPlayer2D" parent="."]
bus = &"Sfx"
[node name="SfxPickup" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("11_lq20m")
[node name="Indicator" type="Sprite2D" parent="."]
position = Vector2(0, -11)
texture = ExtResource("10_nb533")
[node name="AnimationPlayer" type="AnimationPlayer" parent="Indicator"]
libraries = {
&"": SubResource("AnimationLibrary_76fyq")
}
autoplay = "indicate"
[node name="Area2DCollision" type="Area2D" parent="."]
visible = false
collision_layer = 1024
collision_mask = 704
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DCollision"]
position = Vector2(0, -1)
shape = SubResource("RectangleShape2D_nb533")
debug_color = Color(0.7, 0.132592, 0.232379, 0.42)
[connection signal="timeout" from="GPUParticles2D/TimerSmokeParticles" to="." method="_on_timer_smoke_particles_timeout"]
[connection signal="body_entered" from="Area2DPickup" to="." method="_on_area_2d_pickup_body_entered"]
[connection signal="body_exited" from="Area2DPickup" to="." method="_on_area_2d_pickup_body_exited"]
[connection signal="body_entered" from="Area2DCollision" to="." method="_on_area_2d_collision_body_entered"]
[connection signal="body_exited" from="Area2DCollision" to="." method="_on_area_2d_collision_body_exited"]

View File

@@ -0,0 +1,152 @@
[gd_scene load_steps=21 format=3 uid="uid://bdlg5orah64m5"]
[ext_resource type="Script" uid="uid://bj0ueurl3vovc" path="res://scripts/entities/world/pot.gd" id="1_hsjxb"]
[ext_resource type="Texture2D" uid="uid://bu4dq78f8lgj5" path="res://assets/gfx/sheet_18.png" id="1_rxnv2"]
[ext_resource type="AudioStream" uid="uid://fl0rfi4in3n4" path="res://assets/audio/sfx/environment/pot/Drunk lad destroys plant pot.mp3" id="3_vktry"]
[ext_resource type="AudioStream" uid="uid://dejjc0uqthi1b" path="res://assets/audio/sfx/environment/pot/pot_destroy_sound1.mp3" id="4_nb533"]
[ext_resource type="AudioStream" uid="uid://iuxunaogc8xr" path="res://assets/audio/sfx/environment/pot/pot_destroy_sound2.mp3" id="5_cmff4"]
[ext_resource type="AudioStream" uid="uid://bfqusej0pbxem" path="res://assets/audio/sfx/environment/pot/pot_destroy_sound3.mp3" id="6_lq20m"]
[ext_resource type="AudioStream" uid="uid://dq461vpiih3lc" path="res://assets/audio/sfx/environment/pot/pot_destroy_sound4.mp3" id="7_76fyq"]
[ext_resource type="AudioStream" uid="uid://cg1ndvx4t7xtd" path="res://assets/audio/sfx/environment/pot/pot_destroy_sound5.mp3" id="8_m11t2"]
[ext_resource type="AudioStream" uid="uid://bt5npaenq15h2" path="res://assets/audio/sfx/environment/pot/smaller_pot_crash.mp3" id="9_sb38x"]
[ext_resource type="Texture2D" uid="uid://b1twy68vd7f20" path="res://assets/gfx/pickups/indicator.png" id="10_nb533"]
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_hsjxb"]
properties/0/path = NodePath(".:position")
properties/0/spawn = true
properties/0/replication_mode = 2
[sub_resource type="Gradient" id="Gradient_nb533"]
offsets = PackedFloat32Array(0.847255, 0.861575)
colors = PackedColorArray(0, 0, 0, 0.764706, 0, 0, 0, 0)
[sub_resource type="GradientTexture2D" id="GradientTexture2D_87nuj"]
gradient = SubResource("Gradient_nb533")
width = 16
height = 6
fill = 1
fill_from = Vector2(0.504274, 0.478632)
fill_to = Vector2(0.897436, 0.0769231)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_hsjxb"]
size = Vector2(12, 8)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_87nuj"]
size = Vector2(18, 15)
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_ui3li"]
streams_count = 7
stream_0/stream = ExtResource("3_vktry")
stream_1/stream = ExtResource("4_nb533")
stream_2/stream = ExtResource("5_cmff4")
stream_3/stream = ExtResource("6_lq20m")
stream_4/stream = ExtResource("7_76fyq")
stream_5/stream = ExtResource("8_m11t2")
stream_6/stream = ExtResource("9_sb38x")
[sub_resource type="Animation" id="Animation_cmff4"]
resource_name = "indicate"
length = 0.8
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:offset")
tracks/0/interp = 2
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.4, 0.8),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [Vector2(0, 0), Vector2(0, -1), Vector2(0, 0)]
}
[sub_resource type="Animation" id="Animation_lq20m"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:offset")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(0, 0)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_76fyq"]
_data = {
&"RESET": SubResource("Animation_lq20m"),
&"indicate": SubResource("Animation_cmff4")
}
[sub_resource type="RectangleShape2D" id="RectangleShape2D_nb533"]
size = Vector2(14, 9)
[node name="Pot" type="CharacterBody2D"]
collision_layer = 128
collision_mask = 64
script = ExtResource("1_hsjxb")
[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."]
replication_config = SubResource("SceneReplicationConfig_hsjxb")
[node name="Sprite2DShadow" type="Sprite2D" parent="."]
position = Vector2(0, 3)
texture = SubResource("GradientTexture2D_87nuj")
[node name="Sprite2D" type="Sprite2D" parent="."]
position = Vector2(0, -4)
texture = ExtResource("1_rxnv2")
hframes = 19
vframes = 19
frame = 14
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(0, -1)
shape = SubResource("RectangleShape2D_hsjxb")
[node name="Area2DPickup" type="Area2D" parent="."]
collision_layer = 1024
collision_mask = 512
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DPickup"]
position = Vector2(0, -1)
shape = SubResource("RectangleShape2D_87nuj")
debug_color = Color(0.688142, 0.7, 0.0440007, 0.42)
[node name="SfxShatter" type="AudioStreamPlayer2D" parent="."]
stream = SubResource("AudioStreamRandomizer_ui3li")
attenuation = 9.84915
panning_strength = 1.46
bus = &"Sfx"
[node name="SfxThrow" type="AudioStreamPlayer2D" parent="."]
[node name="SfxDrop" type="AudioStreamPlayer2D" parent="."]
[node name="Indicator" type="Sprite2D" parent="."]
position = Vector2(0, -11)
texture = ExtResource("10_nb533")
[node name="AnimationPlayer" type="AnimationPlayer" parent="Indicator"]
libraries = {
&"": SubResource("AnimationLibrary_76fyq")
}
autoplay = "indicate"
[node name="Area2DCollision" type="Area2D" parent="."]
collision_layer = 1024
collision_mask = 704
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DCollision"]
position = Vector2(0, -1)
shape = SubResource("RectangleShape2D_nb533")
debug_color = Color(0.7, 0.132592, 0.232379, 0.42)
[connection signal="body_entered" from="Area2DPickup" to="." method="_on_area_2d_pickup_body_entered"]
[connection signal="body_exited" from="Area2DPickup" to="." method="_on_area_2d_pickup_body_exited"]
[connection signal="body_entered" from="Area2DCollision" to="." method="_on_area_2d_collision_body_entered"]
[connection signal="body_exited" from="Area2DCollision" to="." method="_on_area_2d_collision_body_exited"]

View File

@@ -0,0 +1,175 @@
[gd_scene load_steps=19 format=3 uid="uid://bcxk63irehw1d"]
[ext_resource type="Texture2D" uid="uid://bbvdtm5iqv7a" path="res://assets/gfx/props/wall_torch.png" id="1_wyl82"]
[ext_resource type="Shader" uid="uid://cvksy3guq65ie" path="res://assets/shaders/fire.gdshader" id="2_hab2u"]
[ext_resource type="AudioStream" uid="uid://y4632vubgvmk" path="res://assets/audio/sfx/environment/torch/torch_burn_02.wav.mp3" id="3_hab2u"]
[sub_resource type="Gradient" id="Gradient_wyl82"]
colors = PackedColorArray(0, 0, 0, 1, 0, 0, 0, 1)
[sub_resource type="GradientTexture2D" id="GradientTexture2D_hab2u"]
gradient = SubResource("Gradient_wyl82")
[sub_resource type="Gradient" id="Gradient_7mycd"]
[sub_resource type="GradientTexture1D" id="GradientTexture1D_272bh"]
gradient = SubResource("Gradient_7mycd")
[sub_resource type="Gradient" id="Gradient_5vw27"]
[sub_resource type="FastNoiseLite" id="FastNoiseLite_kek77"]
noise_type = 0
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_4c57u"]
color_ramp = SubResource("Gradient_5vw27")
noise = SubResource("FastNoiseLite_kek77")
[sub_resource type="ShaderMaterial" id="ShaderMaterial_kek77"]
shader = ExtResource("2_hab2u")
shader_parameter/noise_tex = SubResource("NoiseTexture2D_4c57u")
shader_parameter/gradient_tex = SubResource("GradientTexture1D_272bh")
shader_parameter/brighter_color = Color(1, 0.8, 0, 1)
shader_parameter/middle_color = Color(1, 0.474005, 0.175976, 1)
shader_parameter/darker_color = Color(0.621094, 0.123033, 0.0859316, 1)
shader_parameter/spread = 0.526
shader_parameter/amount = 32
[sub_resource type="Gradient" id="Gradient_272bh"]
offsets = PackedFloat32Array(0.603819, 0.673031)
colors = PackedColorArray(1, 0.843137, 0.603922, 0.337255, 1, 1, 1, 0)
[sub_resource type="GradientTexture2D" id="GradientTexture2D_5vw27"]
gradient = SubResource("Gradient_272bh")
width = 22
height = 22
fill = 1
fill_from = Vector2(0.512821, 0.461538)
[sub_resource type="Animation" id="Animation_272bh"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [0]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("FireGlow:scale")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(1, 1)]
}
[sub_resource type="Animation" id="Animation_7mycd"]
resource_name = "torch"
length = 1.6
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.1, 1.2, 1.3, 1.4, 1.5),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
"update": 1,
"values": [0, 1, 2, 1, 0, 1, 2, 1, 0, 1, 2, 1, 0, 1, 2, 1]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("FireGlow:scale")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.199912, 0.401399, 0.601311, 0.794927, 0.994839, 1.19633, 1.39624),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1),
"update": 1,
"values": [Vector2(1, 1), Vector2(1.1, 1.1), Vector2(1, 1), Vector2(1.1, 1.1), Vector2(1, 1), Vector2(1.1, 1.1), Vector2(1, 1), Vector2(1.1, 1.1)]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("TorchLight:scale")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0, 0.3, 0.4, 0.7, 0.8, 1.1, 1.2, 1.5),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1),
"update": 1,
"values": [Vector2(1, 1), Vector2(1.05, 1.05), Vector2(1.1, 1.1), Vector2(1.05, 1.05), Vector2(1, 1), Vector2(1.05, 1.05), Vector2(1.1, 1.1), Vector2(1.05, 1.05)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_5vw27"]
_data = {
&"RESET": SubResource("Animation_272bh"),
&"torch": SubResource("Animation_7mycd")
}
[sub_resource type="Gradient" id="Gradient_lquwl"]
offsets = PackedFloat32Array(0.742243, 0.74463)
colors = PackedColorArray(1, 1, 1, 1, 0, 0, 0, 0)
[sub_resource type="GradientTexture2D" id="GradientTexture2D_lt5sp"]
gradient = SubResource("Gradient_lquwl")
fill = 1
fill_from = Vector2(0.508547, 0.487179)
fill_to = Vector2(0.974359, 0.0470085)
[node name="TorchWall" type="Sprite2D"]
z_index = 2
y_sort_enabled = true
texture = ExtResource("1_wyl82")
hframes = 3
[node name="Sprite2D" type="Sprite2D" parent="."]
visible = false
texture = SubResource("GradientTexture2D_hab2u")
[node name="ColorRect" type="ColorRect" parent="."]
visible = false
material = SubResource("ShaderMaterial_kek77")
offset_left = -8.0
offset_top = -25.0
offset_right = 7.0
offset_bottom = -3.0
[node name="FireGlow" type="Sprite2D" parent="."]
position = Vector2(0, -2)
texture = SubResource("GradientTexture2D_5vw27")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
&"": SubResource("AnimationLibrary_5vw27")
}
autoplay = "torch"
[node name="TorchLight" type="PointLight2D" parent="."]
z_index = 10
position = Vector2(0, -1)
blend_mode = 2
range_layer_max = 2
texture = SubResource("GradientTexture2D_lt5sp")
[node name="SfxTorch" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("3_hab2u")
volume_db = 2.996
autoplay = true
max_distance = 509.0
attenuation = 16.5642
max_polyphony = 2
panning_strength = 1.89
bus = &"Sfx"

483
src/scripts/level.tscn Normal file
View File

@@ -0,0 +1,483 @@
[gd_scene load_steps=43 format=4 uid="uid://c5da75e565n7d"]
[ext_resource type="Texture2D" uid="uid://bu4dq78f8lgj5" path="res://assets/gfx/sheet_18.png" id="1_6ksph"]
[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_lyu2k"]
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_m4brx"]
polygon = PackedVector2Array(6.75, 6.75, 8, 6.625, 8, 8, 6.75, 8)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_5upmd"]
polygon = PackedVector2Array(7, -8, 8, -8, 8, 8, 7, 8)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_emxo0"]
polygon = PackedVector2Array(-8, -8, -4, -8, -4, -7, -8, -7)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_ncpt4"]
polygon = PackedVector2Array(7, -8, 7, -4, 8, -4, 8, -8)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_ugoxn"]
polygon = PackedVector2Array(8, 4, 8, 8, 7, 8, 7, 4)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_s5tcm"]
polygon = PackedVector2Array(6.75, -8, 8, -8, 8, -6.5, 6.875, -6.5)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_b6xc5"]
polygon = PackedVector2Array(-8, -8, 8, -8, 8, -7, -8, -7)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_m8hwt"]
polygon = PackedVector2Array(-8, -8, -7, -8, -7, 8, -8, 8)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_tglxv"]
polygon = PackedVector2Array(-8, -8, -7, -8, -7, 8, -8, 8)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_fq3jy"]
polygon = PackedVector2Array(-8, -8, -7, -8, -7, 8, -8, 8)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_ji7g4"]
polygon = PackedVector2Array(-8, 7, 8, 7, 8, 8, -8, 8)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_fjv83"]
polygon = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_3w1co"]
polygon = PackedVector2Array(4, -8, 8, -8, 8, -7, 4, -7)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_4533o"]
polygon = PackedVector2Array(-8, -8, -8, -4, -7, -4, -7, -8)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_anp3l"]
polygon = PackedVector2Array(-8, 4, -7, 4, -7, 8, -8, 8)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_f8ncv"]
polygon = PackedVector2Array(-8, -8, 8, -8, 8, -7, -8, -7)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_n640s"]
polygon = PackedVector2Array(-8, -8, 8, -8, 8, -7, -8, -7)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_4c57u"]
polygon = PackedVector2Array(7, -8, 8, -8, 8, 8, 7, 8)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_efxa6"]
polygon = PackedVector2Array(7, -8, 8, -8, 8, 8, 7, 8)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_dg77c"]
polygon = PackedVector2Array(7, -8, 8, -8, 8, 8, 7, 8)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_mgwa5"]
polygon = PackedVector2Array(-8, 7, -7, 7, -7, 8, -8, 8)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_yf73x"]
polygon = PackedVector2Array(-8, -8, -7, -8, -7, 8, -8, 8)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_lous1"]
polygon = PackedVector2Array(-8, 7, -4, 7, -4, 8, -8, 8)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_pyflw"]
polygon = PackedVector2Array(-8, -8, -7, -8, -7, -7, -8, -7)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_f1hq0"]
polygon = PackedVector2Array(-8, -8, 8, -8, 8, -7, -8, -7)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_qyrwp"]
polygon = PackedVector2Array(-8, 7, 8, 7, 8, 8, -8, 8)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_3cpci"]
polygon = PackedVector2Array(-8, -8, 8, -8, 8, -7, -7, -7, -7, 8, -8, 8, -8, -8)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_ron74"]
polygon = PackedVector2Array(-8, -8, -8, 8, 8, 8, 8, 7, -7, 7, -7, -8)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_wiqva"]
polygon = PackedVector2Array(4, 7, 4, 8, 8, 8, 8, 7)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_bc8dd"]
polygon = PackedVector2Array(7, -8, 8, -8, 8, 8, 7, 8)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_cqshl"]
polygon = PackedVector2Array(-8, 7, 8, 7, 8, 8, -8, 8)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_n3ur2"]
polygon = PackedVector2Array(-8, -8, 8, -8, 8, 8, 7, 8, 7, -7, -8, -7)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_jlc7t"]
polygon = PackedVector2Array(8, -8, 7, -8, 7, 7, -8, 7, -8, 8, 8, 8)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_13ear"]
polygon = PackedVector2Array(-8, -8, -7, -8, -7, 8, -8, 8)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_jmwb3"]
polygon = PackedVector2Array(-8, 7, 8, 7, 8, 8, -8, 8)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_m7sxa"]
polygon = PackedVector2Array(-8, -8, 8, -8, 8, -6.625, -8, -6.875)
[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_f6bwm"]
polygon = PackedVector2Array(-8, 7, 8, 7, 8, 8, -8, 8)
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_5ksd3"]
texture = ExtResource("1_6ksph")
0:0/0 = 0
0:0/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_m4brx")
0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-6, -6, 8, -6, 8, 8, -6, 8)
1:0/0 = 0
1:0/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_ji7g4")
1:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -6, 8, -6, 8, 8, -8, 8)
2:0/0 = 0
2:0/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_mgwa5")
2:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -6, 6, -6, 6, 8, -8, 8)
3:0/0 = 0
3:0/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_3cpci")
3:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 6, 6, 6, 6, 8, -8, 8)
5:0/0 = 0
6:0/0 = 0
7:0/0 = 0
8:0/0 = 0
9:0/0 = 0
10:0/0 = 0
11:0/0 = 0
12:0/0 = 0
13:0/0 = 0
14:0/0 = 0
15:0/0 = 0
16:0/0 = 0
17:0/0 = 0
18:0/0 = 0
0:1/0 = 0
0:1/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_5upmd")
0:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-6, -8, 8, -8, 8, 8, -6, 8)
1:1/0 = 0
1:1/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_fjv83")
2:1/0 = 0
2:1/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_yf73x")
2:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 6, -8, 6, 8, -8, 8)
3:1/0 = 0
3:1/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_ron74")
3:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 6, -8, 6, -6, 8, -6, 8, 8, -8, 8)
4:1/0 = 0
4:1/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_jlc7t")
4:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-6, -8, 8, -8, 8, 8, -8, 8, -8, -6, -6, -6)
5:1/0 = 0
5:1/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_m7sxa")
5:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 6, -8, 6)
6:1/0 = 0
7:1/0 = 0
8:1/0 = 0
9:1/0 = 0
10:1/0 = 0
11:1/0 = 0
12:1/0 = 0
13:1/0 = 0
14:1/0 = 0
15:1/0 = 0
16:1/0 = 0
17:1/0 = 0
18:1/0 = 0
0:2/0 = 0
0:2/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_s5tcm")
0:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-6, -8, 8, -8, 8, 6, -6, 6)
1:2/0 = 0
1:2/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_f8ncv")
1:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 6, -8, 6)
2:2/0 = 0
2:2/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_pyflw")
2:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 6, -8, 6, 6, -8, 6)
3:2/0 = 0
4:2/0 = 0
4:2/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_13ear")
4:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 6, -8, 6, 8, -8, 8)
5:2/0 = 0
5:2/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_f6bwm")
5:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -6, 8, -6, 8, 8, -8, 8)
6:2/0 = 0
7:2/0 = 0
8:2/0 = 0
9:2/0 = 0
10:2/0 = 0
11:2/0 = 0
12:2/0 = 0
13:2/0 = 0
14:2/0 = 0
15:2/0 = 0
16:2/0 = 0
17:2/0 = 0
0:3/0 = 0
0:3/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_b6xc5")
0:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 6, -8, 6)
1:3/0 = 0
1:3/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_n640s")
1:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 6, -8, 6)
2:3/0 = 0
2:3/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_f1hq0")
2:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 6, -8, 6)
3:3/0 = 0
3:3/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_bc8dd")
3:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-6, -8, 8, -8, 8, 8, -6, 8)
4:3/0 = 0
5:3/0 = 0
6:3/0 = 0
7:3/0 = 0
8:3/0 = 0
9:3/0 = 0
10:3/0 = 0
11:3/0 = 0
12:3/0 = 0
13:3/0 = 0
14:3/0 = 0
15:3/0 = 0
16:3/0 = 0
0:4/0 = 0
0:4/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_m8hwt")
0:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 6, -8, 6, 8, -8, 8)
1:4/0 = 0
1:4/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_4c57u")
1:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-6, -8, 8, -8, 8, 8, -6, 8)
2:4/0 = 0
2:4/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_qyrwp")
2:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -6, 8, -6, 8, 8, -8, 8)
3:4/0 = 0
3:4/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_cqshl")
3:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -6, 8, -6, 8, 8, -8, 8)
4:4/0 = 0
4:4/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_jmwb3")
4:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -6, 8, -6, 8, 8, -8, 8)
5:4/0 = 0
6:4/0 = 0
7:4/0 = 0
8:4/0 = 0
9:4/0 = 0
10:4/0 = 0
11:4/0 = 0
12:4/0 = 0
13:4/0 = 0
14:4/0 = 0
15:4/0 = 0
16:4/0 = 0
0:5/0 = 0
0:5/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_tglxv")
0:5/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 6, -8, 6, 8, -8, 8)
1:5/0 = 0
1:5/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_efxa6")
1:5/0/physics_layer_0/polygon_0/points = PackedVector2Array(-6, -8, 8, -8, 8, 8, -6, 8)
2:5/0 = 0
3:5/0 = 0
4:5/0 = 0
5:5/0 = 0
6:5/0 = 0
7:5/0 = 0
8:5/0 = 0
9:5/0 = 0
10:5/0 = 0
11:5/0 = 0
12:5/0 = 0
13:5/0 = 0
14:5/0 = 0
17:5/0 = 0
18:5/0 = 0
0:6/0 = 0
0:6/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_fq3jy")
0:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 6, -8, 6, 8, -8, 8)
1:6/0 = 0
1:6/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_dg77c")
1:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-6, -8, 8, -8, 8, 8, -6, 8)
2:6/0 = 0
3:6/0 = 0
4:6/0 = 0
5:6/0 = 0
6:6/0 = 0
7:6/0 = 0
8:6/0 = 0
9:6/0 = 0
10:6/0 = 0
11:6/0 = 0
12:6/0 = 0
13:6/0 = 0
14:6/0 = 0
17:6/0 = 0
18:6/0 = 0
0:7/0 = 0
1:7/0 = 0
2:7/0 = 0
3:7/0 = 0
4:7/0 = 0
5:7/0 = 0
6:7/0 = 0
7:7/0 = 0
8:7/0 = 0
9:7/0 = 0
10:7/0 = 0
11:7/0 = 0
12:7/0 = 0
13:7/0 = 0
14:7/0 = 0
15:7/0 = 0
16:7/0 = 0
17:7/0 = 0
18:7/0 = 0
0:8/0 = 0
1:8/0 = 0
2:8/0 = 0
3:8/0 = 0
4:8/0 = 0
5:8/0 = 0
6:8/0 = 0
7:8/0 = 0
8:8/0 = 0
9:8/0 = 0
10:8/0 = 0
11:8/0 = 0
12:8/0 = 0
13:8/0 = 0
14:8/0 = 0
15:8/0 = 0
16:8/0 = 0
17:8/0 = 0
18:8/0 = 0
0:9/0 = 0
1:9/0 = 0
2:9/0 = 0
3:9/0 = 0
4:9/0 = 0
5:9/0 = 0
6:9/0 = 0
7:9/0 = 0
8:9/0 = 0
9:9/0 = 0
10:9/0 = 0
11:9/0 = 0
12:9/0 = 0
13:9/0 = 0
14:9/0 = 0
15:9/0 = 0
16:9/0 = 0
17:9/0 = 0
18:9/0 = 0
0:10/0 = 0
1:10/0 = 0
2:10/0 = 0
3:10/0 = 0
4:10/0 = 0
5:10/0 = 0
6:10/0 = 0
7:10/0 = 0
8:10/0 = 0
9:10/0 = 0
10:10/0 = 0
11:10/0 = 0
12:10/0 = 0
13:10/0 = 0
14:10/0 = 0
15:10/0 = 0
16:10/0 = 0
17:10/0 = 0
18:10/0 = 0
0:11/0 = 0
1:11/0 = 0
2:11/0 = 0
3:11/0 = 0
4:11/0 = 0
5:11/0 = 0
6:11/0 = 0
7:11/0 = 0
8:11/0 = 0
9:11/0 = 0
10:11/0 = 0
11:11/0 = 0
12:11/0 = 0
13:11/0 = 0
14:11/0 = 0
15:11/0 = 0
16:11/0 = 0
17:11/0 = 0
18:11/0 = 0
0:12/0 = 0
1:12/0 = 0
2:12/0 = 0
3:12/0 = 0
4:12/0 = 0
5:12/0 = 0
6:12/0 = 0
7:12/0 = 0
8:12/0 = 0
9:12/0 = 0
10:12/0 = 0
11:12/0 = 0
12:12/0 = 0
13:12/0 = 0
14:12/0 = 0
15:12/0 = 0
16:12/0 = 0
17:12/0 = 0
18:12/0 = 0
0:13/0 = 0
0:13/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_emxo0")
0:13/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, -4, -8, -4, 6, -8, 6)
1:13/0 = 0
1:13/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_3w1co")
1:13/0/physics_layer_0/polygon_0/points = PackedVector2Array(4, -8, 8, -8, 8, 6, 4, 6)
2:13/0 = 0
2:13/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_lous1")
2:13/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -6, -4, -6, -4, 8, -8, 8)
3:13/0 = 0
3:13/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_wiqva")
3:13/0/physics_layer_0/polygon_0/points = PackedVector2Array(8, -6, 4, -6, 4, 8, 8, 8)
0:14/0 = 0
0:14/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_ncpt4")
0:14/0/physics_layer_0/polygon_0/points = PackedVector2Array(-6, -8, -6, -4, 8, -4, 8, -8)
1:14/0 = 0
1:14/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_4533o")
1:14/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 6, -8, 6, -4, -8, -4)
0:15/0 = 0
0:15/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_ugoxn")
0:15/0/physics_layer_0/polygon_0/points = PackedVector2Array(-6, 4, -6, 8, 8, 8, 8, 4)
1:15/0 = 0
1:15/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_anp3l")
1:15/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, 4, 6, 4, 6, 8, -8, 8)
4:0/0 = 0
4:0/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_n3ur2")
4:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -6, 8, -6, 6, -8, 6)
15:5/0 = 0
16:5/0 = 0
16:6/0 = 0
15:6/0 = 0
18:4/0 = 0
17:4/0 = 0
17:3/0 = 0
18:3/0 = 0
18:2/0 = 0
[sub_resource type="TileSet" id="TileSet_ulq2a"]
occlusion_layer_0/light_mask = 1
physics_layer_0/collision_layer = 64
physics_layer_0/collision_mask = 64
physics_layer_0/physics_material = SubResource("PhysicsMaterial_lyu2k")
sources/0 = SubResource("TileSetAtlasSource_5ksd3")
[sub_resource type="RectangleShape2D" id="RectangleShape2D_sfuo5"]
size = Vector2(3, 2)
[node name="Main" type="Node2D"]
y_sort_enabled = true
[node name="TileMapBottom" type="TileMapLayer" parent="."]
tile_map_data = PackedByteArray("AAABAP//AAAGAAAAAAACAP//AAAGAAAAAAACAP7/AAAGAAAAAAABAP7/AAAGAAAAAAAAAP7/AAAGAAAAAAD///7/AAAGAAAAAAD+//7/AAAGAAAAAAD9//7/AAAGAAAAAAAEAP7/AAAGAAAAAAADAP7/AAAGAAAAAAADAP3/AAAGAAAAAAACAP3/AAAGAAAAAAABAP3/AAAGAAAAAAAAAP3/AAAGAAAAAAD///3/AAAGAAAAAAD+//3/AAAGAAAAAAD9////AAAGAAAAAAAEAP3/AAAGAAAAAAAAAP//AAAGAAAAAAD/////AAAGAAAAAAAEAP//AAAGAAAAAAADAP//AAAGAAAAAAD9//3/AAAGAAAAAAD+////AAAGAAAAAAD+/wAAAAAGAAAAAAD//wAAAAAGAAAAAAAAAAAAAAAGAAAAAAABAAAAAAAGAAAAAAACAAAAAAAGAAAAAAADAAAAAAAGAAAAAAADAAEAAAAGAAAAAAACAAEAAAAGAAAAAAABAAEAAAAGAAAAAAAAAAEAAAAGAAAAAAD//wEAAAAGAAAAAAD+/wEAAAAGAAAAAAA=")
tile_set = SubResource("TileSet_ulq2a")
metadata/_edit_lock_ = true
[node name="TileMapFloor" type="TileMapLayer" parent="."]
tile_map_data = PackedByteArray("AAD/////AAAHAAAAAAAAAP//AAAHAAAAAAD9/wAAAAACAAEAAAD9////AAACAAEAAAD9//7/AAACAAEAAAD9//3/AAADAAAAAAD+//3/AAABAAIAAAD///3/AAABAAIAAAAAAP3/AAABAAIAAAABAP3/AAABAAIAAAACAP3/AAABAAIAAAADAP3/AAABAAIAAAAEAP3/AAAEAAAAAAAEAP7/AAAAAAEAAAAEAP//AAAAAAEAAAA=")
tile_set = SubResource("TileSet_ulq2a")
metadata/_edit_lock_ = true
[node name="TileMapAbove" type="TileMapLayer" parent="."]
z_index = 14
tile_set = SubResource("TileSet_ulq2a")
[node name="CorridorCollisions" type="StaticBody2D" parent="."]
collision_layer = 64
collision_mask = 0
metadata/_edit_lock_ = true
[node name="ColToPleaseGodot" type="CollisionShape2D" parent="CorridorCollisions"]
position = Vector2(-111.5, -39)
shape = SubResource("RectangleShape2D_sfuo5")

View File

@@ -0,0 +1,11 @@
extends Button
var current_character_stats = CharacterStats.new()
func set_data(iData) -> void:
current_character_stats.load(iData)
$VBoxContainer/SelectableChar/Player.initStats(current_character_stats)
$VBoxContainer/SelectableChar/Player._stats_changed(current_character_stats)
$VBoxContainer/LabelLevel.text = "Level " + str(current_character_stats.level)
pass

View File

@@ -0,0 +1 @@
uid://fwu8vcxc4qii

View File

@@ -0,0 +1,29 @@
[gd_scene load_steps=3 format=3 uid="uid://dgniqbtakal50"]
[ext_resource type="Script" uid="uid://fwu8vcxc4qii" path="res://scripts/ui/button_select_char.gd" id="1_87l7n"]
[ext_resource type="PackedScene" uid="uid://dgtfy455abe1t" path="res://scripts/entities/player/player.tscn" id="2_0bb2u"]
[node name="ButtonSelectChar" type="Button"]
custom_minimum_size = Vector2(64, 52)
script = ExtResource("1_87l7n")
[node name="VBoxContainer" type="VBoxContainer" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="SelectableChar" type="Node2D" parent="VBoxContainer"]
position = Vector2(30.24, 28.035)
[node name="Player" parent="VBoxContainer/SelectableChar" instance=ExtResource("2_0bb2u")]
isDemoCharacter = true
[node name="LabelLevel" type="Label" parent="VBoxContainer"]
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 10
theme_override_font_sizes/font_size = 6
text = "Level 1"

View File

@@ -0,0 +1,267 @@
extends Control
var buttonSelectChar = preload("res://scripts/ui/button_select_char.tscn")
@onready var demoCharacter = $ControlSelectCharacter/VBoxContainer/Control/SelectableChar/Player
signal character_choose()
signal back_button()
const MAX_CHARACTERS = 10
var save_path = "saves/"
var characters = []
var current_slot = -1
var current_character_stats = CharacterStats.new()
func _ready() -> void:
RenderingServer.set_default_clear_color(Color(0, 0, 0, 1.0))
var pPanel:PopupPanel = $ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerFacial/PickerButtonColorFacial.get_popup()
pPanel.max_size = Vector2i(80,120)
var cPicker:ColorPicker = $ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerFacial/PickerButtonColorFacial.get_picker()
cPicker.hex_visible = true
cPicker.sliders_visible = true
cPicker.can_add_swatches = false
cPicker.presets_visible = false
cPicker.scale = Vector2(0.24,0.24)
var pPanel2:PopupPanel = $ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerHair/PickerButtonColorHair.get_popup()
pPanel2.max_size = Vector2i(80,120)
var cPicker2:ColorPicker = $ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerHair/PickerButtonColorHair.get_picker()
cPicker2.hex_visible = true
cPicker2.sliders_visible = true
cPicker2.can_add_swatches = false
cPicker2.presets_visible = false
cPicker2.scale = Vector2(0.24,0.24)
$ControlSelectCharacter/VBoxContainer/ButtonPlay.visible = false
$ControlCharacterInfo.visible = true
current_slot = -1
current_character_stats = CharacterStats.new()
$ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainerInputName/LineEdit.text = ""
loadCharDatas()
update_character_display()
if characters.size() > 0:
$ControlCharacterInfo.visible = false
current_character_stats.load(characters[current_slot])
$ControlSelectCharacter/VBoxContainer/ButtonPlay.visible = true
else:
current_slot = -1
$ControlCharacterInfo.visible = true
$ControlSelectCharacter/VBoxContainer/ButtonPlay.visible = false
demoCharacter.initStats(current_character_stats)
call_deferred("nextFrame")
pass
func nextFrame():
demoCharacter._stats_changed(current_character_stats)
pass
func loadCharDatas():
characters = [] # reset
var dir = DirAccess.open("user://")
# Load all saved characters
if dir.dir_exists(save_path) == false:
dir.make_dir(save_path)
var saveFiles = DirAccess.get_files_at("user://" + save_path)
for saveFile in saveFiles:
var char_data = getSaveData(saveFile)
if !char_data.is_empty():
current_slot = 0 # preselect first character.
characters.append(char_data)
pass
func getSaveData(iSaveFile:String) -> Dictionary:
var savePath = "user://" + save_path + iSaveFile
if not FileAccess.file_exists(savePath):
return {}
var file_access = FileAccess.open(savePath, FileAccess.READ)
var json_string = file_access.get_line()
file_access.close()
var json = JSON.new()
var parse_result = json.parse(json_string)
return json.data if parse_result == OK else {}
func update_character_display() -> void:
var children = $ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters/ScrollContainer/VBoxContainer.get_children()
for child in children:
$ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters/ScrollContainer/VBoxContainer.remove_child(child)
var curIndex = 0
for chara in characters:
var charBut = buttonSelectChar.instantiate()
$ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters/ScrollContainer/VBoxContainer.add_child(charBut)
charBut.set_data(chara)
charBut.connect("pressed", _pressCharBut.bind(charBut, curIndex))
curIndex+=1
pass
$ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters/ScrollContainer.queue_redraw()
$ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters/ScrollContainer/VBoxContainer.queue_redraw()
pass
func checkSaves():
pass
func _input(event: InputEvent):
var isMouseButton = event is InputEventMouseButton
var isPressed = event.is_pressed()
if isMouseButton and isPressed and event.button_index == 1:
var evLocal = make_input_local(event)
if !Rect2(Vector2(0,0), size).has_point(evLocal.position):
release_focus()
func _on_line_edit_text_changed(new_text: String) -> void:
demoCharacter.stats.character_name = new_text
demoCharacter.initStats(demoCharacter.stats)
pass # Replace with function body.
func _pressCharBut(iCharBut:Button, iIndex:int) -> void:
$ControlSelectCharacter/VBoxContainer/ButtonPlay.visible = true
$ControlCharacterInfo.visible = false
var polayer = iCharBut.find_child("Player")
current_character_stats = iCharBut.find_child("Player").stats
current_slot = iIndex
demoCharacter.initStats(current_character_stats)
demoCharacter._stats_changed(current_character_stats)
pass
func _on_button_create_pressed() -> void:
if characters.size() >= MAX_CHARACTERS:
print("DELETE a characcter, you jhave too many")
else:
$ControlSelectCharacter/VBoxContainer/ButtonPlay.visible = false
$ControlCharacterInfo.visible = true
current_slot = -1
current_character_stats = CharacterStats.new()
demoCharacter.initStats(current_character_stats)
demoCharacter._stats_changed(current_character_stats)
$ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainerInputName/LineEdit.text = ""
pass
pass # Replace with function body.
func _on_button_delete_pressed() -> void:
if current_slot != -1:
var dir = DirAccess.open("user://")
dir.remove("user://" + save_path + current_character_stats.character_name + ".json")
loadCharDatas()
update_character_display()
current_slot = -1
if characters.size() > 0:
current_slot = 0
$ControlCharacterInfo.visible = false
current_character_stats.load(characters[current_slot])
demoCharacter.initStats(current_character_stats)
demoCharacter._stats_changed(current_character_stats)
$ControlSelectCharacter/VBoxContainer/ButtonPlay.visible = true
else:
$ControlCharacterInfo.visible = true
$ControlSelectCharacter/VBoxContainer/ButtonPlay.visible = false
pass # Replace with function body.
func _on_button_save_pressed() -> void:
$ControlCharacterInfo.visible = false
current_character_stats.character_name = $ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainerInputName/LineEdit.text
var json_data = JSON.stringify(current_character_stats.save())
var fileAccess = FileAccess.open("user://" + save_path + current_character_stats.character_name + ".json", FileAccess.WRITE)
fileAccess.store_line(json_data)
fileAccess.close()
loadCharDatas()
update_character_display()
# figure out index by iterating buttons.
var children = $ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters/ScrollContainer/VBoxContainer.get_children()
var cnt = 0
for child in children:
if child.current_character_stats.character_name == current_character_stats.character_name:
current_slot = cnt
break
cnt+=1
demoCharacter.initStats(current_character_stats)
demoCharacter._stats_changed(current_character_stats)
$ControlSelectCharacter/VBoxContainer/ButtonPlay.visible = true
pass # Replace with function body.
func _on_button_play_pressed() -> void:
MultiplayerManager.character_data = current_character_stats
emit_signal("character_choose")
pass # Replace with function body.
func _on_button_back_pressed() -> void:
emit_signal("back_button")
pass # Replace with function body.
func _on_h_slider_skin_value_changed(value: float) -> void:
#current_character_stats.skin = "res://assets/gfx/Puny-Characters/Layer 0 - Skins/Human" + str(int(floor(value))) + ".png"
current_character_stats.setSkin(int(floor(value)))
#demoCharacter.initStats(current_character_stats)
#demoCharacter._stats_changed(current_character_stats)
pass # Replace with function body.
func _on_h_slider_facial_value_changed(value: float) -> void:
current_character_stats.setFacialHair(
int($ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerFacial/HSliderFacial.value)
)
pass # Replace with function body.
func _on_h_slider_hair_value_changed(value: float) -> void:
current_character_stats.setHair(
int($ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerHair/HSliderHair.value)
)
pass # Replace with function body.
func _on_h_slider_eye_color_value_changed(value: float) -> void:
current_character_stats.setEyes(
int($ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Eyes/HBoxContainerEyeColor/HSliderEyeColor.value)
)
pass # Replace with function body.
func _on_h_slider_eye_lashes_value_changed(value: float) -> void:
current_character_stats.setEyeLashes(
int($ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Eyes/HBoxContainerEyeLashes/HSliderEyeLashes.value)
)
pass # Replace with function body.
func _on_h_slider_ears_value_changed(value: float) -> void:
current_character_stats.setEars(
int($ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Ears/HSliderEars.value)
)
pass # Replace with function body.
func _on_color_picker_button_picker_created() -> void:
pass # Replace with function body.
func _on_picker_button_color_facial_color_changed(color: Color) -> void:
current_character_stats.setFacialHairColor(color)
pass # Replace with function body.
func _on_picker_button_color_hair_color_changed(color: Color) -> void:
current_character_stats.setHairColor(color)
pass # Replace with function body.

View File

@@ -0,0 +1 @@
uid://dwmqhbjbhnrvy

View File

@@ -0,0 +1,419 @@
[gd_scene load_steps=4 format=3 uid="uid://274rykgkxi3m"]
[ext_resource type="Script" uid="uid://dwmqhbjbhnrvy" path="res://scripts/ui/character_select.gd" id="1_4pvb2"]
[ext_resource type="PackedScene" uid="uid://dgtfy455abe1t" path="res://scripts/entities/player/player.tscn" id="4_5axoa"]
[ext_resource type="PackedScene" uid="uid://dgniqbtakal50" path="res://scripts/ui/button_select_char.tscn" id="7_bft24"]
[node name="CharacterSelect" type="Control"]
z_index = 26
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_4pvb2")
[node name="ControlCharacterInfo" type="Control" parent="."]
layout_mode = 1
anchors_preset = 0
offset_right = 40.0
offset_bottom = 40.0
[node name="MarginContainer" type="MarginContainer" parent="ControlCharacterInfo"]
layout_mode = 0
offset_right = 40.0
offset_bottom = 40.0
theme_override_constants/margin_left = 2
theme_override_constants/margin_top = 2
theme_override_constants/margin_right = 2
theme_override_constants/margin_bottom = 2
[node name="ColorRect" type="ColorRect" parent="ControlCharacterInfo/MarginContainer"]
layout_mode = 2
color = Color(0, 0, 0, 0.654902)
[node name="MarginContainer" type="MarginContainer" parent="ControlCharacterInfo/MarginContainer"]
layout_mode = 2
theme_override_constants/margin_left = 2
theme_override_constants/margin_top = 2
theme_override_constants/margin_right = 2
theme_override_constants/margin_bottom = 2
[node name="VBoxContainer" type="VBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
text = "Create new character"
[node name="TabContainer" type="TabContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
current_tab = 2
[node name="Skin" type="HBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer"]
visible = false
layout_mode = 2
metadata/_tab_index = 0
[node name="HSliderSkin" type="HSlider" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Skin"]
layout_mode = 2
size_flags_horizontal = 3
max_value = 6.0
[node name="Eyes" type="VBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer"]
visible = false
layout_mode = 2
theme_override_constants/separation = 4
metadata/_tab_index = 1
[node name="HBoxContainerEyeColor" type="HBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Eyes"]
layout_mode = 2
[node name="LabelEyeColor" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Eyes/HBoxContainerEyeColor"]
layout_mode = 2
text = "Color"
[node name="HSliderEyeColor" type="HSlider" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Eyes/HBoxContainerEyeColor"]
layout_mode = 2
size_flags_horizontal = 3
max_value = 14.0
rounded = true
[node name="HBoxContainerEyeLashes" type="HBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Eyes"]
layout_mode = 2
[node name="LabelEyeLashes" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Eyes/HBoxContainerEyeLashes"]
layout_mode = 2
text = "Lashes"
[node name="HSliderEyeLashes" type="HSlider" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Eyes/HBoxContainerEyeLashes"]
layout_mode = 2
size_flags_horizontal = 3
max_value = 8.0
rounded = true
[node name="Hair" type="VBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer"]
layout_mode = 2
metadata/_tab_index = 2
[node name="HBoxContainerFacial" type="HBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair"]
layout_mode = 2
[node name="LabelFacial" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerFacial"]
layout_mode = 2
text = "Facial Hair"
[node name="HSliderFacial" type="HSlider" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerFacial"]
layout_mode = 2
size_flags_horizontal = 3
max_value = 3.0
rounded = true
[node name="PickerButtonColorFacial" type="ColorPickerButton" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerFacial"]
layout_mode = 2
text = "test"
color = Color(1, 1, 1, 1)
edit_alpha = false
[node name="HBoxContainerHair" type="HBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair"]
layout_mode = 2
[node name="LabelHead" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerHair"]
layout_mode = 2
text = "Head Hair"
[node name="HSliderHair" type="HSlider" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerHair"]
layout_mode = 2
size_flags_horizontal = 3
max_value = 12.0
[node name="PickerButtonColorHair" type="ColorPickerButton" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerHair"]
layout_mode = 2
text = "test"
color = Color(1, 1, 1, 1)
edit_alpha = false
[node name="Ears" type="HBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer"]
visible = false
layout_mode = 2
metadata/_tab_index = 3
[node name="HSliderEars" type="HSlider" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Ears"]
layout_mode = 2
size_flags_horizontal = 3
max_value = 7.0
[node name="HBoxContainer" type="HBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="VBoxContainerBaseStats" type="VBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
[node name="LabelBaseStatsHeader" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerBaseStats"]
modulate = Color(0.7429, 0.755937, 0.761719, 1)
layout_mode = 2
text = "Base Stats:"
[node name="HBoxContainerBaseStats" type="HBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerBaseStats"]
layout_mode = 2
[node name="LabelBaseStats" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerBaseStats/HBoxContainerBaseStats"]
layout_mode = 2
theme_override_constants/line_spacing = 0
text = "STR
DEX
END
INT
WIS
LCK"
[node name="LabelBaseStatsValues" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerBaseStats/HBoxContainerBaseStats"]
layout_mode = 2
theme_override_constants/line_spacing = 0
text = "10
10
10
10
10
10"
horizontal_alignment = 2
[node name="VBoxContainerDerivedStats" type="VBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
[node name="LabelDerivedStatsHeader" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerDerivedStats"]
modulate = Color(0.7429, 0.755937, 0.761719, 1)
layout_mode = 2
text = "Derived Stats:"
[node name="HBoxContainerDerivedStats" type="HBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerDerivedStats"]
layout_mode = 2
[node name="LabelDerivedStats" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerDerivedStats/HBoxContainerDerivedStats"]
layout_mode = 2
theme_override_constants/line_spacing = 0
text = "HP
MP
Damage
Defense
MoveSpd
AtkSpd
Sight
SpellAmp
CritChance"
[node name="LabelDerivedStatsValues" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerDerivedStats/HBoxContainerDerivedStats"]
layout_mode = 2
theme_override_constants/line_spacing = 0
text = "30.0
20.0
2.0
3.0
2.10
1.40
7.0
3.0
12.0%"
horizontal_alignment = 2
[node name="LabelDerivedStatsCalculations" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerDerivedStats/HBoxContainerDerivedStats"]
modulate = Color(0.621094, 0.621094, 0.621094, 1)
layout_mode = 2
theme_override_constants/line_spacing = 0
text = "(END × 3)
(WIS × 2)
(STR × 0.2)
(END × 0.3)
(DEX × 0.01 + 2)
(DEX × 0.04 + 1)
(DEX × 0.2 + 5)
(INT × 0.2)
(LCK × 1.2)"
[node name="HBoxContainerInputName" type="HBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="LabelName" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainerInputName"]
layout_mode = 2
text = "Name"
[node name="LineEdit" type="LineEdit" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainerInputName"]
layout_mode = 2
size_flags_horizontal = 3
placeholder_text = "Enter your character name"
max_length = 32
[node name="ButtonSave" type="Button" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
text = "Save"
[node name="Control" type="Control" parent="."]
layout_mode = 1
anchors_preset = 2
anchor_top = 1.0
anchor_bottom = 1.0
offset_top = -40.0
offset_right = 40.0
grow_vertical = 0
[node name="ButtonBack" type="Button" parent="Control"]
layout_mode = 1
anchors_preset = 2
anchor_top = 1.0
anchor_bottom = 1.0
offset_top = -25.0
offset_right = 48.0
grow_vertical = 0
theme_override_constants/outline_size = 6
text = "Back"
[node name="ControlSelectCharacter" type="Control" parent="."]
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
grow_horizontal = 2
grow_vertical = 2
scale = Vector2(2, 2)
[node name="VBoxContainer" type="VBoxContainer" parent="ControlSelectCharacter"]
layout_mode = 1
anchors_preset = 13
anchor_left = 0.5
anchor_right = 0.5
anchor_bottom = 1.0
offset_left = -23.5
offset_right = 23.5
grow_horizontal = 2
grow_vertical = 2
[node name="Control" type="Control" parent="ControlSelectCharacter/VBoxContainer"]
custom_minimum_size = Vector2(0, 14)
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
[node name="SelectableChar" type="Node2D" parent="ControlSelectCharacter/VBoxContainer/Control"]
[node name="ColorRect" type="ColorRect" parent="ControlSelectCharacter/VBoxContainer/Control/SelectableChar"]
custom_minimum_size = Vector2(31.73, 66.99)
anchors_preset = 13
anchor_left = 0.5
anchor_right = 0.5
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
size_flags_vertical = 3
color = Color(0, 0, 0, 0.431373)
[node name="Player" parent="ControlSelectCharacter/VBoxContainer/Control/SelectableChar" instance=ExtResource("4_5axoa")]
position = Vector2(0, 0.5)
isDemoCharacter = true
[node name="ButtonPlay" type="Button" parent="ControlSelectCharacter/VBoxContainer"]
layout_mode = 2
size_flags_horizontal = 4
text = "PLAY"
[node name="ControlYourCharacters" type="Control" parent="."]
layout_mode = 1
anchors_preset = 11
anchor_left = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 0
grow_vertical = 2
[node name="MarginContainer2" type="MarginContainer" parent="ControlYourCharacters"]
layout_mode = 1
anchors_preset = 11
anchor_left = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -70.0
grow_horizontal = 0
grow_vertical = 2
theme_override_constants/margin_left = 2
theme_override_constants/margin_top = 2
theme_override_constants/margin_right = 2
theme_override_constants/margin_bottom = 2
[node name="ColorRect" type="ColorRect" parent="ControlYourCharacters/MarginContainer2"]
layout_mode = 2
color = Color(0, 0, 0, 0.403922)
[node name="MarginContainer" type="MarginContainer" parent="ControlYourCharacters/MarginContainer2"]
layout_mode = 2
theme_override_constants/margin_left = 2
theme_override_constants/margin_top = 2
theme_override_constants/margin_right = 2
theme_override_constants/margin_bottom = 2
[node name="VBoxContainerCharacters" type="VBoxContainer" parent="ControlYourCharacters/MarginContainer2/MarginContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters"]
layout_mode = 2
size_flags_vertical = 0
text = "Your characters"
[node name="ScrollContainer" type="ScrollContainer" parent="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters"]
layout_mode = 2
size_flags_vertical = 3
size_flags_stretch_ratio = 20.0
horizontal_scroll_mode = 0
vertical_scroll_mode = 2
[node name="VBoxContainer" type="VBoxContainer" parent="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters/ScrollContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="ButtonSelectChar" parent="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters/ScrollContainer/VBoxContainer" instance=ExtResource("7_bft24")]
layout_mode = 2
[node name="ButtonSelectChar2" parent="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters/ScrollContainer/VBoxContainer" instance=ExtResource("7_bft24")]
layout_mode = 2
[node name="ButtonSelectChar3" parent="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters/ScrollContainer/VBoxContainer" instance=ExtResource("7_bft24")]
layout_mode = 2
[node name="HBoxContainer" type="HBoxContainer" parent="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters"]
z_index = 1
layout_mode = 2
size_flags_vertical = 10
[node name="ButtonCreate" type="Button" parent="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_constants/outline_size = 6
text = "Create"
[node name="ButtonDelete" type="Button" parent="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters/HBoxContainer"]
z_index = 2
layout_mode = 2
size_flags_horizontal = 3
theme_override_constants/outline_size = 6
text = "Delete"
[connection signal="value_changed" from="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Skin/HSliderSkin" to="." method="_on_h_slider_skin_value_changed"]
[connection signal="value_changed" from="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Eyes/HBoxContainerEyeColor/HSliderEyeColor" to="." method="_on_h_slider_eye_color_value_changed"]
[connection signal="value_changed" from="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Eyes/HBoxContainerEyeLashes/HSliderEyeLashes" to="." method="_on_h_slider_eye_lashes_value_changed"]
[connection signal="value_changed" from="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerFacial/HSliderFacial" to="." method="_on_h_slider_facial_value_changed"]
[connection signal="color_changed" from="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerFacial/PickerButtonColorFacial" to="." method="_on_picker_button_color_facial_color_changed"]
[connection signal="picker_created" from="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerFacial/PickerButtonColorFacial" to="." method="_on_color_picker_button_picker_created"]
[connection signal="value_changed" from="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerHair/HSliderHair" to="." method="_on_h_slider_hair_value_changed"]
[connection signal="color_changed" from="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerHair/PickerButtonColorHair" to="." method="_on_picker_button_color_hair_color_changed"]
[connection signal="value_changed" from="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Ears/HSliderEars" to="." method="_on_h_slider_ears_value_changed"]
[connection signal="text_changed" from="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainerInputName/LineEdit" to="." method="_on_line_edit_text_changed"]
[connection signal="pressed" from="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/ButtonSave" to="." method="_on_button_save_pressed"]
[connection signal="pressed" from="Control/ButtonBack" to="." method="_on_button_back_pressed"]
[connection signal="pressed" from="ControlSelectCharacter/VBoxContainer/ButtonPlay" to="." method="_on_button_play_pressed"]
[connection signal="pressed" from="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters/HBoxContainer/ButtonCreate" to="." method="_on_button_create_pressed"]
[connection signal="pressed" from="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters/HBoxContainer/ButtonDelete" to="." method="_on_button_delete_pressed"]

View File

@@ -0,0 +1,384 @@
[gd_scene load_steps=12 format=3 uid="uid://274rykgkxi3m"]
[ext_resource type="Script" uid="uid://dwmqhbjbhnrvy" path="res://assets/scripts/ui/character_select.gd" id="1_4pvb2"]
[ext_resource type="Texture2D" uid="uid://br5meakhvr7dh" path="res://assets/gfx/Puny-Characters/base.png" id="1_rdoe0"]
[ext_resource type="Texture2D" uid="uid://76feta3qlvee" path="res://assets/gfx/Puny-Characters/ranger_body.png" id="2_4pvb2"]
[ext_resource type="Texture2D" uid="uid://b1ry74iiqoc1f" path="res://assets/gfx/tomb-01.png" id="2_v33st"]
[ext_resource type="Script" uid="uid://b6rwfu5p4g202" path="res://assets/scripts/ui/title_bg.gd" id="3_bft24"]
[ext_resource type="Texture2D" uid="uid://ioyra0y7ife1" path="res://assets/gfx/Puny-Characters/ranger_hat.png" id="3_rx00f"]
[ext_resource type="PackedScene" uid="uid://dgniqbtakal50" path="res://assets/scripts/ui/button_select_char.tscn" id="7_bft24"]
[sub_resource type="Animation" id="Animation_4pvb2"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Body:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [0]
}
[sub_resource type="Animation" id="Animation_rdoe0"]
resource_name = "idle_down"
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Body:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.5),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [0, 1]
}
[sub_resource type="Animation" id="Animation_rx00f"]
resource_name = "idle_down_right"
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Body:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.5),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [24, 25]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_v33st"]
_data = {
&"RESET": SubResource("Animation_4pvb2"),
&"idle_down": SubResource("Animation_rdoe0"),
&"idle_down_right": SubResource("Animation_rx00f")
}
[node name="CharacterSelect" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_4pvb2")
[node name="background" type="Control" parent="."]
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -20.0
offset_top = -20.0
offset_right = 20.0
offset_bottom = 20.0
grow_horizontal = 2
grow_vertical = 2
[node name="Sprite2D" type="Sprite2D" parent="background"]
modulate = Color(0.407892, 0.411388, 0.421875, 1)
position = Vector2(21, 11)
scale = Vector2(0.09, 0.05)
texture = ExtResource("2_v33st")
script = ExtResource("3_bft24")
[node name="ControlCharacterInfo" type="Control" parent="."]
layout_mode = 1
anchors_preset = 0
offset_right = 40.0
offset_bottom = 40.0
[node name="MarginContainer" type="MarginContainer" parent="ControlCharacterInfo"]
layout_mode = 0
offset_right = 40.0
offset_bottom = 40.0
theme_override_constants/margin_left = 2
theme_override_constants/margin_top = 2
theme_override_constants/margin_right = 2
theme_override_constants/margin_bottom = 2
[node name="ColorRect" type="ColorRect" parent="ControlCharacterInfo/MarginContainer"]
layout_mode = 2
color = Color(0, 0, 0, 0.403922)
[node name="MarginContainer" type="MarginContainer" parent="ControlCharacterInfo/MarginContainer"]
layout_mode = 2
theme_override_constants/margin_left = 2
theme_override_constants/margin_top = 2
theme_override_constants/margin_right = 2
theme_override_constants/margin_bottom = 2
[node name="VBoxContainer" type="VBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
theme_override_font_sizes/font_size = 6
text = "Create new character"
[node name="HBoxContainer" type="HBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="VBoxContainerBaseStats" type="VBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
[node name="LabelBaseStatsHeader" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerBaseStats"]
modulate = Color(0.7429, 0.755937, 0.761719, 1)
layout_mode = 2
theme_override_font_sizes/font_size = 4
text = "Base Stats:"
[node name="HBoxContainerBaseStats" type="HBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerBaseStats"]
layout_mode = 2
[node name="LabelBaseStats" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerBaseStats/HBoxContainerBaseStats"]
layout_mode = 2
theme_override_constants/line_spacing = 0
theme_override_font_sizes/font_size = 4
text = "STR
DEX
END
INT
WIS
LCK"
[node name="LabelBaseStatsValues" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerBaseStats/HBoxContainerBaseStats"]
layout_mode = 2
theme_override_constants/line_spacing = 0
theme_override_font_sizes/font_size = 4
text = "10
10
10
10
10
10"
horizontal_alignment = 2
[node name="VBoxContainerDerivedStats" type="VBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
[node name="LabelDerivedStatsHeader" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerDerivedStats"]
modulate = Color(0.7429, 0.755937, 0.761719, 1)
layout_mode = 2
theme_override_font_sizes/font_size = 4
text = "Derived Stats:"
[node name="HBoxContainerDerivedStats" type="HBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerDerivedStats"]
layout_mode = 2
[node name="LabelDerivedStats" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerDerivedStats/HBoxContainerDerivedStats"]
layout_mode = 2
theme_override_constants/line_spacing = 0
theme_override_font_sizes/font_size = 4
text = "HP
MP
Damage
Defense
MoveSpd
AtkSpd
Sight
SpellAmp
CritChance"
[node name="LabelDerivedStatsValues" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerDerivedStats/HBoxContainerDerivedStats"]
layout_mode = 2
theme_override_constants/line_spacing = 0
theme_override_font_sizes/font_size = 4
text = "30.0
20.0
2.0
3.0
2.10
1.40
7.0
3.0
12.0%"
horizontal_alignment = 2
[node name="LabelDerivedStatsCalculations" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerDerivedStats/HBoxContainerDerivedStats"]
modulate = Color(0.621094, 0.621094, 0.621094, 1)
layout_mode = 2
theme_override_constants/line_spacing = 0
theme_override_font_sizes/font_size = 4
text = "(END × 3)
(WIS × 2)
(STR × 0.2)
(END × 0.3)
(DEX × 0.01 + 2)
(DEX × 0.04 + 1)
(DEX × 0.2 + 5)
(INT × 0.2)
(LCK × 1.2)"
[node name="HBoxContainerInputName" type="HBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="LabelName" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainerInputName"]
layout_mode = 2
theme_override_font_sizes/font_size = 4
text = "Name"
[node name="LineEdit" type="LineEdit" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainerInputName"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_font_sizes/font_size = 4
placeholder_text = "Enter your character name"
max_length = 32
[node name="ButtonCreate" type="Button" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
theme_override_font_sizes/font_size = 6
text = "Create"
[node name="ControlSelectCharacter" type="Control" parent="."]
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
grow_horizontal = 2
grow_vertical = 2
scale = Vector2(2, 2)
[node name="VBoxContainer" type="VBoxContainer" parent="ControlSelectCharacter"]
layout_mode = 1
anchors_preset = 13
anchor_left = 0.5
anchor_right = 0.5
anchor_bottom = 1.0
offset_left = -23.5
offset_right = 23.5
grow_horizontal = 2
grow_vertical = 2
[node name="Control" type="Control" parent="ControlSelectCharacter/VBoxContainer"]
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
[node name="SelectableChar" type="Node2D" parent="ControlSelectCharacter/VBoxContainer/Control"]
[node name="Body" type="Sprite2D" parent="ControlSelectCharacter/VBoxContainer/Control/SelectableChar"]
texture = ExtResource("1_rdoe0")
hframes = 24
vframes = 8
[node name="Armour" type="Sprite2D" parent="ControlSelectCharacter/VBoxContainer/Control/SelectableChar"]
visible = false
texture = ExtResource("2_4pvb2")
hframes = 24
vframes = 8
[node name="Headgear" type="Sprite2D" parent="ControlSelectCharacter/VBoxContainer/Control/SelectableChar"]
visible = false
texture = ExtResource("3_rx00f")
hframes = 24
vframes = 8
[node name="AnimationPlayer" type="AnimationPlayer" parent="ControlSelectCharacter/VBoxContainer/Control/SelectableChar"]
libraries = {
&"": SubResource("AnimationLibrary_v33st")
}
[node name="LabelCharacterName" type="Label" parent="ControlSelectCharacter/VBoxContainer/Control/SelectableChar"]
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -23.5
offset_top = -16.825
offset_right = 23.5
offset_bottom = -7.825
grow_horizontal = 2
grow_vertical = 2
theme_override_font_sizes/font_size = 4
text = "Name"
horizontal_alignment = 1
[node name="ControlYourCharacters" type="Control" parent="."]
layout_mode = 1
anchors_preset = 11
anchor_left = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 0
grow_vertical = 2
[node name="MarginContainer2" type="MarginContainer" parent="ControlYourCharacters"]
layout_mode = 1
anchors_preset = 11
anchor_left = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -70.0
grow_horizontal = 0
grow_vertical = 2
theme_override_constants/margin_left = 2
theme_override_constants/margin_top = 2
theme_override_constants/margin_right = 2
theme_override_constants/margin_bottom = 2
[node name="ColorRect" type="ColorRect" parent="ControlYourCharacters/MarginContainer2"]
layout_mode = 2
color = Color(0, 0, 0, 0.403922)
[node name="MarginContainer" type="MarginContainer" parent="ControlYourCharacters/MarginContainer2"]
layout_mode = 2
theme_override_constants/margin_left = 2
theme_override_constants/margin_top = 2
theme_override_constants/margin_right = 2
theme_override_constants/margin_bottom = 2
[node name="VBoxContainerCharacters" type="VBoxContainer" parent="ControlYourCharacters/MarginContainer2/MarginContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters"]
layout_mode = 2
theme_override_font_sizes/font_size = 8
text = "Your characters"
[node name="ScrollContainer" type="ScrollContainer" parent="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters"]
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 3
horizontal_scroll_mode = 0
vertical_scroll_mode = 2
[node name="VBoxContainer" type="VBoxContainer" parent="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters/ScrollContainer"]
layout_mode = 2
[node name="ButtonSelectChar" parent="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters/ScrollContainer/VBoxContainer" instance=ExtResource("7_bft24")]
layout_mode = 2
[node name="HBoxContainer" type="HBoxContainer" parent="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters"]
z_index = 1
layout_mode = 2
size_flags_vertical = 10
[node name="ButtonCreate" type="Button" parent="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_font_sizes/font_size = 6
text = "Create"
[node name="ButtonDelete" type="Button" parent="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters/HBoxContainer"]
z_index = 2
layout_mode = 2
size_flags_horizontal = 3
theme_override_font_sizes/font_size = 6
text = "Delete"
[connection signal="text_changed" from="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainerInputName/LineEdit" to="." method="_on_line_edit_text_changed"]
[connection signal="pressed" from="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/ButtonCreate" to="." method="_on_button_create_pressed"]

View File

@@ -0,0 +1,441 @@
[gd_scene load_steps=4 format=3 uid="uid://274rykgkxi3m"]
[ext_resource type="Script" uid="uid://dwmqhbjbhnrvy" path="res://scripts/ui/character_select.gd" id="1_4pvb2"]
[ext_resource type="PackedScene" uid="uid://dgtfy455abe1t" path="res://scripts/entities/player/player.tscn" id="4_5axoa"]
[ext_resource type="PackedScene" uid="uid://dgniqbtakal50" path="res://scripts/ui/button_select_char.tscn" id="7_bft24"]
[node name="CharacterSelect" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_4pvb2")
[node name="ControlCharacterInfo" type="Control" parent="."]
layout_mode = 1
anchors_preset = 0
offset_right = 40.0
offset_bottom = 40.0
[node name="MarginContainer" type="MarginContainer" parent="ControlCharacterInfo"]
layout_mode = 0
offset_right = 40.0
offset_bottom = 40.0
theme_override_constants/margin_left = 2
theme_override_constants/margin_top = 2
theme_override_constants/margin_right = 2
theme_override_constants/margin_bottom = 2
[node name="ColorRect" type="ColorRect" parent="ControlCharacterInfo/MarginContainer"]
layout_mode = 2
color = Color(0, 0, 0, 0.403922)
[node name="MarginContainer" type="MarginContainer" parent="ControlCharacterInfo/MarginContainer"]
layout_mode = 2
theme_override_constants/margin_left = 2
theme_override_constants/margin_top = 2
theme_override_constants/margin_right = 2
theme_override_constants/margin_bottom = 2
[node name="VBoxContainer" type="VBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
text = "Create new character"
[node name="TabContainer" type="TabContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
current_tab = 1
[node name="Eyes" type="VBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer"]
visible = false
layout_mode = 2
theme_override_constants/separation = 4
metadata/_tab_index = 0
[node name="HBoxContainerEyeColor" type="HBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Eyes"]
layout_mode = 2
[node name="LabelEyeColor" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Eyes/HBoxContainerEyeColor"]
layout_mode = 2
text = "Color"
[node name="HSliderEyeColor" type="HSlider" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Eyes/HBoxContainerEyeColor"]
layout_mode = 2
size_flags_horizontal = 3
max_value = 14.0
rounded = true
[node name="HBoxContainerEyeLashes" type="HBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Eyes"]
layout_mode = 2
[node name="LabelEyeLashes" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Eyes/HBoxContainerEyeLashes"]
layout_mode = 2
text = "Lashes"
[node name="HSliderEyeLashes" type="HSlider" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Eyes/HBoxContainerEyeLashes"]
layout_mode = 2
size_flags_horizontal = 3
max_value = 8.0
rounded = true
[node name="Hair" type="VBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer"]
layout_mode = 2
metadata/_tab_index = 1
[node name="HBoxContainerFacial" type="HBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair"]
layout_mode = 2
[node name="LabelFacial" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerFacial"]
layout_mode = 2
text = "Facial"
[node name="HSliderFacial" type="HSlider" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerFacial"]
layout_mode = 2
size_flags_horizontal = 3
max_value = 3.0
rounded = true
[node name="HSliderFacialColor" type="HSlider" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerFacial"]
layout_mode = 2
size_flags_horizontal = 3
max_value = 4.0
rounded = true
[node name="PickerButtonColorFacial" type="ColorPickerButton" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerFacial"]
layout_mode = 2
text = "test"
color = Color(1, 1, 1, 1)
edit_alpha = false
[node name="HBoxContainerHair" type="HBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair"]
layout_mode = 2
[node name="LabelHead" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerHair"]
layout_mode = 2
text = "Hair"
[node name="HSliderHair" type="HSlider" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerHair"]
layout_mode = 2
size_flags_horizontal = 3
max_value = 13.0
[node name="HSliderHairColor" type="HSlider" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerHair"]
layout_mode = 2
size_flags_horizontal = 3
max_value = 10.0
[node name="PickerButtonColorHair" type="ColorPickerButton" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerHair"]
layout_mode = 2
text = "test"
color = Color(1, 1, 1, 1)
edit_alpha = false
[node name="Skin" type="HBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer"]
visible = false
layout_mode = 2
metadata/_tab_index = 2
[node name="HSliderSkin" type="HSlider" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Skin"]
layout_mode = 2
size_flags_horizontal = 3
max_value = 6.0
[node name="Ears" type="HBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer"]
visible = false
layout_mode = 2
metadata/_tab_index = 3
[node name="HSliderEars" type="HSlider" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Ears"]
layout_mode = 2
size_flags_horizontal = 3
max_value = 7.0
[node name="HBoxContainer" type="HBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="VBoxContainerBaseStats" type="VBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
[node name="LabelBaseStatsHeader" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerBaseStats"]
modulate = Color(0.7429, 0.755937, 0.761719, 1)
layout_mode = 2
text = "Base Stats:"
[node name="HBoxContainerBaseStats" type="HBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerBaseStats"]
layout_mode = 2
[node name="LabelBaseStats" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerBaseStats/HBoxContainerBaseStats"]
layout_mode = 2
theme_override_constants/line_spacing = 0
text = "STR
DEX
END
INT
WIS
LCK"
[node name="LabelBaseStatsValues" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerBaseStats/HBoxContainerBaseStats"]
layout_mode = 2
theme_override_constants/line_spacing = 0
text = "10
10
10
10
10
10"
horizontal_alignment = 2
[node name="VBoxContainerDerivedStats" type="VBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
[node name="LabelDerivedStatsHeader" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerDerivedStats"]
modulate = Color(0.7429, 0.755937, 0.761719, 1)
layout_mode = 2
text = "Derived Stats:"
[node name="HBoxContainerDerivedStats" type="HBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerDerivedStats"]
layout_mode = 2
[node name="LabelDerivedStats" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerDerivedStats/HBoxContainerDerivedStats"]
layout_mode = 2
theme_override_constants/line_spacing = 0
text = "HP
MP
Damage
Defense
MoveSpd
AtkSpd
Sight
SpellAmp
CritChance"
[node name="LabelDerivedStatsValues" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerDerivedStats/HBoxContainerDerivedStats"]
layout_mode = 2
theme_override_constants/line_spacing = 0
text = "30.0
20.0
2.0
3.0
2.10
1.40
7.0
3.0
12.0%"
horizontal_alignment = 2
[node name="LabelDerivedStatsCalculations" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainerDerivedStats/HBoxContainerDerivedStats"]
modulate = Color(0.621094, 0.621094, 0.621094, 1)
layout_mode = 2
theme_override_constants/line_spacing = 0
text = "(END × 3)
(WIS × 2)
(STR × 0.2)
(END × 0.3)
(DEX × 0.01 + 2)
(DEX × 0.04 + 1)
(DEX × 0.2 + 5)
(INT × 0.2)
(LCK × 1.2)"
[node name="HBoxContainerInputName" type="HBoxContainer" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="LabelName" type="Label" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainerInputName"]
layout_mode = 2
text = "Name"
[node name="LineEdit" type="LineEdit" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainerInputName"]
layout_mode = 2
size_flags_horizontal = 3
placeholder_text = "Enter your character name"
max_length = 32
[node name="ButtonSave" type="Button" parent="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
text = "Save"
[node name="Control" type="Control" parent="."]
layout_mode = 1
anchors_preset = 7
anchor_left = 0.5
anchor_top = 1.0
anchor_right = 0.5
anchor_bottom = 1.0
offset_left = -20.0
offset_top = -40.0
offset_right = 20.0
grow_horizontal = 2
grow_vertical = 0
[node name="ButtonBack" type="Button" parent="Control"]
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -13.5
offset_top = -10.0
offset_right = 13.5
offset_bottom = 10.0
grow_horizontal = 2
grow_vertical = 2
theme_override_font_sizes/font_size = 8
text = "Back"
[node name="ControlSelectCharacter" type="Control" parent="."]
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
grow_horizontal = 2
grow_vertical = 2
scale = Vector2(2, 2)
[node name="VBoxContainer" type="VBoxContainer" parent="ControlSelectCharacter"]
layout_mode = 1
anchors_preset = 13
anchor_left = 0.5
anchor_right = 0.5
anchor_bottom = 1.0
offset_left = -23.5
offset_right = 23.5
grow_horizontal = 2
grow_vertical = 2
[node name="Control" type="Control" parent="ControlSelectCharacter/VBoxContainer"]
custom_minimum_size = Vector2(0, 14)
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
[node name="SelectableChar" type="Node2D" parent="ControlSelectCharacter/VBoxContainer/Control"]
[node name="ColorRect" type="ColorRect" parent="ControlSelectCharacter/VBoxContainer/Control/SelectableChar"]
custom_minimum_size = Vector2(31.73, 66.99)
anchors_preset = 13
anchor_left = 0.5
anchor_right = 0.5
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
size_flags_vertical = 3
color = Color(0, 0, 0, 0.431373)
[node name="Player" parent="ControlSelectCharacter/VBoxContainer/Control/SelectableChar" instance=ExtResource("4_5axoa")]
position = Vector2(0, 0.5)
[node name="ButtonPlay" type="Button" parent="ControlSelectCharacter/VBoxContainer"]
layout_mode = 2
size_flags_horizontal = 4
theme_override_font_sizes/font_size = 4
text = "PLAY"
[node name="ControlYourCharacters" type="Control" parent="."]
layout_mode = 1
anchors_preset = 11
anchor_left = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 0
grow_vertical = 2
[node name="MarginContainer2" type="MarginContainer" parent="ControlYourCharacters"]
layout_mode = 1
anchors_preset = 11
anchor_left = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -70.0
grow_horizontal = 0
grow_vertical = 2
theme_override_constants/margin_left = 2
theme_override_constants/margin_top = 2
theme_override_constants/margin_right = 2
theme_override_constants/margin_bottom = 2
[node name="ColorRect" type="ColorRect" parent="ControlYourCharacters/MarginContainer2"]
layout_mode = 2
color = Color(0, 0, 0, 0.403922)
[node name="MarginContainer" type="MarginContainer" parent="ControlYourCharacters/MarginContainer2"]
layout_mode = 2
theme_override_constants/margin_left = 2
theme_override_constants/margin_top = 2
theme_override_constants/margin_right = 2
theme_override_constants/margin_bottom = 2
[node name="VBoxContainerCharacters" type="VBoxContainer" parent="ControlYourCharacters/MarginContainer2/MarginContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters"]
layout_mode = 2
size_flags_vertical = 0
theme_override_font_sizes/font_size = 8
text = "Your characters"
[node name="ScrollContainer" type="ScrollContainer" parent="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters"]
layout_mode = 2
size_flags_vertical = 3
size_flags_stretch_ratio = 20.0
horizontal_scroll_mode = 0
vertical_scroll_mode = 2
[node name="VBoxContainer" type="VBoxContainer" parent="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters/ScrollContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="ButtonSelectChar" parent="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters/ScrollContainer/VBoxContainer" instance=ExtResource("7_bft24")]
layout_mode = 2
[node name="ButtonSelectChar2" parent="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters/ScrollContainer/VBoxContainer" instance=ExtResource("7_bft24")]
layout_mode = 2
[node name="ButtonSelectChar3" parent="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters/ScrollContainer/VBoxContainer" instance=ExtResource("7_bft24")]
layout_mode = 2
[node name="HBoxContainer" type="HBoxContainer" parent="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters"]
z_index = 1
layout_mode = 2
size_flags_vertical = 10
[node name="ButtonCreate" type="Button" parent="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_font_sizes/font_size = 6
text = "Create"
[node name="ButtonDelete" type="Button" parent="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters/HBoxContainer"]
z_index = 2
layout_mode = 2
size_flags_horizontal = 3
theme_override_font_sizes/font_size = 6
text = "Delete"
[connection signal="value_changed" from="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Eyes/HBoxContainerEyeColor/HSliderEyeColor" to="." method="_on_h_slider_eye_color_value_changed"]
[connection signal="value_changed" from="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Eyes/HBoxContainerEyeLashes/HSliderEyeLashes" to="." method="_on_h_slider_eye_lashes_value_changed"]
[connection signal="value_changed" from="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerFacial/HSliderFacial" to="." method="_on_h_slider_facial_value_changed"]
[connection signal="value_changed" from="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerFacial/HSliderFacialColor" to="." method="_on_h_slider_facial_value_changed"]
[connection signal="color_changed" from="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerFacial/PickerButtonColorFacial" to="." method="_on_picker_button_color_facial_color_changed"]
[connection signal="picker_created" from="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerFacial/PickerButtonColorFacial" to="." method="_on_color_picker_button_picker_created"]
[connection signal="value_changed" from="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerHair/HSliderHair" to="." method="_on_h_slider_hair_value_changed"]
[connection signal="value_changed" from="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerHair/HSliderHairColor" to="." method="_on_h_slider_hair_value_changed"]
[connection signal="color_changed" from="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Hair/HBoxContainerHair/PickerButtonColorHair" to="." method="_on_picker_button_color_hair_color_changed"]
[connection signal="value_changed" from="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Skin/HSliderSkin" to="." method="_on_h_slider_skin_value_changed"]
[connection signal="value_changed" from="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/TabContainer/Ears/HSliderEars" to="." method="_on_h_slider_ears_value_changed"]
[connection signal="text_changed" from="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/HBoxContainerInputName/LineEdit" to="." method="_on_line_edit_text_changed"]
[connection signal="pressed" from="ControlCharacterInfo/MarginContainer/MarginContainer/VBoxContainer/ButtonSave" to="." method="_on_button_save_pressed"]
[connection signal="pressed" from="Control/ButtonBack" to="." method="_on_button_back_pressed"]
[connection signal="pressed" from="ControlSelectCharacter/VBoxContainer/ButtonPlay" to="." method="_on_button_play_pressed"]
[connection signal="pressed" from="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters/HBoxContainer/ButtonCreate" to="." method="_on_button_create_pressed"]
[connection signal="pressed" from="ControlYourCharacters/MarginContainer2/MarginContainer/VBoxContainerCharacters/HBoxContainer/ButtonDelete" to="." method="_on_button_delete_pressed"]

491
src/scripts/ui/inventory.gd Normal file
View File

@@ -0,0 +1,491 @@
extends CanvasLayer
var is_showing_inventory = true
var finished_tween = true
var selectedItem:Item = null
var selectedEquipment:Item = null
var lastPressedItem:Item = null
var lastPressedType = "Item"
var timerSelect:float = 0.0
func bindInventory():
if GameManager.character_data.is_connected("character_changed", _charChanged):
GameManager.character_data.disconnect("character_changed", _charChanged)
GameManager.character_data.connect("character_changed", _charChanged)
pass
func _ready() -> void:
is_showing_inventory = false
var move_range = -119
$ControlContainer/ControlStats.position.x += move_range
move_range = 80
$ControlContainer/ControlInventory.position.x += move_range
move_range = 33
$ControlContainer/ControlInfo.position.y += move_range
$ControlContainer.mouse_filter = Control.MOUSE_FILTER_IGNORE
# Set up multiplayer peer
'
GameManager.host(21212, false)
GameManager.character_data.connect("character_changed", _charChanged)
#$Player.position = Vector2(30, 30)
var item = Item.new()
item.item_type = Item.ItemType.Equippable
item.equipment_type = Item.EquipmentType.ARMOUR
item.item_name = "Leather Armour"
item.description = "A nice leather armour"
item.spriteFrame = 12
item.modifiers["def"] = 2
item.equipmentPath = "res://assets/gfx/Puny-Characters/Layer 2 - Clothes/Tunic Body/BrownTunic.png"
GameManager.character_data.add_item(item)
var item2 = Item.new()
item2.item_type = Item.ItemType.Equippable
item2.equipment_type = Item.EquipmentType.HEADGEAR
item2.item_name = "Leather helm"
item2.description = "A nice leather helm"
item2.spriteFrame = 31
item2.modifiers["def"] = 1
item2.equipmentPath = "res://assets/gfx/Puny-Characters/Layer 6 - Headgears/Basic Mage/MageHatRed.png"
item2.colorReplacements = [
{ "original": Color(255/255.0, 39/255.0, 44/255.0), "replace": Color(255/255.0,106/255.0,39/255.0)},
{ "original": Color(182/255.0, 0, 0), "replace": Color(182/255.0,106/255.0,0)},
{ "original": Color(118/255.0, 1/255.0, 0), "replace": Color(118/255.0,66/255.0,0)},
{ "original": Color(72/255.0, 0, 12/255.0), "replace": Color(72/255.0,34/255.0,0)}
]
GameManager.character_data.add_item(item2)
var item3 = Item.new()
item3.item_type = Item.ItemType.Equippable
item3.equipment_type = Item.EquipmentType.MAINHAND
item3.weapon_type = Item.WeaponType.SWORD
item3.item_name = "Dagger"
item3.description = "A sharp dagger"
item3.spriteFrame = 5*20 + 10
item3.modifiers["dmg"] = 2
GameManager.character_data.add_item(item3)
var item4 = Item.new()
item4.item_type = Item.ItemType.Equippable
item4.equipment_type = Item.EquipmentType.MAINHAND
item4.weapon_type = Item.WeaponType.AXE
item4.item_name = "Hand Axe"
item4.description = "A sharp hand axe"
item4.spriteFrame = 5*20 + 11
item4.modifiers["dmg"] = 4
GameManager.character_data.add_item(item4)
var item5 = Item.new()
item5.item_type = Item.ItemType.Equippable
item5.equipment_type = Item.EquipmentType.OFFHAND
item5.weapon_type = Item.WeaponType.AMMUNITION
item5.quantity = 13
item5.can_have_multiple_of = true
item5.item_name = "Iron Arrow"
item5.description = "A sharp arrow made of iron and feathers from pelican birds"
item5.spriteFrame = 7*20 + 11
item5.modifiers["dmg"] = 3
GameManager.character_data.add_item(item5)
var item6 = Item.new()
item6.item_type = Item.ItemType.Equippable
item6.equipment_type = Item.EquipmentType.MAINHAND
item6.weapon_type = Item.WeaponType.BOW
item6.item_name = "Wooden Bow"
item6.description = "A wooden bow made of elfish lembas trees"
item6.spriteFrame = 6*20 + 16
item6.modifiers["dmg"] = 3
GameManager.character_data.add_item(item6)
var item7 = Item.new()
item7.item_type = Item.ItemType.Equippable
item7.equipment_type = Item.EquipmentType.BOOTS
item7.weapon_type = Item.WeaponType.NONE
item7.item_name = "Sandals"
item7.description = "A pair of shitty sandals"
item7.equipmentPath = "res://assets/gfx/Puny-Characters/Layer 1 - Shoes/ShoesBrown.png"
item7.spriteFrame = 2*20 + 10
item7.modifiers["def"] = 1
GameManager.character_data.add_item(item7)
'
# clear default stuff
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control/Sprite2DItem.texture = null
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/LabelItemDescription.text = ""
pass
func _charChanged(iChar:CharacterStats):
# update all stats:
$ControlContainer/ControlStats/MarginContainer/VBoxContainer/HBoxContainer/LabelBaseStatsValue.text = str(iChar.level) + "\r\n" + \
"\r\n" + \
str(floori(iChar.hp)) + "/" + str(floori(iChar.maxhp)) + "\r\n" + \
str(floori(iChar.mp)) + "/" + str(floori(iChar.maxmp)) + "\r\n" + \
"\r\n" + \
str(iChar.baseStats.str) + "\r\n" + \
str(iChar.baseStats.dex) + "\r\n" + \
str(iChar.baseStats.end) + "\r\n" + \
str(iChar.baseStats.int) + "\r\n" + \
str(iChar.baseStats.wis) + "\r\n" + \
str(iChar.baseStats.lck)
$ControlContainer/ControlStats/MarginContainer/VBoxContainer/HBoxContainer/LabelDerivedStatsValue.text = str(floori(iChar.xp)) + "/" + str(floori(iChar.xp_to_next_level)) + "\r\n" + \
str(iChar.coin) + "\r\n" + \
"\r\n" + \
"\r\n" + \
"\r\n" + \
str(iChar.damage) + "\r\n" + \
str(iChar.defense) + "\r\n" + \
str(iChar.move_speed) + "\r\n" + \
str(iChar.attack_speed) + "\r\n" + \
str(iChar.sight) + "\r\n" + \
str(iChar.spell_amp) + "\r\n" + \
str(iChar.crit_chance) + "%"
# read inventory and populate inventory
var vboxInvent = $ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory
for child in vboxInvent.find_child("HBoxControl1").get_children():
child.get_parent().remove_child(child)
child.propagate_call("queue_free", [])
for child in vboxInvent.find_child("HBoxControl2").get_children():
child.get_parent().remove_child(child)
child.propagate_call("queue_free", [])
for child in vboxInvent.find_child("HBoxControl3").get_children():
child.get_parent().remove_child(child)
child.propagate_call("queue_free", [])
var selected_tex = preload("res://assets/gfx/ui/inventory_slot_kenny_white.png")
var styleBoxHover:StyleBox = StyleBoxTexture.new()
var styleBoxFocused:StyleBox = StyleBoxTexture.new()
var styleBoxPressed:StyleBox = StyleBoxTexture.new()
var styleBoxEmpty:StyleBox = StyleBoxEmpty.new()
styleBoxHover.texture = selected_tex
styleBoxFocused.texture = selected_tex
styleBoxPressed.texture = selected_tex
var quantityFont:Font = load("res://assets/fonts/dmg_numbers.png")
for item:Item in iChar.inventory:
var btn:Button = Button.new()
btn.add_theme_stylebox_override("normal", styleBoxEmpty)
btn.add_theme_stylebox_override("hover", styleBoxHover)
btn.add_theme_stylebox_override("focus", styleBoxFocused)
btn.add_theme_stylebox_override("pressed", styleBoxPressed)
btn.custom_minimum_size = Vector2(24, 24)
btn.size = Vector2(24, 24)
vboxInvent.find_child("HBoxControl1").add_child(btn)
var spr:Sprite2D = Sprite2D.new()
spr.texture = load(item.spritePath)
spr.hframes = item.spriteFrames.x
spr.vframes = item.spriteFrames.y
spr.frame = item.spriteFrame
spr.centered = false
spr.position = Vector2(4,4)
btn.add_child(spr)
if item.can_have_multiple_of:
var lblQuantity:Label = Label.new()
lblQuantity.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
lblQuantity.size = Vector2(24, 24)
lblQuantity.custom_minimum_size = Vector2(0,0)
lblQuantity.position = Vector2(10, 2)
lblQuantity.text = str(item.quantity)
lblQuantity.add_theme_font_override("font", quantityFont)
lblQuantity.add_theme_font_size_override("font", 8)
lblQuantity.scale = Vector2(0.5, 0.5)
btn.add_child(lblQuantity)
pass
btn.connect("pressed", _selectItem.bind(item, true))
btn.connect("focus_entered", _selectItem.bind(item, false))
pass
# clear eq container...
var eqContainer = $ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer
for child in eqContainer.get_children():
child.get_parent().remove_child(child)
child.propagate_call("queue_free", [])
'"mainhand": null,
"offhand": null,
"headgear": null,
"armour": null,
"boots": null,
"accessory": null'
addEq(iChar, "mainhand", eqContainer, styleBoxEmpty, styleBoxHover, styleBoxFocused, styleBoxPressed, quantityFont)
addEq(iChar, "offhand", eqContainer, styleBoxEmpty, styleBoxHover, styleBoxFocused, styleBoxPressed, quantityFont)
addEq(iChar, "headgear", eqContainer, styleBoxEmpty, styleBoxHover, styleBoxFocused, styleBoxPressed, quantityFont)
addEq(iChar, "armour", eqContainer, styleBoxEmpty, styleBoxHover, styleBoxFocused, styleBoxPressed, quantityFont)
addEq(iChar, "boots", eqContainer, styleBoxEmpty, styleBoxHover, styleBoxFocused, styleBoxPressed, quantityFont)
addEq(iChar, "accessory", eqContainer, styleBoxEmpty, styleBoxHover, styleBoxFocused, styleBoxPressed, quantityFont)
pass
func addEq(iChar:CharacterStats, iPiece:String, eqContainer:Control, styleBoxEmpty: StyleBox, styleBoxHover: StyleBox, styleBoxFocused: StyleBox, styleBoxPressed: StyleBox, quantityFont: Font):
if iChar.equipment[iPiece] != null:
var btn:Button = Button.new()
btn.add_theme_stylebox_override("normal", styleBoxEmpty)
btn.add_theme_stylebox_override("hover", styleBoxHover)
btn.add_theme_stylebox_override("focus", styleBoxFocused)
btn.add_theme_stylebox_override("pressed", styleBoxPressed)
btn.custom_minimum_size = Vector2(24, 24)
btn.position = Vector2(1,9)
match iPiece:
"armour":
btn.position = Vector2(28, 9)
pass
"offhand":
btn.position = Vector2(55, 9)
pass
"headgear":
btn.position = Vector2(1, 36)
pass
"boots":
btn.position = Vector2(28, 36)
pass
"accessory":
btn.position = Vector2(55, 36)
pass
pass
eqContainer.add_child(btn)
var spr:Sprite2D = Sprite2D.new()
spr.texture = load(iChar.equipment[iPiece].spritePath)
spr.hframes = iChar.equipment[iPiece].spriteFrames.x
spr.vframes = iChar.equipment[iPiece].spriteFrames.y
spr.frame = iChar.equipment[iPiece].spriteFrame
spr.centered = false
spr.position = Vector2(4,4)
btn.add_child(spr)
btn.connect("pressed", _selectEquipment.bind(iChar.equipment[iPiece], true))
btn.connect("focus_entered", _selectEquipment.bind(iChar.equipment[iPiece], false))
if iChar.equipment[iPiece].can_have_multiple_of:
var lblQuantity:Label = Label.new()
lblQuantity.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
lblQuantity.size = Vector2(24, 24)
lblQuantity.custom_minimum_size = Vector2(0,0)
lblQuantity.position = Vector2(10, 2)
lblQuantity.text = str(iChar.equipment[iPiece].quantity)
lblQuantity.add_theme_font_override("font", quantityFont)
lblQuantity.add_theme_font_size_override("font", 8)
lblQuantity.scale = Vector2(0.5, 0.5)
btn.add_child(lblQuantity)
pass
pass
pass
# draw equipment buttons (for unequipping)
func _selectEquipment(item:Item, isPress: bool):
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/ButtonDrop.visible = true
if !is_showing_inventory:
return
if lastPressedItem == item and lastPressedType == "Equipment" and timerSelect > 0:
$SfxUnequip.play()
GameManager.character_data.unequip_item(selectedEquipment)
selectedItem = selectedEquipment
lastPressedItem = null
selectedEquipment = null
lastPressedType = "Item"
var vboxInvent = $ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory
for child in vboxInvent.find_child("HBoxControl1").get_children():
child.grab_focus()
break
return
lastPressedType = "Equipment"
selectedEquipment = item
# update description in bottom
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control/Sprite2DItem.texture = load(item.spritePath)
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control/Sprite2DItem.hframes = item.spriteFrames.x
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control/Sprite2DItem.vframes = item.spriteFrames.y
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control/Sprite2DItem.frame = item.spriteFrame
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/LabelItemDescription.text = item.description
if isPress:
lastPressedItem = item
timerSelect = 0.4
# unequip item
pass
func _selectItem(item:Item, isPress: bool):
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/ButtonDrop.visible = true
if !is_showing_inventory:
return
if lastPressedItem == item and lastPressedType == "Item" and timerSelect > 0:
timerSelect = 0
$SfxEquip.play()
GameManager.character_data.equip_item(selectedItem)
selectedEquipment = selectedItem
selectedItem = null
lastPressedItem = null
lastPressedType = "Equipment"
var eqContainer = $ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer
for child in eqContainer.get_children():
child.grab_focus()
break
return
lastPressedType = "Item"
selectedItem = item
# update description in bottom
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control/Sprite2DItem.texture = load(item.spritePath)
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control/Sprite2DItem.hframes = item.spriteFrames.x
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control/Sprite2DItem.vframes = item.spriteFrames.y
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control/Sprite2DItem.frame = item.spriteFrame
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/LabelItemDescription.text = item.description
if isPress:
lastPressedItem = item
timerSelect = 0.4
pass
func _process(delta: float) -> void:
if timerSelect > 0:
timerSelect -= delta
if timerSelect <= 0:
timerSelect = 0
pass
func _input(_event: InputEvent):
#print("connected to newtwork:", GameManager.is_network_connected)
#print("finished tween:", finished_tween)
if !GameManager.is_network_connected or finished_tween == false:
return
if is_showing_inventory:
if !$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/ButtonDrop.has_focus():
if lastPressedType == "Equipment" and selectedEquipment != null and Input.is_action_just_pressed("ui_accept"):
$SfxUnequip.play()
GameManager.character_data.unequip_item(selectedEquipment)
selectedItem = selectedEquipment
selectedEquipment = null
lastPressedItem = null
lastPressedType = "Item"
var vboxInvent = $ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory
for child in vboxInvent.find_child("HBoxControl1").get_children():
child.grab_focus()
break
return
if lastPressedType == "Item" and selectedItem != null and Input.is_action_just_pressed("ui_accept"):
$SfxEquip.play()
GameManager.character_data.equip_item(selectedItem)
selectedEquipment = selectedItem
selectedItem = null
lastPressedItem = null
lastPressedType = "Equipment"
var eqContainer = $ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer
for child in eqContainer.get_children():
child.grab_focus()
break
return
if Input.is_action_just_pressed("inventory") and finished_tween == true:
finished_tween = false
var move_range = 119
var move_duration = 0.3
if is_showing_inventory:
move_range = -move_range
#stats movement
var move_tween = get_tree().create_tween()
move_tween.tween_property($ControlContainer/ControlStats, "position:x",$ControlContainer/ControlStats.position.x + move_range,move_duration).from($ControlContainer/ControlStats.position.x).set_trans(Tween.TRANS_EXPO).set_ease(Tween.EASE_IN_OUT)
move_range = -80
if is_showing_inventory:
move_range = -move_range
#inventory movement
var move_tween2 = get_tree().create_tween()
move_tween2.tween_property($ControlContainer/ControlInventory, "position:x",$ControlContainer/ControlInventory.position.x + move_range,move_duration).from($ControlContainer/ControlInventory.position.x).set_trans(Tween.TRANS_EXPO).set_ease(Tween.EASE_IN_OUT)
move_range = -33
if is_showing_inventory:
$SfxInventoryClose.play()
move_range = -move_range
else:
$SfxInventoryOpen.play()
#info movement
var move_tween3 = get_tree().create_tween()
move_tween3.tween_property($ControlContainer/ControlInfo, "position:y",$ControlContainer/ControlInfo.position.y + move_range,move_duration).from($ControlContainer/ControlInfo.position.y).set_trans(Tween.TRANS_EXPO).set_ease(Tween.EASE_IN_OUT)
is_showing_inventory = !is_showing_inventory
await move_tween3.finished
finished_tween = true
if is_showing_inventory:
# preselect first item
var vboxInvent = $ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory
var hadInventoryItem = false
for child in vboxInvent.find_child("HBoxControl1").get_children():
child.grab_focus()
hadInventoryItem = true
break
lastPressedType = "Item"
if hadInventoryItem == false:
# preselect something in equipment instead
selectedItem = null
lastPressedItem = null
lastPressedType = "Equipment"
var eqContainer = $ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer
for child in eqContainer.get_children():
child.grab_focus()
break
pass
pass
'
if Input.is_action_just_pressed("ui_right"):
$ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer.
pass
if Input.is_action_just_pressed("ui_left"):
pass'
'
if Input.is_action_just_pressed("ui_up"):
$ControlContainer/ControlInventory/Sprite2DSelector.position.y -= 20
pass
if Input.is_action_just_pressed("ui_down"):
$ControlContainer/ControlInventory/Sprite2DSelector.position.y += 20
pass'
func _on_button_drop_pressed() -> void:
if !is_showing_inventory:
return
if lastPressedType == "Item":
if selectedItem != null:
GameManager.character_data.drop_item(selectedItem)
selectedItem = null
# clear default stuff
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control/Sprite2DItem.texture = null
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/LabelItemDescription.text = ""
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/ButtonDrop.visible = false
else:
if selectedEquipment != null:
GameManager.character_data.drop_equipment(selectedEquipment)
selectedEquipment = null
# clear default stuff
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control/Sprite2DItem.texture = null
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/LabelItemDescription.text = ""
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/ButtonDrop.visible = false
var vboxInvent = $ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory
var hadInventoryItem = false
for child in vboxInvent.find_child("HBoxControl1").get_children():
child.grab_focus()
hadInventoryItem = true
break
lastPressedType = "Item"
if hadInventoryItem == false:
selectedItem = null
lastPressedItem = null
lastPressedType = "Equipment"
var eqContainer = $ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer
for child in eqContainer.get_children():
child.grab_focus()
break
pass # Replace with function body.

View File

@@ -0,0 +1 @@
uid://20kfmxrtt20e

View File

@@ -0,0 +1,693 @@
[gd_scene load_steps=24 format=3 uid="uid://du1cpug8yag6w"]
[ext_resource type="Texture2D" uid="uid://b7u7dbiaub8lp" path="res://assets/gfx/ruinborn_mImwZSNWBM.png" id="1_0amil"]
[ext_resource type="Script" uid="uid://20kfmxrtt20e" path="res://assets/scripts/ui/inventory.gd" id="1_k81k7"]
[ext_resource type="Texture2D" uid="uid://hib38y541eog" path="res://assets/gfx/items_n_shit.png" id="2_7vwhs"]
[ext_resource type="Texture2D" uid="uid://ct0rllwve2s1y" path="res://assets/gfx/ui/inventory_panel_small.png" id="2_voqm7"]
[ext_resource type="Texture2D" uid="uid://who0clhmi5cl" path="res://assets/gfx/ui/inventory_panel.png" id="4_nlhqn"]
[ext_resource type="Texture2D" uid="uid://cxend0ndnfn32" path="res://assets/gfx/ui/inventory_slot_kenny_white.png" id="4_nxmsh"]
[ext_resource type="Texture2D" uid="uid://bsnfadlf1dgnw" path="res://assets/gfx/ui/inventory_slot_kenny_black_sword.png" id="6_k81k7"]
[ext_resource type="FontFile" uid="uid://cbmcfue0ek0tk" path="res://assets/fonts/dmg_numbers.png" id="7_kiwfx"]
[ext_resource type="Texture2D" uid="uid://tdivehfcj0el" path="res://assets/gfx/ui/inventory_slot_kenny_black_shield.png" id="7_vardb"]
[ext_resource type="Texture2D" uid="uid://b1l30o2ljhl2t" path="res://assets/gfx/ui/inventory_slot_kenny_black_armour.png" id="8_mnwqb"]
[ext_resource type="Texture2D" uid="uid://jgbrhnsaxvg" path="res://assets/gfx/ui/inventory_slot_kenny_black_helm.png" id="9_nbh80"]
[ext_resource type="Texture2D" uid="uid://b71gs7h2v0rdi" path="res://assets/gfx/ui/inventory_slot_kenny_black_ring.png" id="10_kiwfx"]
[ext_resource type="Texture2D" uid="uid://ckctmypotajtf" path="res://assets/gfx/ui/inventory_slot_kenny_black_shoes.png" id="11_ylqbh"]
[ext_resource type="Texture2D" uid="uid://c21a60s4funrr" path="res://assets/gfx/ui/inventory_info_panel.png" id="13_vardb"]
[ext_resource type="AudioStream" uid="uid://x6lxrywls7e2" path="res://assets/audio/sfx/inventory/inventory_open.mp3" id="14_mnwqb"]
[ext_resource type="AudioStream" uid="uid://cfsubtwvpi7yn" path="res://assets/audio/sfx/inventory/inventory_open_inverted.mp3" id="14_nbh80"]
[ext_resource type="AudioStream" uid="uid://djw6c5rb4mm60" path="res://assets/audio/sfx/cloth/leather_cloth_02.wav.mp3" id="17_51fgf"]
[ext_resource type="AudioStream" uid="uid://umoxmryvbm01" path="res://assets/audio/sfx/cloth/leather_cloth_01.wav.mp3" id="18_qk47y"]
[sub_resource type="StyleBoxTexture" id="StyleBoxTexture_nbh80"]
texture = ExtResource("4_nxmsh")
modulate_color = Color(0.511719, 0.511719, 0.511719, 1)
[sub_resource type="StyleBoxTexture" id="StyleBoxTexture_kiwfx"]
texture = ExtResource("4_nxmsh")
modulate_color = Color(0, 0, 0, 1)
[sub_resource type="StyleBoxTexture" id="StyleBoxTexture_ylqbh"]
texture = ExtResource("4_nxmsh")
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_nbh80"]
[sub_resource type="StyleBoxTexture" id="StyleBoxTexture_51fgf"]
texture = ExtResource("4_nxmsh")
[node name="Inventory" type="CanvasLayer"]
layer = 21
script = ExtResource("1_k81k7")
[node name="Sprite2D" type="Sprite2D" parent="."]
visible = false
modulate = Color(0.980057, 0.975295, 1, 1)
z_index = -2
z_as_relative = false
position = Vector2(164.625, 92.75)
scale = Vector2(0.258803, 0.263268)
texture = ExtResource("1_0amil")
[node name="ControlContainer" type="Control" parent="."]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="ControlStats" type="Control" parent="ControlContainer"]
layout_mode = 1
anchors_preset = 9
anchor_bottom = 1.0
grow_vertical = 2
[node name="Sprite2DPanelz" type="Sprite2D" parent="ControlContainer/ControlStats"]
texture = ExtResource("4_nlhqn")
centered = false
[node name="MarginContainer" type="MarginContainer" parent="ControlContainer/ControlStats"]
layout_mode = 0
offset_right = 40.0
offset_bottom = 40.0
theme_override_constants/margin_left = 3
theme_override_constants/margin_top = 3
theme_override_constants/margin_right = 3
theme_override_constants/margin_bottom = 3
[node name="VBoxContainer" type="VBoxContainer" parent="ControlContainer/ControlStats/MarginContainer"]
layout_mode = 2
[node name="LabelPlayerName" type="Label" parent="ControlContainer/ControlStats/MarginContainer/VBoxContainer"]
layout_mode = 2
theme_override_font_sizes/font_size = 6
text = "Fronko"
horizontal_alignment = 1
[node name="HBoxContainer" type="HBoxContainer" parent="ControlContainer/ControlStats/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="LabelBaseStats" type="Label" parent="ControlContainer/ControlStats/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
theme_override_constants/line_spacing = 0
theme_override_font_sizes/font_size = 6
text = "Level
Hp
Mp
Str
Dex
End
Int
Wis
Lck"
[node name="LabelBaseStatsValue" type="Label" parent="ControlContainer/ControlStats/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
theme_override_constants/line_spacing = 0
theme_override_font_sizes/font_size = 6
text = "1
30 / 30
20 / 20
10
10
10
10
10
10"
horizontal_alignment = 2
[node name="LabelDerivedStats" type="Label" parent="ControlContainer/ControlStats/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
theme_override_constants/line_spacing = 0
theme_override_font_sizes/font_size = 6
text = "Exp
Coin
Damage
Defense
MovSpd
AtkSpd
Sight
SpellAmp
CritChance"
[node name="LabelDerivedStatsValue" type="Label" parent="ControlContainer/ControlStats/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
theme_override_constants/line_spacing = 0
theme_override_font_sizes/font_size = 6
text = "400 / 1000
1
2
3
2.1
1.4
7.0
3.0
12.0%"
horizontal_alignment = 2
[node name="ControlInventory" type="Control" parent="ControlContainer"]
custom_minimum_size = Vector2(80, 0)
layout_mode = 1
anchors_preset = 11
anchor_left = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 0
grow_vertical = 2
[node name="Sprite2DPanel" type="Sprite2D" parent="ControlContainer/ControlInventory"]
modulate = Color(0, 0, 0, 0.862745)
texture = ExtResource("2_voqm7")
centered = false
[node name="MarginContainer" type="MarginContainer" parent="ControlContainer/ControlInventory"]
custom_minimum_size = Vector2(80, 0)
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/margin_left = 2
theme_override_constants/margin_top = 2
theme_override_constants/margin_right = 2
theme_override_constants/margin_bottom = 2
[node name="VBoxContainer" type="VBoxContainer" parent="ControlContainer/ControlInventory/MarginContainer"]
layout_mode = 2
theme_override_constants/separation = 0
[node name="LabelInventory" type="Label" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer"]
layout_mode = 2
theme_override_font_sizes/font_size = 6
text = "Inventory"
horizontal_alignment = 1
[node name="ControlInventory" type="Control" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer"]
custom_minimum_size = Vector2(0, 72)
layout_mode = 2
[node name="MarginContainer" type="MarginContainer" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory"]
layout_mode = 2
offset_left = 2.0
offset_top = 2.0
offset_right = 78.0
offset_bottom = 70.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/margin_left = 2
theme_override_constants/margin_top = 2
theme_override_constants/margin_right = 2
theme_override_constants/margin_bottom = 2
[node name="ScrollContainer" type="ScrollContainer" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer"]
layout_mode = 2
follow_focus = true
[node name="VBoxContainerInventory" type="VBoxContainer" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer"]
layout_mode = 2
theme_override_constants/separation = -4
[node name="HBoxControl1" type="HBoxContainer" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/separation = 0
[node name="Button3" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1/Button3"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="LabelStack" type="Label" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1/Button3"]
layout_mode = 1
anchors_preset = 1
anchor_left = 1.0
anchor_right = 1.0
offset_left = -26.0
offset_top = 2.0
offset_right = -2.0
offset_bottom = 26.0
grow_horizontal = 0
theme_override_fonts/font = ExtResource("7_kiwfx")
theme_override_font_sizes/font_size = 8
text = "5"
horizontal_alignment = 2
[node name="Button6" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1/Button6"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button5" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1/Button5"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button4" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1/Button4"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="HBoxControl2" type="HBoxContainer" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/separation = 0
[node name="Button3" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl2"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl2/Button3"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button5" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl2"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl2/Button5"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button4" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl2"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl2/Button4"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="HBoxControl3" type="HBoxContainer" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/separation = 0
[node name="Button3" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl3"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl3/Button3"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button5" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl3"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl3/Button5"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button4" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl3"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl3/Button4"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="ControlEquipment" type="Control" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer"]
custom_minimum_size = Vector2(80, 64)
layout_mode = 2
[node name="Label" type="Label" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
layout_mode = 1
anchors_preset = 5
anchor_left = 0.5
anchor_right = 0.5
offset_left = -21.5
offset_right = 21.5
offset_bottom = 23.0
grow_horizontal = 2
theme_override_font_sizes/font_size = 6
text = "Equipment"
horizontal_alignment = 1
[node name="Sprite2D" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
modulate = Color(1, 1, 1, 0.670588)
position = Vector2(13, 21)
texture = ExtResource("6_k81k7")
[node name="Sprite2D2" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
modulate = Color(1, 1, 1, 0.670588)
position = Vector2(67, 21)
texture = ExtResource("7_vardb")
[node name="Sprite2D3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
modulate = Color(1, 1, 1, 0.670588)
position = Vector2(40, 21)
texture = ExtResource("8_mnwqb")
[node name="Sprite2D4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
modulate = Color(1, 1, 1, 0.670588)
position = Vector2(13, 48)
texture = ExtResource("9_nbh80")
[node name="Sprite2D9" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
modulate = Color(1, 1, 1, 0.670588)
position = Vector2(67, 48)
texture = ExtResource("10_kiwfx")
[node name="Sprite2D5" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
modulate = Color(1, 1, 1, 0.670588)
position = Vector2(40, 48)
texture = ExtResource("11_ylqbh")
[node name="ControlEquipmentContainer" type="Control" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Button" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 0
offset_left = 1.0
offset_top = 9.0
offset_right = 25.0
offset_bottom = 33.0
theme_override_styles/normal = SubResource("StyleBoxTexture_51fgf")
[node name="Sprite2DShield3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer/Button"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button2" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 0
offset_left = 28.0
offset_top = 9.0
offset_right = 52.0
offset_bottom = 33.0
theme_override_styles/normal = SubResource("StyleBoxTexture_51fgf")
[node name="Sprite2DShield3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer/Button2"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button3" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 0
offset_left = 55.0
offset_top = 9.0
offset_right = 79.0
offset_bottom = 33.0
theme_override_styles/normal = SubResource("StyleBoxTexture_51fgf")
[node name="Sprite2DShield3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer/Button3"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button4" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 0
offset_left = 1.0
offset_top = 36.0
offset_right = 25.0
offset_bottom = 60.0
theme_override_styles/normal = SubResource("StyleBoxTexture_51fgf")
[node name="Sprite2DShield3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer/Button4"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button5" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 0
offset_left = 28.0
offset_top = 36.0
offset_right = 52.0
offset_bottom = 60.0
theme_override_styles/normal = SubResource("StyleBoxTexture_51fgf")
[node name="Sprite2DShield3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer/Button5"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button6" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 0
offset_left = 55.0
offset_top = 36.0
offset_right = 79.0
offset_bottom = 60.0
theme_override_styles/normal = SubResource("StyleBoxTexture_51fgf")
[node name="Sprite2DShield3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer/Button6"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="ControlInfo" type="Control" parent="ControlContainer"]
custom_minimum_size = Vector2(0, 33)
layout_mode = 1
anchors_preset = 12
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 0
[node name="Control" type="Control" parent="ControlContainer/ControlInfo"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Sprite2D" type="Sprite2D" parent="ControlContainer/ControlInfo/Control"]
texture = ExtResource("13_vardb")
centered = false
[node name="MarginContainer" type="MarginContainer" parent="ControlContainer/ControlInfo/Control"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/margin_left = 5
theme_override_constants/margin_top = 5
theme_override_constants/margin_right = 5
theme_override_constants/margin_bottom = 5
[node name="HBoxContainer" type="HBoxContainer" parent="ControlContainer/ControlInfo/Control/MarginContainer"]
layout_mode = 2
[node name="Control" type="Control" parent="ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_vertical = 4
[node name="Sprite2DSelector" type="Sprite2D" parent="ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control"]
modulate = Color(0.20704, 0.205805, 0.214844, 1)
texture = ExtResource("4_nxmsh")
centered = false
[node name="Sprite2DItem" type="Sprite2D" parent="ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="LabelItemDescription" type="Label" parent="ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer"]
layout_mode = 2
size_flags_vertical = 1
theme_override_font_sizes/font_size = 6
text = "A small, but sturdy wooden shield. + 1 DEF"
[node name="ButtonDrop" type="Button" parent="ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer"]
layout_mode = 2
theme_override_font_sizes/font_size = 8
text = "Drop"
[node name="SfxInventoryClose" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("14_nbh80")
volume_db = -10.0
[node name="SfxInventoryOpen" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("14_mnwqb")
volume_db = -10.0
[node name="SfxUnequip" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("17_51fgf")
[node name="SfxEquip" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("18_qk47y")
[connection signal="pressed" from="ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/ButtonDrop" to="." method="_on_button_drop_pressed"]

View File

@@ -0,0 +1,692 @@
[gd_scene load_steps=24 format=3 uid="uid://du1cpug8yag6w"]
[ext_resource type="Texture2D" uid="uid://b7u7dbiaub8lp" path="res://assets/gfx/ruinborn_mImwZSNWBM.png" id="1_0amil"]
[ext_resource type="Script" uid="uid://20kfmxrtt20e" path="res://assets/scripts/ui/inventory.gd" id="1_k81k7"]
[ext_resource type="Texture2D" uid="uid://hib38y541eog" path="res://assets/gfx/items_n_shit.png" id="2_7vwhs"]
[ext_resource type="Texture2D" uid="uid://ct0rllwve2s1y" path="res://assets/gfx/ui/inventory_panel_small.png" id="2_voqm7"]
[ext_resource type="Texture2D" uid="uid://who0clhmi5cl" path="res://assets/gfx/ui/inventory_panel.png" id="4_nlhqn"]
[ext_resource type="Texture2D" uid="uid://cxend0ndnfn32" path="res://assets/gfx/ui/inventory_slot_kenny_white.png" id="4_nxmsh"]
[ext_resource type="Texture2D" uid="uid://bsnfadlf1dgnw" path="res://assets/gfx/ui/inventory_slot_kenny_black_sword.png" id="6_k81k7"]
[ext_resource type="FontFile" uid="uid://cbmcfue0ek0tk" path="res://assets/fonts/dmg_numbers.png" id="7_kiwfx"]
[ext_resource type="Texture2D" uid="uid://tdivehfcj0el" path="res://assets/gfx/ui/inventory_slot_kenny_black_shield.png" id="7_vardb"]
[ext_resource type="Texture2D" uid="uid://b1l30o2ljhl2t" path="res://assets/gfx/ui/inventory_slot_kenny_black_armour.png" id="8_mnwqb"]
[ext_resource type="Texture2D" uid="uid://jgbrhnsaxvg" path="res://assets/gfx/ui/inventory_slot_kenny_black_helm.png" id="9_nbh80"]
[ext_resource type="Texture2D" uid="uid://b71gs7h2v0rdi" path="res://assets/gfx/ui/inventory_slot_kenny_black_ring.png" id="10_kiwfx"]
[ext_resource type="Texture2D" uid="uid://ckctmypotajtf" path="res://assets/gfx/ui/inventory_slot_kenny_black_shoes.png" id="11_ylqbh"]
[ext_resource type="Texture2D" uid="uid://c21a60s4funrr" path="res://assets/gfx/ui/inventory_info_panel.png" id="13_vardb"]
[ext_resource type="AudioStream" uid="uid://x6lxrywls7e2" path="res://assets/audio/sfx/inventory/inventory_open.mp3" id="14_mnwqb"]
[ext_resource type="AudioStream" uid="uid://cfsubtwvpi7yn" path="res://assets/audio/sfx/inventory/inventory_open_inverted.mp3" id="14_nbh80"]
[ext_resource type="AudioStream" uid="uid://djw6c5rb4mm60" path="res://assets/audio/sfx/cloth/leather_cloth_02.wav.mp3" id="17_51fgf"]
[ext_resource type="AudioStream" uid="uid://umoxmryvbm01" path="res://assets/audio/sfx/cloth/leather_cloth_01.wav.mp3" id="18_qk47y"]
[sub_resource type="StyleBoxTexture" id="StyleBoxTexture_nbh80"]
texture = ExtResource("4_nxmsh")
modulate_color = Color(0.511719, 0.511719, 0.511719, 1)
[sub_resource type="StyleBoxTexture" id="StyleBoxTexture_kiwfx"]
texture = ExtResource("4_nxmsh")
modulate_color = Color(0, 0, 0, 1)
[sub_resource type="StyleBoxTexture" id="StyleBoxTexture_ylqbh"]
texture = ExtResource("4_nxmsh")
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_nbh80"]
[sub_resource type="StyleBoxTexture" id="StyleBoxTexture_51fgf"]
texture = ExtResource("4_nxmsh")
[node name="Inventory" type="CanvasLayer"]
layer = 21
script = ExtResource("1_k81k7")
[node name="Sprite2D" type="Sprite2D" parent="."]
visible = false
modulate = Color(0.980057, 0.975295, 1, 1)
z_index = -2
z_as_relative = false
position = Vector2(164.625, 92.75)
scale = Vector2(0.258803, 0.263268)
texture = ExtResource("1_0amil")
[node name="ControlContainer" type="Control" parent="."]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="ControlStats" type="Control" parent="ControlContainer"]
layout_mode = 1
anchors_preset = 9
anchor_bottom = 1.0
grow_vertical = 2
[node name="Sprite2DPanelz" type="Sprite2D" parent="ControlContainer/ControlStats"]
texture = ExtResource("4_nlhqn")
centered = false
[node name="MarginContainer" type="MarginContainer" parent="ControlContainer/ControlStats"]
layout_mode = 0
offset_right = 40.0
offset_bottom = 40.0
theme_override_constants/margin_left = 3
theme_override_constants/margin_top = 3
theme_override_constants/margin_right = 3
theme_override_constants/margin_bottom = 3
[node name="VBoxContainer" type="VBoxContainer" parent="ControlContainer/ControlStats/MarginContainer"]
layout_mode = 2
[node name="LabelPlayerName" type="Label" parent="ControlContainer/ControlStats/MarginContainer/VBoxContainer"]
layout_mode = 2
theme_override_font_sizes/font_size = 6
text = "Fronko"
horizontal_alignment = 1
[node name="HBoxContainer" type="HBoxContainer" parent="ControlContainer/ControlStats/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="LabelBaseStats" type="Label" parent="ControlContainer/ControlStats/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
theme_override_constants/line_spacing = 0
theme_override_font_sizes/font_size = 6
text = "Level
Hp
Mp
Str
Dex
End
Int
Wis
Lck"
[node name="LabelBaseStatsValue" type="Label" parent="ControlContainer/ControlStats/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
theme_override_constants/line_spacing = 0
theme_override_font_sizes/font_size = 6
text = "1
30 / 30
20 / 20
10
10
10
10
10
10"
horizontal_alignment = 2
[node name="LabelDerivedStats" type="Label" parent="ControlContainer/ControlStats/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
theme_override_constants/line_spacing = 0
theme_override_font_sizes/font_size = 6
text = "Exp
Coin
Damage
Defense
MovSpd
AtkSpd
Sight
SpellAmp
CritChance"
[node name="LabelDerivedStatsValue" type="Label" parent="ControlContainer/ControlStats/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
theme_override_constants/line_spacing = 0
theme_override_font_sizes/font_size = 6
text = "400 / 1000
1
2
3
2.1
1.4
7.0
3.0
12.0%"
horizontal_alignment = 2
[node name="ControlInventory" type="Control" parent="ControlContainer"]
custom_minimum_size = Vector2(80, 0)
layout_mode = 1
anchors_preset = 11
anchor_left = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 0
grow_vertical = 2
[node name="Sprite2DPanel" type="Sprite2D" parent="ControlContainer/ControlInventory"]
modulate = Color(0, 0, 0, 0.862745)
texture = ExtResource("2_voqm7")
centered = false
[node name="MarginContainer" type="MarginContainer" parent="ControlContainer/ControlInventory"]
custom_minimum_size = Vector2(80, 0)
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/margin_left = 2
theme_override_constants/margin_top = 2
theme_override_constants/margin_right = 2
theme_override_constants/margin_bottom = 2
[node name="VBoxContainer" type="VBoxContainer" parent="ControlContainer/ControlInventory/MarginContainer"]
layout_mode = 2
theme_override_constants/separation = 0
[node name="LabelInventory" type="Label" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer"]
layout_mode = 2
theme_override_font_sizes/font_size = 6
text = "Inventory"
horizontal_alignment = 1
[node name="ControlInventory" type="Control" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer"]
custom_minimum_size = Vector2(0, 72)
layout_mode = 2
[node name="MarginContainer" type="MarginContainer" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory"]
layout_mode = 2
offset_left = 2.0
offset_top = 2.0
offset_right = 78.0
offset_bottom = 70.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/margin_left = 2
theme_override_constants/margin_top = 2
theme_override_constants/margin_right = 2
theme_override_constants/margin_bottom = 2
[node name="ScrollContainer" type="ScrollContainer" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer"]
layout_mode = 2
follow_focus = true
[node name="VBoxContainerInventory" type="VBoxContainer" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer"]
layout_mode = 2
theme_override_constants/separation = -4
[node name="HBoxControl1" type="HBoxContainer" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/separation = 0
[node name="Button3" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1/Button3"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="LabelStack" type="Label" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1/Button3"]
layout_mode = 1
anchors_preset = 1
anchor_left = 1.0
anchor_right = 1.0
offset_left = -26.0
offset_top = 2.0
offset_right = -2.0
offset_bottom = 26.0
grow_horizontal = 0
theme_override_fonts/font = ExtResource("7_kiwfx")
theme_override_font_sizes/font_size = 8
text = "5"
horizontal_alignment = 2
[node name="Button6" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1/Button6"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button5" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1/Button5"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button4" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1/Button4"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="HBoxControl2" type="HBoxContainer" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/separation = 0
[node name="Button3" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl2"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl2/Button3"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button5" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl2"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl2/Button5"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button4" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl2"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl2/Button4"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="HBoxControl3" type="HBoxContainer" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/separation = 0
[node name="Button3" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl3"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl3/Button3"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button5" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl3"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl3/Button5"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button4" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl3"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl3/Button4"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="ControlEquipment" type="Control" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer"]
custom_minimum_size = Vector2(80, 64)
layout_mode = 2
[node name="Label" type="Label" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
layout_mode = 1
anchors_preset = 5
anchor_left = 0.5
anchor_right = 0.5
offset_left = -21.5
offset_right = 21.5
offset_bottom = 23.0
grow_horizontal = 2
theme_override_font_sizes/font_size = 6
text = "Equipment"
horizontal_alignment = 1
[node name="Sprite2D" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
modulate = Color(1, 1, 1, 0.670588)
position = Vector2(13, 21)
texture = ExtResource("6_k81k7")
[node name="Sprite2D2" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
modulate = Color(1, 1, 1, 0.670588)
position = Vector2(67, 21)
texture = ExtResource("7_vardb")
[node name="Sprite2D3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
modulate = Color(1, 1, 1, 0.670588)
position = Vector2(40, 21)
texture = ExtResource("8_mnwqb")
[node name="Sprite2D4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
modulate = Color(1, 1, 1, 0.670588)
position = Vector2(13, 48)
texture = ExtResource("9_nbh80")
[node name="Sprite2D9" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
modulate = Color(1, 1, 1, 0.670588)
position = Vector2(67, 48)
texture = ExtResource("10_kiwfx")
[node name="Sprite2D5" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
modulate = Color(1, 1, 1, 0.670588)
position = Vector2(40, 48)
texture = ExtResource("11_ylqbh")
[node name="ControlEquipmentContainer" type="Control" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Button" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 0
offset_left = 1.0
offset_top = 9.0
offset_right = 25.0
offset_bottom = 33.0
theme_override_styles/normal = SubResource("StyleBoxTexture_51fgf")
[node name="Sprite2DShield3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer/Button"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button2" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 0
offset_left = 28.0
offset_top = 9.0
offset_right = 52.0
offset_bottom = 33.0
theme_override_styles/normal = SubResource("StyleBoxTexture_51fgf")
[node name="Sprite2DShield3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer/Button2"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button3" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 0
offset_left = 55.0
offset_top = 9.0
offset_right = 79.0
offset_bottom = 33.0
theme_override_styles/normal = SubResource("StyleBoxTexture_51fgf")
[node name="Sprite2DShield3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer/Button3"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button4" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 0
offset_left = 1.0
offset_top = 36.0
offset_right = 25.0
offset_bottom = 60.0
theme_override_styles/normal = SubResource("StyleBoxTexture_51fgf")
[node name="Sprite2DShield3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer/Button4"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button5" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 0
offset_left = 28.0
offset_top = 36.0
offset_right = 52.0
offset_bottom = 60.0
theme_override_styles/normal = SubResource("StyleBoxTexture_51fgf")
[node name="Sprite2DShield3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer/Button5"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button6" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 0
offset_left = 55.0
offset_top = 36.0
offset_right = 79.0
offset_bottom = 60.0
theme_override_styles/normal = SubResource("StyleBoxTexture_51fgf")
[node name="Sprite2DShield3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer/Button6"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="ControlInfo" type="Control" parent="ControlContainer"]
custom_minimum_size = Vector2(0, 33)
layout_mode = 1
anchors_preset = 12
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 0
[node name="Control" type="Control" parent="ControlContainer/ControlInfo"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Sprite2D" type="Sprite2D" parent="ControlContainer/ControlInfo/Control"]
texture = ExtResource("13_vardb")
centered = false
[node name="MarginContainer" type="MarginContainer" parent="ControlContainer/ControlInfo/Control"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/margin_left = 5
theme_override_constants/margin_top = 5
theme_override_constants/margin_right = 5
theme_override_constants/margin_bottom = 5
[node name="HBoxContainer" type="HBoxContainer" parent="ControlContainer/ControlInfo/Control/MarginContainer"]
layout_mode = 2
[node name="Control" type="Control" parent="ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_vertical = 4
[node name="Sprite2DSelector" type="Sprite2D" parent="ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control"]
modulate = Color(0.20704, 0.205805, 0.214844, 1)
texture = ExtResource("4_nxmsh")
centered = false
[node name="Sprite2DItem" type="Sprite2D" parent="ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="LabelItemDescription" type="Label" parent="ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer"]
layout_mode = 2
size_flags_vertical = 1
theme_override_font_sizes/font_size = 6
text = "A small, but sturdy wooden shield. + 1 DEF"
[node name="ButtonEquip" type="Button" parent="ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer"]
visible = false
layout_mode = 2
theme_override_font_sizes/font_size = 8
text = "Equip"
[node name="SfxInventoryClose" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("14_nbh80")
volume_db = -10.0
[node name="SfxInventoryOpen" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("14_mnwqb")
volume_db = -10.0
[node name="SfxUnequip" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("17_51fgf")
[node name="SfxEquip" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("18_qk47y")

View File

@@ -0,0 +1,39 @@
extends Control
func _ready() -> void:
$CanvasLayer/CharacterSelect.character_choose.connect(_showHostButton)
MultiplayerManager.connectionFailed.connect(_connectFail)
MultiplayerManager.connectionSucceeded.connect(_connectSuccess)
$CanvasLayer/CharacterSelect.visible = true
#_showHostButton()
pass
func _showHostButton():
$CanvasLayer/CharacterSelect.visible = false
$CanvasLayer/VBoxContainer.visible = true
$CanvasLayer/CharacterSelect.queue_free()
pass
func _connectFail():
self.visible = true
$CanvasLayer.visible = true
pass
func _connectSuccess():
#$CanvasLayer/CharacterSelect.queue_free()
pass
func _on_button_host_pressed() -> void:
self.visible = false
$CanvasLayer.visible = false
MultiplayerManager.host()
#$CanvasLayer/CharacterSelect.queue_free()
pass # Replace with function body.
func _on_button_join_pressed() -> void:
self.visible = false
$CanvasLayer.visible = false
MultiplayerManager.join()
pass # Replace with function body.

View File

@@ -0,0 +1 @@
uid://b11oy1ejms306

Binary file not shown.

View File

@@ -0,0 +1,48 @@
[gd_scene load_steps=3 format=3 uid="uid://bb3ku551810en"]
[ext_resource type="Script" uid="uid://b11oy1ejms306" path="res://scripts/ui/main_menu.gd" id="1_2jmfu"]
[ext_resource type="PackedScene" uid="uid://274rykgkxi3m" path="res://scripts/ui/character_select.tscn" id="2_7ntqy"]
[node name="MainMenu" type="Control"]
layout_mode = 3
anchors_preset = 0
offset_right = 46.0
offset_bottom = 54.0
script = ExtResource("1_2jmfu")
[node name="CanvasLayer" type="CanvasLayer" parent="."]
layer = 2
[node name="CharacterSelect" parent="CanvasLayer" instance=ExtResource("2_7ntqy")]
visible = false
[node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer"]
offset_right = 42.0
offset_bottom = 46.0
[node name="ButtonHost" type="Button" parent="CanvasLayer/VBoxContainer"]
layout_mode = 2
theme_override_constants/outline_size = 8
theme_override_font_sizes/font_size = 32
text = "Host"
flat = true
[node name="ButtonJoin" type="Button" parent="CanvasLayer/VBoxContainer"]
layout_mode = 2
theme_override_constants/outline_size = 8
theme_override_font_sizes/font_size = 32
text = "Join
"
flat = true
[node name="Label" type="Label" parent="CanvasLayer/VBoxContainer"]
layout_mode = 2
theme_override_constants/outline_size = 6
text = "DEATHMATCH - POT YOUR ENEMY!
Use Arrowkeys or WASD to move.
Use F or RightMouse to pickup/throw/push/pull pots
Use CTRL or LeftMouse to attack (does nothing besides throw pots atm...)"
[connection signal="pressed" from="CanvasLayer/VBoxContainer/ButtonHost" to="." method="_on_button_host_pressed"]
[connection signal="pressed" from="CanvasLayer/VBoxContainer/ButtonJoin" to="." method="_on_button_join_pressed"]

File diff suppressed because one or more lines are too long