Compare commits

..

42 Commits

Author SHA1 Message Date
Georgiy Gorin 221727289d New pics 2026-05-06 20:23:07 +03:00
DragonSpirit 1baf3e047b latest prompts by @gera 2026-05-06 09:06:08 +03:00
Nikolay Fedorov 849b0b7315 fix sound 2026-04-23 19:05:10 +03:00
DragonSpirit 1c70488ea5 add animation on movement 2026-04-23 18:53:50 +03:00
Georgiy Gorin 480d355926 Sound 2026-04-23 18:53:25 +03:00
Nikolay Fedorov 229a2cca60 add walk animation 2026-04-23 18:50:01 +03:00
Nikolay Fedorov b0ef832c64 fix rotation 2026-04-23 18:39:58 +03:00
DragonSpirit f28f21d5b4 add sounds, add logo 2026-04-23 18:32:57 +03:00
Nikolay Fedorov 69babae913 update game name 2026-04-23 18:23:11 +03:00
DragonSpirit e3261f8e78 update tutors 2026-04-23 18:22:37 +03:00
DragonSpirit 794261e0d0 win and lose cheat hotkey 2026-04-23 18:16:26 +03:00
DragonSpirit 187fe7a9ce mouse save 2026-04-23 18:14:14 +03:00
DragonSpirit c201a67bb8 add kick animation by enemy 2026-04-23 18:11:03 +03:00
Georgiy Gorin 7475339ddb recepie 2026-04-23 18:00:17 +03:00
Nikolay Fedorov dd60de0a66 update shape order 2026-04-23 17:48:23 +03:00
Nikolay Fedorov 912bffd59a Merge branch 'exp' of https://git.nfedorov.dev/DragonSpirit/KickSurvivors into exp 2026-04-23 17:45:50 +03:00
Nikolay Fedorov a2e710575e import new gnomes 2026-04-23 17:45:17 +03:00
Georgiy Gorin 31cab204ad Правки 2 2026-04-23 17:40:24 +03:00
Georgiy Gorin 3a3edc54a4 По хуйне 2026-04-23 17:34:24 +03:00
DragonSpirit 05f46021b8 add recepies list 2026-04-23 17:29:43 +03:00
Georgiy Gorin 5f589c8c89 Железо добавлено 2026-04-23 17:20:24 +03:00
DragonSpirit c8aba822bf remove coloring when item grabbed 2026-04-23 17:20:14 +03:00
DragonSpirit 23177b9079 increase hud text 2026-04-23 17:18:07 +03:00
Georgiy Gorin 86b837dded Боты добавил 2026-04-23 17:16:41 +03:00
DragonSpirit a835ae5755 fix tutorial images 2026-04-23 17:14:15 +03:00
DragonSpirit d20360c8f3 apply boot material 2026-04-23 17:11:45 +03:00
DragonSpirit fb3b653604 fix boot animation 2026-04-23 17:08:14 +03:00
Nikolay Fedorov 6b7294dfd8 add boot animation 2026-04-23 17:06:10 +03:00
Nikolay Fedorov 82af31501d add boots 2026-04-23 16:52:12 +03:00
Georgiy Gorin 0d9890c370 Баланс + картинки 3 босс, конец игры 2026-04-23 16:51:43 +03:00
Nikolay Fedorov d36a2cf9ec fix props 2026-04-23 16:28:34 +03:00
Georgiy Gorin e185d2e1fd Merge branch 'exp' of https://git.nfedorov.dev/DragonSpirit/KickSurvivors into exp 2026-04-23 16:27:03 +03:00
DragonSpirit 7d6d96e499 shield on spacebar 2026-04-23 16:18:35 +03:00
DragonSpirit 3c2afefc95 spawn settings 2026-04-23 16:17:40 +03:00
Georgiy Gorin 34a9b6b18f Нью баланс 2026-04-23 16:11:34 +03:00
DragonSpirit 9acbc49084 difficulity 2026-04-23 16:05:25 +03:00
Nikolay Fedorov 3542c328c0 fix export shield tutor 2026-04-23 15:59:14 +03:00
DragonSpirit f37c27887e upgrade mesh merge 2026-04-23 15:52:36 +03:00
DragonSpirit 20eaa513c3 fix stick and rock spawn 2026-04-23 15:42:14 +03:00
DragonSpirit 3974d7416d boss phase 2026-04-23 15:38:45 +03:00
Nikolay Fedorov 5d843f94f7 change kick to lmb 2026-04-23 15:36:17 +03:00
Nikolay Fedorov 8e7ff9ae83 rollback huge hit 2026-04-23 15:28:18 +03:00
86 changed files with 41887 additions and 16839 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

+40
View File
@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ccbdsbteef3cs"
path="res://.godot/imported/LoseGame.jpeg-bea62e54d6bb932d2fc0c97398854ad4.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/LoseGame.jpeg"
dest_files=["res://.godot/imported/LoseGame.jpeg-bea62e54d6bb932d2fc0c97398854ad4.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
Binary file not shown.

After

Width:  |  Height:  |  Size: 484 KiB

+40
View File
@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://un6qkfobvo2o"
path="res://.godot/imported/Pause_Controls.jpeg-7b152fd8be8bb847576ebbef7cd65320.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/Pause_Controls.jpeg"
dest_files=["res://.godot/imported/Pause_Controls.jpeg-7b152fd8be8bb847576ebbef7cd65320.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
Binary file not shown.

After

Width:  |  Height:  |  Size: 372 KiB

+40
View File
@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cavydxru3563h"
path="res://.godot/imported/Pause_Craft.jpeg-62e6f52659e81a185c138647d52f9aef.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/Pause_Craft.jpeg"
dest_files=["res://.godot/imported/Pause_Craft.jpeg-62e6f52659e81a185c138647d52f9aef.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
Binary file not shown.

After

Width:  |  Height:  |  Size: 424 KiB

+40
View File
@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c335dn481ctxu"
path="res://.godot/imported/ThirdLevelEnemy.jpeg-283cc2c1ead2d9769e11fd7206d21703.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/ThirdLevelEnemy.jpeg"
dest_files=["res://.godot/imported/ThirdLevelEnemy.jpeg-283cc2c1ead2d9769e11fd7206d21703.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 177 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 405 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 324 KiB

+3 -3
View File
@@ -3,15 +3,15 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://baeea1yfs0cnn"
path="res://.godot/imported/Tutorial_shield.jpeg-d9b563c9ca34dc1a19e82a0ec964c1b9.ctex"
path="res://.godot/imported/Tutorial_Shield.jpeg-6b96e6b9716aced42153397e827ce868.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/Tutorial_shield.jpeg"
dest_files=["res://.godot/imported/Tutorial_shield.jpeg-d9b563c9ca34dc1a19e82a0ec964c1b9.ctex"]
source_file="res://assets/Tutorial_Shield.jpeg"
dest_files=["res://.godot/imported/Tutorial_Shield.jpeg-6b96e6b9716aced42153397e827ce868.ctex"]
[params]
Binary file not shown.

After

Width:  |  Height:  |  Size: 231 KiB

+40
View File
@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cqo3yiuu4kwdk"
path="res://.godot/imported/VictoryScreen.jpeg-36aa76d727e7a226d71b97af302cccc0.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/VictoryScreen.jpeg"
dest_files=["res://.godot/imported/VictoryScreen.jpeg-36aa76d727e7a226d71b97af302cccc0.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
Binary file not shown.
+19
View File
@@ -0,0 +1,19 @@
[remap]
importer="oggvorbisstr"
type="AudioStreamOggVorbis"
uid="uid://boyy2vpjoxb6l"
path="res://.godot/imported/ambient.ogg-35a37efc4b30706a227e17f0453e3a99.oggvorbisstr"
[deps]
source_file="res://assets/ambient.ogg"
dest_files=["res://.godot/imported/ambient.ogg-35a37efc4b30706a227e17f0453e3a99.oggvorbisstr"]
[params]
loop=false
loop_offset=0
bpm=0
beat_count=0
bar_beats=4
+20857
View File
File diff suppressed because it is too large Load Diff
+25
View File
@@ -0,0 +1,25 @@
[remap]
importer="wavefront_obj"
importer_version=1
type="Mesh"
uid="uid://caurrbclp30ly"
path="res://.godot/imported/armor.obj-af01c4b492188328bde6fd5b9ed2eed0.mesh"
[deps]
files=["res://.godot/imported/armor.obj-af01c4b492188328bde6fd5b9ed2eed0.mesh"]
source_file="res://assets/armor.obj"
dest_files=["res://.godot/imported/armor.obj-af01c4b492188328bde6fd5b9ed2eed0.mesh", "res://.godot/imported/armor.obj-af01c4b492188328bde6fd5b9ed2eed0.mesh"]
[params]
generate_tangents=true
generate_lods=true
generate_shadow_mesh=true
generate_lightmap_uv2=false
generate_lightmap_uv2_texel_size=0.2
scale_mesh=Vector3(1, 1, 1)
offset_mesh=Vector3(0, 0, 0)
force_disable_mesh_compression=false
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

+40
View File
@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://w5fnj0g3j6ms"
path="res://.godot/imported/armor.png-7969b140c50e154aedeaeb60a071ac9b.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/armor.png"
dest_files=["res://.godot/imported/armor.png-7969b140c50e154aedeaeb60a071ac9b.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
BIN
View File
Binary file not shown.
@@ -3,13 +3,13 @@
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://b3xjq4m8fhonq"
path="res://.godot/imported/player_man.glb-c09ea8d824dd49bf945f1e4f9dbd3bba.scn"
uid="uid://cniw0ypfvjw61"
path="res://.godot/imported/boot.glb-d1c29f9ff7f48815266f56a7be3dd896.scn"
[deps]
source_file="res://assets/player_man.glb"
dest_files=["res://.godot/imported/player_man.glb-c09ea8d824dd49bf945f1e4f9dbd3bba.scn"]
source_file="res://assets/boot.glb"
dest_files=["res://.godot/imported/boot.glb-d1c29f9ff7f48815266f56a7be3dd896.scn"]
[params]
+18661
View File
File diff suppressed because it is too large Load Diff
+25
View File
@@ -0,0 +1,25 @@
[remap]
importer="wavefront_obj"
importer_version=1
type="Mesh"
uid="uid://jls6i8ov73ld"
path="res://.godot/imported/boot.obj-e334fc0955e7dcb45c6e02ac806a59e8.mesh"
[deps]
files=["res://.godot/imported/boot.obj-e334fc0955e7dcb45c6e02ac806a59e8.mesh"]
source_file="res://assets/boot.obj"
dest_files=["res://.godot/imported/boot.obj-e334fc0955e7dcb45c6e02ac806a59e8.mesh", "res://.godot/imported/boot.obj-e334fc0955e7dcb45c6e02ac806a59e8.mesh"]
[params]
generate_tangents=true
generate_lods=true
generate_shadow_mesh=true
generate_lightmap_uv2=false
generate_lightmap_uv2_texel_size=0.2
scale_mesh=Vector3(1, 1, 1)
offset_mesh=Vector3(0, 0, 0)
force_disable_mesh_compression=false
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

+41
View File
@@ -0,0 +1,41 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b85nk7r6dkenp"
path.s3tc="res://.godot/imported/boot1.png-351fe0276d90e80dc572c41c781fc909.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://assets/boot1.png"
dest_files=["res://.godot/imported/boot1.png-351fe0276d90e80dc572c41c781fc909.s3tc.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

+41
View File
@@ -0,0 +1,41 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ce4g8nblils0e"
path.s3tc="res://.godot/imported/boot2.png-a3406216bcaf3ad03e199064a129c36e.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://assets/boot2.png"
dest_files=["res://.godot/imported/boot2.png-a3406216bcaf3ad03e199064a129c36e.s3tc.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

+41
View File
@@ -0,0 +1,41 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bqpntq4rf2q7s"
path.s3tc="res://.godot/imported/boot3.png-d7aa5373b9b2c6ad231646d4daea89b4.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://assets/boot3.png"
dest_files=["res://.godot/imported/boot3.png-d7aa5373b9b2c6ad231646d4daea89b4.s3tc.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0
Binary file not shown.
+42
View File
@@ -0,0 +1,42 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://82lpmyibj8tp"
path="res://.godot/imported/boot_walk.glb-d86cd37ca982d86b2ebd647af9a26482.scn"
[deps]
source_file="res://assets/boot_walk.glb"
dest_files=["res://.godot/imported/boot_walk.glb-d86cd37ca982d86b2ebd647af9a26482.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
nodes/use_name_suffixes=true
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
materials/extract=0
materials/extract_format=0
materials/extract_path=""
_subresources={}
gltf/naming_version=2
gltf/embedded_image_handling=1
BIN
View File
Binary file not shown.
+19
View File
@@ -0,0 +1,19 @@
[remap]
importer="oggvorbisstr"
type="AudioStreamOggVorbis"
uid="uid://c743vb62pekwt"
path="res://.godot/imported/damage.ogg-137ecbb71d5ea483a0892197341e95d9.oggvorbisstr"
[deps]
source_file="res://assets/damage.ogg"
dest_files=["res://.godot/imported/damage.ogg-137ecbb71d5ea483a0892197341e95d9.oggvorbisstr"]
[params]
loop=false
loop_offset=0
bpm=0
beat_count=0
bar_beats=4
BIN
View File
Binary file not shown.
+42
View File
@@ -0,0 +1,42 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://bpmi0k5uuwef4"
path="res://.godot/imported/gnome1.glb-48274b613f374ee33041724d50181ae2.scn"
[deps]
source_file="res://assets/gnome1.glb"
dest_files=["res://.godot/imported/gnome1.glb-48274b613f374ee33041724d50181ae2.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
nodes/use_name_suffixes=true
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
materials/extract=0
materials/extract_format=0
materials/extract_path=""
_subresources={}
gltf/naming_version=2
gltf/embedded_image_handling=1
BIN
View File
Binary file not shown.
+42
View File
@@ -0,0 +1,42 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://cqtr8862yg1pw"
path="res://.godot/imported/gnome2.glb-ed506cf1ac0ccb2d264457e28d22df82.scn"
[deps]
source_file="res://assets/gnome2.glb"
dest_files=["res://.godot/imported/gnome2.glb-ed506cf1ac0ccb2d264457e28d22df82.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
nodes/use_name_suffixes=true
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
materials/extract=0
materials/extract_format=0
materials/extract_path=""
_subresources={}
gltf/naming_version=2
gltf/embedded_image_handling=1
BIN
View File
Binary file not shown.
+42
View File
@@ -0,0 +1,42 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://d38xq7m2ov1ig"
path="res://.godot/imported/gnome3.glb-60a565f65ec090ccf38c4f1b4928e113.scn"
[deps]
source_file="res://assets/gnome3.glb"
dest_files=["res://.godot/imported/gnome3.glb-60a565f65ec090ccf38c4f1b4928e113.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
nodes/use_name_suffixes=true
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
materials/extract=0
materials/extract_format=0
materials/extract_path=""
_subresources={}
gltf/naming_version=2
gltf/embedded_image_handling=1
Binary file not shown.
@@ -0,0 +1,19 @@
[remap]
importer="oggvorbisstr"
type="AudioStreamOggVorbis"
uid="uid://d0ygls7mtp1q1"
path="res://.godot/imported/growling-cartoon-animal-in-the-game.ogg-f3dde05a2449a5cb1bbbeaf8a5c195ca.oggvorbisstr"
[deps]
source_file="res://assets/growling-cartoon-animal-in-the-game.ogg"
dest_files=["res://.godot/imported/growling-cartoon-animal-in-the-game.ogg-f3dde05a2449a5cb1bbbeaf8a5c195ca.oggvorbisstr"]
[params]
loop=false
loop_offset=0
bpm=0
beat_count=0
bar_beats=4
Binary file not shown.
+19
View File
@@ -0,0 +1,19 @@
[remap]
importer="oggvorbisstr"
type="AudioStreamOggVorbis"
uid="uid://bqj5f858tqy5w"
path="res://.godot/imported/kick_enemy.ogg-47fb08fccd1ea50bf15fb26d6abda71e.oggvorbisstr"
[deps]
source_file="res://assets/kick_enemy.ogg"
dest_files=["res://.godot/imported/kick_enemy.ogg-47fb08fccd1ea50bf15fb26d6abda71e.oggvorbisstr"]
[params]
loop=false
loop_offset=0
bpm=0
beat_count=0
bar_beats=4
Binary file not shown.
+19
View File
@@ -0,0 +1,19 @@
[remap]
importer="oggvorbisstr"
type="AudioStreamOggVorbis"
uid="uid://cq4hup0lwti13"
path="res://.godot/imported/kick_player.ogg-ed43ff774ec5730f331b64274b81fa27.oggvorbisstr"
[deps]
source_file="res://assets/kick_player.ogg"
dest_files=["res://.godot/imported/kick_player.ogg-ed43ff774ec5730f331b64274b81fa27.oggvorbisstr"]
[params]
loop=true
loop_offset=12.0
bpm=0.0
beat_count=0
bar_beats=4
BIN
View File
Binary file not shown.
+19
View File
@@ -0,0 +1,19 @@
[remap]
importer="oggvorbisstr"
type="AudioStreamOggVorbis"
uid="uid://djmceowwiaxh"
path="res://.godot/imported/merge.ogg-23e958ec7fe7428616d58e4721608c5d.oggvorbisstr"
[deps]
source_file="res://assets/merge.ogg"
dest_files=["res://.godot/imported/merge.ogg-23e958ec7fe7428616d58e4721608c5d.oggvorbisstr"]
[params]
loop=false
loop_offset=0
bpm=0
beat_count=0
bar_beats=4
File diff suppressed because it is too large Load Diff
-25
View File
@@ -1,25 +0,0 @@
[remap]
importer="wavefront_obj"
importer_version=1
type="Mesh"
uid="uid://b3m2872sdp3ep"
path="res://.godot/imported/stick.obj-4b867b5d040e587c60e2778589aa0361.mesh"
[deps]
files=["res://.godot/imported/stick.obj-4b867b5d040e587c60e2778589aa0361.mesh"]
source_file="res://assets/meshes/stick.obj"
dest_files=["res://.godot/imported/stick.obj-4b867b5d040e587c60e2778589aa0361.mesh", "res://.godot/imported/stick.obj-4b867b5d040e587c60e2778589aa0361.mesh"]
[params]
generate_tangents=true
generate_lods=true
generate_shadow_mesh=true
generate_lightmap_uv2=false
generate_lightmap_uv2_texel_size=0.2
scale_mesh=Vector3(1, 1, 1)
offset_mesh=Vector3(0, 0, 0)
force_disable_mesh_compression=false
+206
View File
@@ -0,0 +1,206 @@
# Blender 4.2.9 LTS
# www.blender.org
o metal_item
v -0.000455 0.025430 0.375746
v -0.019059 0.025407 0.394395
v -0.011318 0.009290 0.383589
v -0.075059 0.208979 0.300395
v -0.099042 0.225119 0.294986
v -0.093682 0.209002 0.319026
v -0.361011 0.009290 0.383589
v -0.353269 0.025407 0.394395
v -0.371873 0.025430 0.375746
v -0.297269 0.208979 0.300395
v -0.278646 0.209002 0.319026
v -0.273286 0.225119 0.294986
v -0.000455 0.025430 -0.378701
v -0.011318 0.009290 -0.386544
v -0.019059 0.025407 -0.397351
v -0.075059 0.208979 -0.303350
v -0.093682 0.209002 -0.321981
v -0.099042 0.225119 -0.297942
v -0.361011 0.009290 -0.386544
v -0.371873 0.025430 -0.378701
v -0.353269 0.025407 -0.397350
v -0.297269 0.208979 -0.303350
v -0.273286 0.225119 -0.297942
v -0.278646 0.209002 -0.321981
v 0.374544 0.025430 0.375746
v 0.355940 0.025407 0.394395
v 0.363682 0.009290 0.383589
v 0.299940 0.208979 0.300395
v 0.275957 0.225119 0.294986
v 0.281317 0.209002 0.319026
v 0.013989 0.009290 0.383589
v 0.021730 0.025407 0.394395
v 0.003126 0.025430 0.375746
v 0.077730 0.208979 0.300395
v 0.096353 0.209002 0.319026
v 0.101713 0.225119 0.294986
v 0.374544 0.025430 -0.378701
v 0.363682 0.009290 -0.386544
v 0.355940 0.025407 -0.397351
v 0.299940 0.208979 -0.303350
v 0.281317 0.209002 -0.321981
v 0.275957 0.225119 -0.297942
v 0.013989 0.009290 -0.386544
v 0.003126 0.025430 -0.378701
v 0.021730 0.025407 -0.397350
v 0.077730 0.208979 -0.303350
v 0.101713 0.225119 -0.297942
v 0.096353 0.209002 -0.321981
v 0.182543 0.234038 0.301050
v 0.163938 0.234015 0.316007
v 0.171680 0.217897 0.307340
v 0.107939 0.417586 0.240620
v 0.083956 0.433727 0.236282
v 0.089316 0.417609 0.255561
v -0.178013 0.217897 0.307340
v -0.170271 0.234015 0.316007
v -0.188875 0.234038 0.301050
v -0.114271 0.417586 0.240620
v -0.095648 0.417609 0.255561
v -0.090288 0.433727 0.236282
v 0.182543 0.234038 -0.304005
v 0.171680 0.217897 -0.310296
v 0.163938 0.234015 -0.318962
v 0.107939 0.417586 -0.243575
v 0.089316 0.417609 -0.258517
v 0.083956 0.433727 -0.239238
v -0.178013 0.217897 -0.310296
v -0.188875 0.234038 -0.304005
v -0.170271 0.234015 -0.318962
v -0.114271 0.417586 -0.243575
v -0.090288 0.433727 -0.239238
v -0.095648 0.417609 -0.258517
vn -0.0000 -1.0000 -0.0001
vn 0.0001 -1.0000 -0.0000
vn -0.0000 -1.0000 0.0001
vn -0.0001 -1.0000 -0.0000
vn -0.0000 1.0000 -0.0000
vn -0.0000 1.0000 0.0001
vn -0.0000 1.0000 -0.0001
vn -0.0000 0.3798 -0.9251
vn -0.0000 0.3797 -0.9251
vn -0.0000 0.3798 0.9251
vn -0.0000 0.3797 0.9251
vn -0.9264 0.3766 -0.0000
vn -0.9264 0.3765 -0.0000
vn 0.9390 0.0074 0.3439
vn 0.7239 0.6390 0.2600
vn 0.9390 0.0074 -0.3439
vn 0.7239 0.6390 -0.2600
vn -0.9390 0.0074 0.3439
vn -0.7239 0.6390 0.2600
vn -0.7239 0.6390 -0.2600
vn -0.9390 0.0074 -0.3439
vn 0.9264 0.3766 -0.0000
vn -0.0000 -1.0000 -0.0000
vn -0.0000 0.3127 -0.9499
vn -0.0000 0.3128 -0.9498
vn -0.0000 0.3127 0.9499
vn -0.0000 0.3128 0.9498
vn -0.9264 0.3765 0.0001
vn -0.9264 0.3766 -0.0001
vn 0.9264 0.3765 -0.0000
vt 0.734770 0.428017
vt 0.734335 0.435070
vt 0.734335 0.435070
vt 0.726011 0.434850
vt 0.726420 0.428380
vt 0.726420 0.428380
vt 0.726011 0.434850
vt 0.733716 0.435018
vt 0.726630 0.434915
vt 0.727047 0.428304
vt 0.734145 0.428079
vt 0.733716 0.435018
vt 0.734144 0.428079
vt 0.726630 0.434915
vt 0.733690 0.435427
vt 0.726594 0.435491
vt 0.726594 0.435491
vt 0.733690 0.435427
vt 0.734169 0.427670
vt 0.727084 0.427728
vt 0.734169 0.427670
vt 0.727084 0.427728
s 1
f 3/1/1 7/2/2 19/3/3 14/1/4
f 12/4/5 5/5/6 18/6/5 23/7/7
f 21/8/8 24/9/8 17/10/9 15/11/8
f 8/12/10 2/13/10 6/10/10 11/14/11
f 9/15/12 10/16/13 22/17/13 20/18/12
f 1/19/14 2/13/10 3/1/1
f 4/20/15 5/5/6 6/10/10
f 7/2/2 8/12/10 9/15/12
f 10/16/13 11/14/11 12/4/5
f 13/21/16 14/1/4 15/11/8
f 16/22/17 17/10/9 18/6/5
f 19/3/3 20/18/12 21/8/8
f 22/17/13 23/7/7 24/9/8
f 1/19/14 4/20/15 6/10/10 2/13/10
f 7/2/2 3/1/1 2/13/10 8/12/10
f 10/16/13 9/15/12 8/12/10 11/14/11
f 11/14/11 6/10/10 5/5/6 12/4/5
f 15/11/8 17/10/9 16/22/17 13/21/16
f 21/8/8 15/11/8 14/1/4 19/3/3
f 24/9/8 21/8/8 20/18/12 22/17/13
f 23/7/7 18/6/5 17/10/9 24/9/8
f 9/15/12 20/18/12 19/3/3 7/2/2
f 13/21/16 1/19/14 3/1/1 14/1/4
f 12/4/5 23/7/7 22/17/13 10/16/13
f 18/6/5 5/5/6 4/20/15 16/22/17
f 4/20/15 1/19/14 13/21/16 16/22/17
f 27/1/1 31/2/2 43/3/3 38/1/4
f 36/4/5 29/5/6 42/6/5 47/7/7
f 45/8/8 48/9/8 41/10/9 39/11/8
f 32/12/10 26/13/10 30/10/10 35/14/11
f 33/15/18 34/16/19 46/17/20 44/18/21
f 25/19/22 26/13/10 27/1/1
f 28/20/22 29/5/6 30/10/10
f 31/2/2 32/12/10 33/15/18
f 34/16/19 35/14/11 36/4/5
f 37/21/22 38/1/4 39/11/8
f 40/22/22 41/10/9 42/6/5
f 43/3/3 44/18/21 45/8/8
f 46/17/20 47/7/7 48/9/8
f 25/19/22 28/20/22 30/10/10 26/13/10
f 31/2/2 27/1/1 26/13/10 32/12/10
f 34/16/19 33/15/18 32/12/10 35/14/11
f 35/14/11 30/10/10 29/5/6 36/4/5
f 39/11/8 41/10/9 40/22/22 37/21/22
f 45/8/8 39/11/8 38/1/4 43/3/3
f 48/9/8 45/8/8 44/18/21 46/17/20
f 47/7/7 42/6/5 41/10/9 48/9/8
f 33/15/18 44/18/21 43/3/3 31/2/2
f 37/21/22 25/19/22 27/1/1 38/1/4
f 36/4/5 47/7/7 46/17/20 34/16/19
f 42/6/5 29/5/6 28/20/22 40/22/22
f 28/20/22 25/19/22 37/21/22 40/22/22
f 51/1/23 55/2/2 67/3/23 62/1/4
f 60/4/5 53/5/6 66/6/5 71/7/7
f 69/8/24 72/9/25 65/10/25 63/11/24
f 56/12/26 50/13/26 54/10/27 59/14/27
f 57/15/13 58/16/28 70/17/12 68/18/29
f 49/19/30 50/13/26 51/1/23
f 52/20/22 53/5/6 54/10/27
f 55/2/2 56/12/26 57/15/13
f 58/16/28 59/14/27 60/4/5
f 61/21/22 62/1/4 63/11/24
f 64/22/22 65/10/25 66/6/5
f 67/3/23 68/18/29 69/8/24
f 70/17/12 71/7/7 72/9/25
f 49/19/30 52/20/22 54/10/27 50/13/26
f 55/2/2 51/1/23 50/13/26 56/12/26
f 58/16/28 57/15/13 56/12/26 59/14/27
f 59/14/27 54/10/27 53/5/6 60/4/5
f 63/11/24 65/10/25 64/22/22 61/21/22
f 69/8/24 63/11/24 62/1/4 67/3/23
f 72/9/25 69/8/24 68/18/29 70/17/12
f 71/7/7 66/6/5 65/10/25 72/9/25
f 57/15/13 68/18/29 67/3/23 55/2/2
f 61/21/22 49/19/30 51/1/23 62/1/4
f 60/4/5 71/7/7 70/17/12 58/16/28
f 66/6/5 53/5/6 52/20/22 64/22/22
f 52/20/22 49/19/30 61/21/22 64/22/22
+25
View File
@@ -0,0 +1,25 @@
[remap]
importer="wavefront_obj"
importer_version=1
type="Mesh"
uid="uid://2r4vjjli71xm"
path="res://.godot/imported/metal_item.obj-a4cb4f3f6e92689b191537ec00614f65.mesh"
[deps]
files=["res://.godot/imported/metal_item.obj-a4cb4f3f6e92689b191537ec00614f65.mesh"]
source_file="res://assets/metal_item.obj"
dest_files=["res://.godot/imported/metal_item.obj-a4cb4f3f6e92689b191537ec00614f65.mesh", "res://.godot/imported/metal_item.obj-a4cb4f3f6e92689b191537ec00614f65.mesh"]
[params]
generate_tangents=true
generate_lods=true
generate_shadow_mesh=true
generate_lightmap_uv2=false
generate_lightmap_uv2_texel_size=0.2
scale_mesh=Vector3(1, 1, 1)
offset_mesh=Vector3(0, 0, 0)
force_disable_mesh_compression=false
Binary file not shown.
+42
View File
@@ -0,0 +1,42 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://cx7dvk0afwj6h"
path="res://.godot/imported/player_man_walk.glb-3657f9b02230b13d6d797514cd5d2eb0.scn"
[deps]
source_file="res://assets/player_man_walk.glb"
dest_files=["res://.godot/imported/player_man_walk.glb-3657f9b02230b13d6d797514cd5d2eb0.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
nodes/use_name_suffixes=true
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
materials/extract=0
materials/extract_format=0
materials/extract_path=""
_subresources={}
gltf/naming_version=2
gltf/embedded_image_handling=1
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

+40
View File
@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://baavv8uqo25la"
path="res://.godot/imported/studio_logo.png-f3d319855b8a77cbfc974454f8f0d5d5.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/studio_logo.png"
dest_files=["res://.godot/imported/studio_logo.png-f3d319855b8a77cbfc974454f8f0d5d5.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
-12548
View File
File diff suppressed because it is too large Load Diff
-25
View File
@@ -1,25 +0,0 @@
[remap]
importer="wavefront_obj"
importer_version=1
type="Mesh"
uid="uid://dnm1mgo7pkojl"
path="res://.godot/imported/temp.obj-bd08f73c102326544e2e3889f01d337d.mesh"
[deps]
files=["res://.godot/imported/temp.obj-bd08f73c102326544e2e3889f01d337d.mesh"]
source_file="res://assets/temp.obj"
dest_files=["res://.godot/imported/temp.obj-bd08f73c102326544e2e3889f01d337d.mesh", "res://.godot/imported/temp.obj-bd08f73c102326544e2e3889f01d337d.mesh"]
[params]
generate_tangents=true
generate_lods=true
generate_shadow_mesh=true
generate_lightmap_uv2=false
generate_lightmap_uv2_texel_size=0.2
scale_mesh=Vector3(1, 1, 1)
offset_mesh=Vector3(0, 0, 0)
force_disable_mesh_compression=false
+71
View File
@@ -0,0 +1,71 @@
[preset.0]
name="Windows Desktop"
platform="Windows Desktop"
runnable=true
dedicated_server=false
custom_features=""
export_filter="all_resources"
include_filter="*jpeg"
exclude_filter=""
export_path="../Kick/CraftKick.exe"
patches=PackedStringArray()
patch_delta_encoding=false
patch_delta_compression_level_zstd=19
patch_delta_min_reduction=0.1
patch_delta_include_filters="*"
patch_delta_exclude_filters=""
encryption_include_filters=""
encryption_exclude_filters=""
seed=0
encrypt_pck=false
encrypt_directory=false
script_export_mode=2
[preset.0.options]
custom_template/debug=""
custom_template/release=""
debug/export_console_wrapper=1
binary_format/embed_pck=false
texture_format/s3tc_bptc=true
texture_format/etc2_astc=false
shader_baker/enabled=false
binary_format/architecture="x86_64"
codesign/enable=false
codesign/timestamp=true
codesign/timestamp_server_url=""
codesign/digest_algorithm=1
codesign/description=""
codesign/custom_options=PackedStringArray()
application/modify_resources=true
application/icon=""
application/console_wrapper_icon=""
application/icon_interpolation=4
application/file_version=""
application/product_version=""
application/company_name=""
application/product_name=""
application/file_description=""
application/copyright=""
application/trademarks=""
application/export_angle=0
application/export_d3d12=0
application/d3d12_agility_sdk_multiarch=true
ssh_remote_deploy/enabled=false
ssh_remote_deploy/host="user@host_ip"
ssh_remote_deploy/port="22"
ssh_remote_deploy/extra_args_ssh=""
ssh_remote_deploy/extra_args_scp=""
ssh_remote_deploy/run_script="Expand-Archive -LiteralPath '{temp_dir}\\{archive_name}' -DestinationPath '{temp_dir}'
$action = New-ScheduledTaskAction -Execute '{temp_dir}\\{exe_name}' -Argument '{cmd_args}'
$trigger = New-ScheduledTaskTrigger -Once -At 00:00
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries
$task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings
Register-ScheduledTask godot_remote_debug -InputObject $task -Force:$true
Start-ScheduledTask -TaskName godot_remote_debug
while (Get-ScheduledTask -TaskName godot_remote_debug | ? State -eq running) { Start-Sleep -Milliseconds 100 }
Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue"
ssh_remote_deploy/cleanup_script="Stop-ScheduledTask -TaskName godot_remote_debug -ErrorAction:SilentlyContinue
Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue
Remove-Item -Recurse -Force '{temp_dir}'"
+12 -15
View File
@@ -1,29 +1,26 @@
[gd_scene format=3 uid="uid://cayybawvw26cm"]
[ext_resource type="Script" path="res://scripts/EnchantedSphere.gd" id="1_sphere"]
[sub_resource type="SphereMesh" id="SphereMesh_1"]
radius = 0.28
height = 0.56
[ext_resource type="Script" uid="uid://c4d11cs4fcqib" path="res://scripts/EnchantedSphere.gd" id="1_sphere"]
[ext_resource type="Texture2D" uid="uid://bqpntq4rf2q7s" path="res://assets/boot3.png" id="2_gp14g"]
[ext_resource type="ArrayMesh" uid="uid://jls6i8ov73ld" path="res://assets/boot.obj" id="3_d6vog"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_1"]
albedo_color = Color(0.8, 0.3, 1.0, 1)
albedo_texture = ExtResource("2_gp14g")
emission_enabled = true
emission = Color(0.6, 0.1, 1.0, 1)
emission = Color(0.6, 0.1, 1, 1)
emission_energy_multiplier = 3.0
[node name="EnchantedSphere" type="Node3D"]
[node name="EnchantedSphere" type="Node3D" unique_id=879211768]
script = ExtResource("1_sphere")
[node name="SphereMesh" type="MeshInstance3D" parent="."]
mesh = SubResource("SphereMesh_1")
[node name="SphereMesh" type="MeshInstance3D" parent="." unique_id=905498826]
material_override = SubResource("StandardMaterial3D_1")
mesh = ExtResource("3_d6vog")
[node name="Tooltip" type="Label3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.1, 0)
[node name="Tooltip" type="Label3D" parent="." unique_id=947504755]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.3280884, 0)
billboard = 1
double_sided = true
text = "[E] Enchanted Sphere
text = "[E] Enchanted Boots
+1 Tier"
font_size = 32
font_size = 56
outline_size = 6
+183 -21
View File
File diff suppressed because one or more lines are too long
+3 -5
View File
@@ -1,6 +1,7 @@
[gd_scene format=3 uid="uid://g7iron5etp8u"]
[ext_resource type="Script" uid="uid://0wdmbocpe2ir" path="res://scripts/Iron.gd" id="1_iron"]
[ext_resource type="ArrayMesh" uid="uid://2r4vjjli71xm" path="res://assets/metal_item.obj" id="2_53umh"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_1"]
albedo_color = Color(0.55, 0.58, 0.62, 1)
@@ -8,9 +9,6 @@ metallic = 0.7
metallic_specular = 0.8
roughness = 0.4
[sub_resource type="BoxMesh" id="BoxMesh_1"]
size = Vector3(0.38, 0.22, 0.5)
[sub_resource type="BoxShape3D" id="BoxShape3D_1"]
size = Vector3(1.3992603, 0.58835024, 0.49035645)
@@ -18,9 +16,9 @@ size = Vector3(1.3992603, 0.58835024, 0.49035645)
script = ExtResource("1_iron")
[node name="IronMesh" type="MeshInstance3D" parent="." unique_id=1832879739]
transform = Transform3D(3.5611715, 0, 0, 0, 2.7614622, 0, 0, 0, 1, 0, 0.2, 0)
transform = Transform3D(1.8825685, 0, 0, 0, 1.0460571, 0, 0, 0, 0.64741147, 0, -0.0042432398, 0)
material_override = SubResource("StandardMaterial3D_1")
mesh = SubResource("BoxMesh_1")
mesh = ExtResource("2_53umh")
[node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=665808333]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.00068727136, 0.22091705, -0.0048217773)
+2 -4
View File
@@ -1,14 +1,12 @@
[gd_scene format=3 uid="uid://d4leath8bvq2r"]
[ext_resource type="Script" uid="uid://dndcs6xc7m08x" path="res://scripts/Leather.gd" id="1_leather"]
[ext_resource type="ArrayMesh" uid="uid://cjrhycju6l7v6" path="res://assets/leather.obj" id="2_b7gx8"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_1"]
albedo_color = Color(0.62, 0.38, 0.2, 1)
roughness = 0.85
[sub_resource type="BoxMesh" id="BoxMesh_1"]
size = Vector3(0.5, 0.06, 0.35)
[sub_resource type="BoxShape3D" id="BoxShape3D_1"]
size = Vector3(0.7527008, 0.108486325, 0.6336487)
@@ -18,7 +16,7 @@ script = ExtResource("1_leather")
[node name="LeatherMesh" type="MeshInstance3D" parent="." unique_id=2045837180]
transform = Transform3D(1.5, 0, 0, 0, 1.812, 0, 0, 0, 1.784, 0, 0.12694196, 0)
material_override = SubResource("StandardMaterial3D_1")
mesh = SubResource("BoxMesh_1")
mesh = ExtResource("2_b7gx8")
[node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=1940111930]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.00071039796, 0.12997423, 0.0029245168)
+9 -11
View File
@@ -1,26 +1,24 @@
[gd_scene format=3 uid="uid://bidrinpjiyb2x"]
[ext_resource type="Script" path="res://scripts/LeatherArmor.gd" id="1_leatha"]
[sub_resource type="BoxMesh" id="BoxMesh_1"]
size = Vector3(0.5, 0.6, 0.22)
[ext_resource type="Script" uid="uid://b80k2b1icwlbm" path="res://scripts/LeatherArmor.gd" id="1_leatha"]
[ext_resource type="ArrayMesh" uid="uid://caurrbclp30ly" path="res://assets/armor.obj" id="2_dji1h"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_1"]
albedo_color = Color(0.55, 0.32, 0.14, 1)
roughness = 0.8
[node name="LeatherArmor" type="Node3D"]
[node name="LeatherArmor" type="Node3D" unique_id=1218398814]
script = ExtResource("1_leatha")
[node name="ArmorMesh" type="MeshInstance3D" parent="."]
mesh = SubResource("BoxMesh_1")
[node name="ArmorMesh" type="MeshInstance3D" parent="." unique_id=1757935253]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.3858314, 0)
material_override = SubResource("StandardMaterial3D_1")
mesh = ExtResource("2_dji1h")
[node name="Tooltip" type="Label3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.0, 0)
[node name="Tooltip" type="Label3D" parent="." unique_id=1322485403]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.7649657, 0)
billboard = 1
double_sided = true
text = "[E] Leather Armor
+1 Toughness"
font_size = 32
font_size = 56
outline_size = 6
+10 -12
View File
@@ -1,27 +1,25 @@
[gd_scene format=3 uid="uid://cbvs3rvwslsd2"]
[ext_resource type="Script" path="res://scripts/LeatherBoots.gd" id="1_boots"]
[sub_resource type="BoxMesh" id="BoxMesh_1"]
size = Vector3(0.4, 0.2, 0.55)
[ext_resource type="Script" uid="uid://d0j8nw7eynmk8" path="res://scripts/LeatherBoots.gd" id="1_boots"]
[ext_resource type="Texture2D" uid="uid://b85nk7r6dkenp" path="res://assets/boot1.png" id="2_ky34n"]
[ext_resource type="ArrayMesh" uid="uid://jls6i8ov73ld" path="res://assets/boot.obj" id="3_7iwdw"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_1"]
albedo_color = Color(0.45, 0.25, 0.10, 1)
roughness = 0.8
albedo_color = Color(0.45, 0.25, 0.1, 1)
albedo_texture = ExtResource("2_ky34n")
metallic = 0.1
roughness = 0.8
[node name="LeatherBoots" type="Node3D"]
[node name="LeatherBoots" type="Node3D" unique_id=2009442467]
script = ExtResource("1_boots")
[node name="BootsMesh" type="MeshInstance3D" parent="."]
mesh = SubResource("BoxMesh_1")
[node name="BootsMesh" type="MeshInstance3D" parent="." unique_id=1801555312]
material_override = SubResource("StandardMaterial3D_1")
mesh = ExtResource("3_7iwdw")
[node name="Tooltip" type="Label3D" parent="."]
[node name="Tooltip" type="Label3D" parent="." unique_id=1833908896]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.8, 0)
billboard = 1
double_sided = true
text = "[E] Leather Boots
+10 Move Speed"
font_size = 32
outline_size = 6
+5 -3
View File
@@ -1,8 +1,10 @@
[gd_scene format=3 uid="uid://mainmenu2024"]
[gd_scene format=3 uid="uid://jgfauchpwiii"]
[ext_resource type="Script" path="res://scripts/MainMenu.gd" id="1_menu"]
[ext_resource type="Script" uid="uid://on1o20vpycgm" path="res://scripts/MainMenu.gd" id="1_menu"]
[node name="MainMenu" type="Control"]
[node name="MainMenu" type="Control" unique_id=495626975]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
script = ExtResource("1_menu")
+13 -13
View File
@@ -1,28 +1,28 @@
[gd_scene format=3 uid="uid://h8armor4fura"]
[ext_resource type="Script" path="res://scripts/MetalArmor.gd" id="1_armor"]
[sub_resource type="BoxMesh" id="BoxMesh_1"]
size = Vector3(0.55, 0.7, 0.25)
[ext_resource type="Script" uid="uid://cqp1ucyvnno7i" path="res://scripts/MetalArmor.gd" id="1_armor"]
[ext_resource type="Texture2D" uid="uid://ce4g8nblils0e" path="res://assets/boot2.png" id="2_ocond"]
[ext_resource type="ArrayMesh" uid="uid://caurrbclp30ly" path="res://assets/armor.obj" id="3_ocond"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_1"]
albedo_color = Color(0.55, 0.60, 0.68, 1)
roughness = 0.3
albedo_color = Color(0.55, 0.6, 0.68, 1)
albedo_texture = ExtResource("2_ocond")
metallic = 0.85
metallic_specular = 1.0
roughness = 0.3
[node name="MetalArmor" type="Node3D"]
[node name="MetalArmor" type="Node3D" unique_id=1379243712]
script = ExtResource("1_armor")
[node name="ArmorMesh" type="MeshInstance3D" parent="."]
mesh = SubResource("BoxMesh_1")
[node name="ArmorMesh" type="MeshInstance3D" parent="." unique_id=1340618559]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.3499111, 0)
material_override = SubResource("StandardMaterial3D_1")
mesh = ExtResource("3_ocond")
[node name="Tooltip" type="Label3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.0, 0)
[node name="Tooltip" type="Label3D" parent="." unique_id=748491675]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.9431921, 0)
billboard = 1
double_sided = true
text = "[E] Metal Armor
+1 Tier"
font_size = 32
font_size = 56
outline_size = 6
+8 -7
View File
@@ -1,16 +1,16 @@
[gd_scene format=3 uid="uid://dbvt3pkrej5nq"]
[ext_resource type="Script" uid="uid://sfq4iq0btm0g" path="res://scripts/MetalPlate.gd" id="1_plate"]
[ext_resource type="Texture2D" uid="uid://ce4g8nblils0e" path="res://assets/boot2.png" id="2_quvug"]
[ext_resource type="ArrayMesh" uid="uid://jls6i8ov73ld" path="res://assets/boot.obj" id="3_2i44a"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_1"]
albedo_color = Color(0.6, 0.65, 0.72, 1)
albedo_texture = ExtResource("2_quvug")
metallic = 0.8
metallic_specular = 0.9
roughness = 0.35
[sub_resource type="BoxMesh" id="BoxMesh_1"]
size = Vector3(0.55, 0.08, 0.7)
[sub_resource type="BoxShape3D" id="BoxShape3D_1"]
size = Vector3(1.0203736, 0.124472655, 1.4775146)
@@ -20,15 +20,16 @@ script = ExtResource("1_plate")
[node name="PlateMesh" type="MeshInstance3D" parent="." unique_id=436086498]
transform = Transform3D(1.8395851, 0, 0, 0, 1.5228686, 0, 0, 0, 2.050398, 0, 0.16620824, 0)
material_override = SubResource("StandardMaterial3D_1")
mesh = SubResource("BoxMesh_1")
mesh = ExtResource("3_2i44a")
[node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=1642999883]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.005560264, 0.16739155, 0.003918484)
shape = SubResource("BoxShape3D_1")
[node name="Tooltip" type="Label3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.1, 0)
[node name="Tooltip" type="Label3D" parent="." unique_id=59052869]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.425037, 0)
billboard = 1
text = "[E] Metal Plate
text = "[E] Armored Boots
+1 Kick Tier"
font_size = 56
outline_size = 6
+186 -26
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -32,7 +32,7 @@ func _ready() -> void:
_tooltip = Label3D.new()
_tooltip.text = "Boulder\nRock+Rock\nVery heavy. High damage"
_tooltip.billboard = BaseMaterial3D.BILLBOARD_ENABLED
_tooltip.font_size = 28
_tooltip.font_size = 56
_tooltip.outline_size = 6
_tooltip.position = Vector3(0, 1.4, 0)
_tooltip.modulate = Color(1.0, 0.95, 0.8)
+60 -10
View File
@@ -45,10 +45,13 @@ var merge_partner: Node = null
var is_upgrading: bool = false
@onready var mesh_node: MeshInstance3D = $BodyMesh
#@onready var mesh_node1: MeshInstance3D = $BodyMesh1
#@onready var mesh_node2: MeshInstance3D = $BodyMesh2
@onready var mesh_node1: MeshInstance3D = $BodyMesh1
@onready var mesh_node2: MeshInstance3D = $BodyMesh2
@onready var anim_player: AnimationPlayer = $AnimationPlayer
var mat: StandardMaterial3D
var type_label: Label3D
var active_mesh: MeshInstance3D
var COLOR_CHASE = Color(1.0, 0.28, 0.18)
@@ -61,7 +64,9 @@ const AIR_FRICTION = 0.86
func _ready() -> void:
process_mode = Node.PROCESS_MODE_PAUSABLE
add_to_group("enemies")
mat = mesh_node.material_override.duplicate() as StandardMaterial3D
active_mesh = mesh_node
var orig := mesh_node.material_override
mat = (orig.duplicate() if orig != null else StandardMaterial3D.new()) as StandardMaterial3D
mesh_node.material_override = mat
#mesh_node1.set_visible(false)
#mesh_node2.set_visible(false)
@@ -89,13 +94,13 @@ func setup(type: String, wave: int) -> void:
match type:
"slime":
move_speed = 2.8 + wave * 0.12
health = 25 + wave * 4
health = 40 + wave * 4
score_value = 10
damage_to_player = 8
enemy_level = 1
"bat":
move_speed = 5 + wave * 0.15
health = 40 + wave * 2
health = 100 + wave * 2
score_value = 20
damage_to_player = 6
base_scale = 0.7
@@ -107,7 +112,7 @@ func setup(type: String, wave: int) -> void:
#mesh_node1.set_visible(true)
"ogre":
move_speed = 3 + wave * 0.08
health = 150 + wave * 12
health = 200 + wave * 12
score_value = 50
damage_to_player = 18
base_scale = 1.5
@@ -120,6 +125,38 @@ func setup(type: String, wave: int) -> void:
kick_tier = enemy_level
toughness_tier = enemy_level
_update_label()
_apply_mesh(enemy_level)
func _apply_mesh(level: int) -> void:
var idx := clampi(level, 1, 3)
var scene := load("res://assets/gnome%d.glb" % idx) as PackedScene
if scene == null:
return
var root := scene.instantiate()
var src: MeshInstance3D = null
for child in root.get_children():
var mi := child as MeshInstance3D
if mi != null:
src = mi
break
if src == null:
root.queue_free()
return
mesh_node.mesh = src.mesh
var new_mat: StandardMaterial3D
if src.get_surface_override_material(0) != null:
new_mat = src.get_surface_override_material(0).duplicate() as StandardMaterial3D
else:
new_mat = StandardMaterial3D.new()
var tex := load("res://assets/gnome%d.png" % idx) as Texture2D
if tex != null:
new_mat.albedo_texture = tex
new_mat.albedo_color = Color.WHITE
mesh_node.material_override = new_mat
root.queue_free()
mat = new_mat
COLOR_CHASE = Color.WHITE
active_mesh = mesh_node
func _physics_process(delta: float) -> void:
match state:
@@ -139,10 +176,11 @@ func _chase(delta: float) -> void:
var dist := diff.length()
if dist < 1.0 and contact_timer <= 0.0:
contact_timer = CONTACT_CD
_play_kick_blend()
if target.has_method("take_damage"):
target.take_damage(damage_to_player)
FX.hit_spark(target.global_position + Vector3(0, 0.5, 0), get_parent(), Color(0.95, 0.18, 0.08))
if randf() < 0.3:
#if randf() < 0.3:
var knock_dir := diff.normalized() if dist > 0.01 else -global_transform.basis.z
knock_dir.y = 0.0
target.call("receive_kick", knock_dir, 12.0 + kick_tier * 10.0)
@@ -185,8 +223,8 @@ func _try_enemy_kick() -> void:
var k := node as Node3D
if k == null or not is_instance_valid(k):
continue
if k.get("kickable_type") == "stick":
continue
#if k.get("kickable_type") == "stick":
#continue
var kfv = k.get("fly_vel")
if kfv != null and Vector2((kfv as Vector3).x, (kfv as Vector3).z).length() > 15.0:
continue
@@ -196,6 +234,7 @@ func _try_enemy_kick() -> void:
nearest_dist = d.length()
nearest_kickable = k
if nearest_kickable != null:
_play_kick_blend()
nearest_kickable.call("receive_kick", kick_dir, 35.0 + kick_tier * 8.0)
FX.hit_spark(nearest_kickable.global_position + Vector3(0, 0.4, 0), get_parent(), Color(1.0, 0.72, 0.1))
kickable_kick_timer = KICKABLE_KICK_COOLDOWN
@@ -217,6 +256,7 @@ func _try_enemy_kick() -> void:
nearest_enemy_dist = d.length()
nearest_enemy = en
if nearest_enemy != null:
_play_kick_blend()
nearest_enemy.call("receive_kick", kick_dir, 40.0 + kick_tier * 10.0)
enemy_kick_timer = ENEMY_KICK_COOLDOWN
return
@@ -226,7 +266,8 @@ func _try_enemy_kick() -> void:
if to_player.length() < ENEMY_KICK_RANGE:
var player_toughness: int = target.get("toughness_tier") if target.get("toughness_tier") != null else 0
if player_toughness < kick_tier:
target.call("receive_kick", kick_dir, 12.0 + kick_tier * 10.0)
_play_kick_blend()
target.call("receive_kick", kick_dir, 35.0 + kick_tier * 8.0)
FX.hit_spark(target.global_position + Vector3(0, 0.5, 0), get_parent(), Color(0.95, 0.18, 0.08))
enemy_kick_timer = ENEMY_KICK_COOLDOWN
@@ -355,6 +396,9 @@ func _enter_stun() -> void:
func _enter_chase() -> void:
state = State.CHASING
mat.albedo_color = COLOR_CHASE
mesh_node.rotation.y = 0.0
mesh_node1.rotation.y = 0.0
mesh_node2.rotation.y = 0.0
func _take_hit(dmg: int) -> void:
if state == State.DEAD:
@@ -363,6 +407,12 @@ func _take_hit(dmg: int) -> void:
if health <= 0:
_die()
func _play_kick_blend() -> void:
SFX.kick_enemy(get_parent())
if anim_player != null and anim_player.has_animation("kick"):
anim_player.stop()
anim_player.play("kick")
func _wall_impact_effect() -> void:
var tw := create_tween()
tw.tween_property(mat, "albedo_color", Color.WHITE, 0.04)
+1 -1
View File
@@ -34,7 +34,7 @@ func _ready() -> void:
_tooltip = Label3D.new()
_tooltip.text = "Magic Essence\nKick into\nEnchanting Table → Sphere"
_tooltip.billboard = BaseMaterial3D.BILLBOARD_ENABLED
_tooltip.font_size = 28
_tooltip.font_size = 56
_tooltip.outline_size = 6
_tooltip.position = Vector3(0, 1.2, 0)
_tooltip.modulate = Color(0.85, 0.7, 1.0)
+11
View File
@@ -0,0 +1,11 @@
class_name GameSettings
## "immortal" — no damage, tier-based kick force
## "survival" — takes damage, fixed kick force
static var difficulty: String = "immortal"
## enemy spawn interval in seconds
static var enemy_spawn_interval: float = 6.0
## item (rock/stick) respawn delay in seconds
static var item_respawn_delay: float = 10.0
+1
View File
@@ -0,0 +1 @@
uid://deu62njwuhjd3
+2 -2
View File
@@ -16,7 +16,7 @@ var kick_tier: int = 0
var toughness_tier: int = 2
var state: State = State.IDLE
var fly_vel: Vector3 = Vector3.ZERO
var health: float = 80.0
var health: float = 400.0
var dead: bool = false
var damage_modifier: float = 0.9
@@ -34,7 +34,7 @@ func _ready() -> void:
_tooltip = Label3D.new()
_tooltip.text = "Iron\nHeavy weapon\n+Leather → Iron Shield\nForge → Metal Plate"
_tooltip.billboard = BaseMaterial3D.BILLBOARD_ENABLED
_tooltip.font_size = 28
_tooltip.font_size = 56
_tooltip.outline_size = 6
_tooltip.position = Vector3(0, 1.1, 0)
_tooltip.modulate = Color(1.0, 0.95, 0.8)
+7
View File
@@ -52,6 +52,11 @@ static func resolve(owner: Node3D, other: Node3D, owner_vel: Vector3) -> bool:
static func _execute_recipe(a: Node3D, b: Node3D, recipe: Dictionary) -> void:
var pos := (a.global_position + b.global_position) * 0.5
var parent := a.get_parent()
# Emit before freeing so respawn counters in Main decrement correctly.
if a.has_signal("destroyed"):
a.emit_signal("destroyed")
if b.has_signal("destroyed"):
b.emit_signal("destroyed")
a.queue_free()
b.queue_free()
var scene: PackedScene = load(recipe["result_scene"])
@@ -61,3 +66,5 @@ static func _execute_recipe(a: Node3D, b: Node3D, recipe: Dictionary) -> void:
parent.add_child(result)
result.global_position = pos
FX.merge_smoke(pos + Vector3(0, 0.3, 0), parent)
SFX.merge(parent)
parent.get_tree().create_timer(30.0).connect("timeout", result.queue_free)
+1 -1
View File
@@ -21,7 +21,7 @@ func _ready() -> void:
_tooltip = Label3D.new()
_tooltip.text = "Leather\n+Stick → Boots\n+Rock → Leather Armor\n+Iron → Iron Shield"
_tooltip.billboard = BaseMaterial3D.BILLBOARD_ENABLED
_tooltip.font_size = 28
_tooltip.font_size = 56
_tooltip.outline_size = 6
_tooltip.position = Vector3(0, 1.0, 0)
_tooltip.modulate = Color(1.0, 0.95, 0.8)
-3
View File
@@ -23,6 +23,3 @@ func _process(delta: float) -> void:
func interact(player: Node) -> void:
player.call("apply_upgrade_boots", 2.0, tier)
queue_free()
var mains := get_tree().get_nodes_in_group("main")
if not mains.is_empty():
mains[0].call("show_tutorial", "Tutorial_LeatherBoots")
+489 -43
View File
@@ -10,7 +10,7 @@ const CAM_DIST := 8.0
const MOUSE_SENS := 0.18
const PITCH_MIN := 5.0
const PITCH_MAX := 70.0
const SPAWN_TIME := 10
const SPAWN_TIME := 5
var arena_size: float = 14.0
var cam_yaw: float = 0.0
@@ -47,12 +47,26 @@ var progress_bar: ColorRect
var progress_bg: ColorRect
var upgrade_panel: Panel
var gameover_panel: Panel
var pause_panel: Panel
var pause_image: TextureRect
var pause_toggle_btn: Button
var _pause_showing_craft: bool = true
# Equipment slots
var equip_fills: Array[ColorRect] = []
var equip_labels: Array[Label] = []
var _equip_prev_tiers: Array[int] = [-1, -1, -1]
# Boss phase
var boss_active: bool = false
var first_boss_spawned: bool = false
var first_bat_spawned: bool = false
var boss_timer: float = 90.0
var portal_node: Node3D = null
var boss_timer_label: Label
var boss_hint_label: Label
var win_panel: Panel
func _ready() -> void:
_spawn_level()
_create_camera()
@@ -75,11 +89,23 @@ func _input(event: InputEvent) -> void:
cam_pitch = clampf(cam_pitch, PITCH_MIN, PITCH_MAX)
if event.is_action_pressed("ui_cancel"):
if game_active and not upgrading:
_toggle_pause_menu()
else:
if Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
else:
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
if OS.is_debug_build():
var key := event as InputEventKey
if key != null and key.pressed and not key.echo:
if key.keycode == KEY_F5:
boss_active = true
_trigger_win()
elif key.keycode == KEY_F6:
_on_player_died()
# ─── Level ────────────────────────────────────────────────────────────────────
func _spawn_level() -> void:
@@ -108,17 +134,38 @@ func _process(delta: float) -> void:
var look_at_pos := player.global_position + Vector3(0, 0.8, 0)
camera.global_position = camera.global_position.lerp(look_at_pos + offset, 14.0 * delta)
camera.look_at(look_at_pos, Vector3.UP)
if Input.is_mouse_button_pressed(MOUSE_BUTTON_RIGHT):
player.set_aim_direction(deg_to_rad(cam_yaw))
_update_tier_label()
if boss_active:
boss_timer = max(0.0, boss_timer - delta)
var mins := int(boss_timer) / 60
var secs := int(boss_timer) % 60
boss_timer_label.text = "%d:%02d" % [mins, secs]
if boss_timer <= 10.0:
boss_timer_label.add_theme_color_override("font_color", Color(1.0, 0.2, 0.2))
if boss_timer <= 0.0:
_trigger_time_up()
return
if is_instance_valid(portal_node):
var area := portal_node.get_node_or_null("PortalArea") as Area3D
if area != null:
for body in area.get_overlapping_bodies():
if body.get("enemy_level") == 3:
var fv = body.get("fly_vel")
if fv != null:
var spd := Vector2((fv as Vector3).x, (fv as Vector3).z).length()
if spd >= 25.0:
_trigger_win()
return
# ─── Rocks ────────────────────────────────────────────────────────────────────
var rocks_on_field: int = 0
var rocks_pending: int = 0
func _get_rock_limit() -> int:
return mini(2 + (wave + 1) / 2, 7)
return mini(3 + (wave + 1) / 2, 7)
func _spawn_rocks() -> void:
var limit := _get_rock_limit()
@@ -127,7 +174,7 @@ func _spawn_rocks() -> void:
var sticks_on_field: int = 0
var sticks_pending: int = 0
const STICK_LIMIT := 2
const STICK_LIMIT := 3
func _spawn_sticks() -> void:
for i in range(STICK_LIMIT):
@@ -146,7 +193,8 @@ func _on_stick_destroyed() -> void:
return
if sticks_on_field + sticks_pending < STICK_LIMIT:
sticks_pending += 1
await get_tree().create_timer(20.0).timeout
await get_tree().create_timer(GameSettings.item_respawn_delay).timeout
sticks_pending -= 1
if game_active:
_spawn_single_stick()
@@ -182,7 +230,7 @@ func _on_rock_destroyed() -> void:
return
if rocks_on_field + rocks_pending < _get_rock_limit():
rocks_pending += 1
await get_tree().create_timer(20.0).timeout
await get_tree().create_timer(GameSettings.item_respawn_delay).timeout
rocks_pending -= 1
if game_active:
_spawn_single_rock()
@@ -204,6 +252,7 @@ func _spawn_player() -> void:
# ─── Game flow ────────────────────────────────────────────────────────────────
func _start_game() -> void:
SFX.start_ambient(self)
game_active = true
wave = 1
score = 0
@@ -213,7 +262,7 @@ func _start_game() -> void:
Enemy.first_iron_spawned = false
Enemy.first_essence_spawned = false
_update_labels()
spawn_timer.wait_time = 1.4
spawn_timer.wait_time = GameSettings.enemy_spawn_interval
spawn_timer.connect("timeout", _on_spawn_timer)
spawn_timer.start()
@@ -221,7 +270,7 @@ func _on_spawn_timer() -> void:
if not game_active or upgrading:
return
_spawn_enemy()
spawn_timer.wait_time = SPAWN_TIME # max(0.25, 1.4 - wave * 0.07)
spawn_timer.wait_time = GameSettings.enemy_spawn_interval
func _spawn_enemy() -> void:
var enemy := ENEMY_SCENE.instantiate() as CharacterBody3D
@@ -236,6 +285,12 @@ func _spawn_enemy() -> void:
enemy.target = player
enemy.connect("died", _on_enemy_died)
enemy.connect("merged", _on_enemy_merged)
if type == "bat" and not first_bat_spawned:
first_bat_spawned = true
show_tutorial("Tutorial_LeatherBoots")
if type == "ogre" and not first_boss_spawned:
first_boss_spawned = true
_start_boss_phase()
# Spawn at random edge
var side := randi() % 4
@@ -272,6 +327,7 @@ func _spawn_upgraded_enemy(pos: Vector3, type: String, level: int, w: int) -> Ch
enemy.kick_tier = level
enemy.toughness_tier = level
enemy.call("_update_label")
enemy.call("_apply_mesh", level)
enemy.global_position = pos
enemy.connect("died", _on_enemy_died)
enemy.connect("merged", _on_enemy_merged)
@@ -284,11 +340,9 @@ func _spawn_upgraded_enemy(pos: Vector3, type: String, level: int, w: int) -> Ch
var old_size: Vector3 = s3d.size
col_shape.shape = BoxShape3D.new()
(col_shape.shape as BoxShape3D).size = old_size * s
var color := Color(1.0, 1.0, 0.5) if level > 2 else Color(1.0, 0.9, 0.3)
tw.tween_property(enemy.mat, "albedo_color", color, 0.25)
#var bs := scale
#tw.tween_property(enemy.mesh_node, "scale", Vector3(bs * 1.6, bs * 0.25, bs * 1.6), 0.07)
#tw.tween_property(enemy.mesh_node, "scale", Vector3(bs, bs, bs), 0.22)
if level >= 3 and not first_boss_spawned:
first_boss_spawned = true
_start_boss_phase()
return enemy
func _on_enemy_merged(_upgrade: bool) -> void:
@@ -296,6 +350,12 @@ func _on_enemy_merged(_upgrade: bool) -> void:
func _on_player_died() -> void:
game_active = false
if boss_active:
boss_active = false
boss_timer_label.visible = false
boss_hint_label.visible = false
if is_instance_valid(portal_node):
portal_node.queue_free()
spawn_timer.stop()
_show_gameover()
@@ -344,14 +404,141 @@ func _pick_upgrade(id: String) -> void:
_update_labels()
func _show_gameover() -> void:
gameover_panel.visible = true
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
var lbl := gameover_panel.get_node("VBox/ScoreLabel") as Label
lbl.text = "Score: %d\nWave: %d" % [score, wave]
show_tutorial("LoseGame", func() -> void:
gameover_panel.visible = true
)
func _restart() -> void:
get_tree().paused = false
get_tree().reload_current_scene()
# ─── Boss phase ───────────────────────────────────────────────────────────────
func _start_boss_phase() -> void:
if boss_active or not game_active:
return
boss_active = true
boss_timer = 120.0
_spawn_portal()
show_tutorial("ThirdLevelEnemy", func() -> void:
boss_timer_label.visible = true
boss_hint_label.visible = true
)
func _spawn_portal() -> void:
portal_node = Node3D.new()
add_child(portal_node)
var player_pos := player.global_position if is_instance_valid(player) else Vector3.ZERO
var best_pos := Vector3(arena_size - 1.5, 0.0, 0.0)
var best_dist := 0.0
for _i in range(16):
var angle := randf() * TAU
var cand := Vector3(cos(angle), 0.0, sin(angle)) * (arena_size - 1.5)
var d := cand.distance_to(player_pos)
if d > best_dist:
best_dist = d
best_pos = cand
portal_node.global_position = best_pos
var light := OmniLight3D.new()
light.light_color = Color(0.5, 0.1, 1.0)
light.omni_range = 7.0
light.light_energy = 3.0
light.position.y = 1.0
portal_node.add_child(light)
var ring := MeshInstance3D.new()
var torus := TorusMesh.new()
torus.inner_radius = 1.0
torus.outer_radius = 1.65
var ring_mat := StandardMaterial3D.new()
ring_mat.albedo_color = Color(0.55, 0.1, 1.0)
ring_mat.emission_enabled = true
ring_mat.emission = Color(0.6, 0.2, 1.0)
ring_mat.emission_energy = 3.5
ring_mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
torus.material = ring_mat
ring.mesh = torus
ring.position.y = 0.05
portal_node.add_child(ring)
ring.create_tween().set_loops().tween_property(ring, "rotation:y", TAU, 2.5)
var disc := MeshInstance3D.new()
var disc_mesh := CylinderMesh.new()
disc_mesh.top_radius = 1.0
disc_mesh.bottom_radius = 1.0
disc_mesh.height = 0.05
var disc_mat := StandardMaterial3D.new()
disc_mat.albedo_color = Color(0.25, 0.0, 0.7, 0.65)
disc_mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
disc_mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
disc_mat.emission_enabled = true
disc_mat.emission = Color(0.4, 0.1, 1.0)
disc_mat.emission_energy = 1.5
disc_mesh.material = disc_mat
disc.mesh = disc_mesh
disc.position.y = 0.03
portal_node.add_child(disc)
var tw_pulse := portal_node.create_tween().set_loops()
tw_pulse.tween_method(func(e: float): disc_mat.emission_energy = e, 0.8, 3.0, 0.7)
tw_pulse.tween_method(func(e: float): disc_mat.emission_energy = e, 3.0, 0.8, 0.7)
var area := Area3D.new()
area.name = "PortalArea"
var col := CollisionShape3D.new()
var cyl := CylinderShape3D.new()
cyl.radius = 1.8
cyl.height = 3.0
col.shape = cyl
col.position.y = 1.5
area.add_child(col)
portal_node.add_child(area)
var lbl := Label3D.new()
lbl.text = "PORTAL\nPush Ogre Here"
lbl.position = Vector3(0, 2.6, 0)
lbl.billboard = BaseMaterial3D.BILLBOARD_ENABLED
lbl.font_size = 34
lbl.outline_size = 6
lbl.modulate = Color(0.85, 0.55, 1.0)
lbl.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
portal_node.add_child(lbl)
FX.merge_smoke(best_pos + Vector3(0, 0.5, 0), self)
func _trigger_win() -> void:
if not boss_active:
return
boss_active = false
game_active = false
spawn_timer.stop()
boss_timer_label.visible = false
boss_hint_label.visible = false
if is_instance_valid(portal_node):
portal_node.queue_free()
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
(win_panel.get_node("VBox/ScoreLabel") as Label).text = "Score: %d\nWave: %d" % [score, wave]
show_tutorial("VictoryScreen", func() -> void:
get_tree().paused = true
win_panel.visible = true
)
func _trigger_time_up() -> void:
if not boss_active:
return
boss_active = false
game_active = false
spawn_timer.stop()
boss_timer_label.visible = false
boss_hint_label.visible = false
if is_instance_valid(portal_node):
portal_node.queue_free()
_show_gameover()
# ─── Tutorial ─────────────────────────────────────────────────────────────────
func _create_tutorial_overlay() -> void:
@@ -366,18 +553,18 @@ func _create_tutorial_overlay() -> void:
tutorial_canvas.add_child(bg)
tutorial_image = TextureRect.new()
tutorial_image.anchor_left = 0.1
tutorial_image.anchor_right = 0.9
tutorial_image.anchor_top = 0.07
tutorial_image.anchor_bottom = 0.84
tutorial_image.anchor_left = 0.02
tutorial_image.anchor_right = 0.98
tutorial_image.anchor_top = 0.02
tutorial_image.anchor_bottom = 0.91
tutorial_image.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
tutorial_image.expand_mode = TextureRect.EXPAND_FIT_WIDTH_PROPORTIONAL
tutorial_image.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
tutorial_canvas.add_child(tutorial_image)
tutorial_hint = Label.new()
tutorial_hint.anchor_left = 0.5
tutorial_hint.anchor_right = 0.5
tutorial_hint.anchor_top = 0.88
tutorial_hint.anchor_top = 0.93
tutorial_hint.offset_left = -280
tutorial_hint.offset_right = 280
tutorial_hint.text = "Нажмите ЛКМ чтобы продолжить"
@@ -415,8 +602,10 @@ func _set_player_paused(paused: bool) -> void:
for e in get_tree().get_nodes_in_group("player"):
(e as Node).process_mode = mode
const _REPEATABLE_TUTORIALS := ["VictoryScreen", "LoseGame"]
func show_tutorial(key: String, on_dismiss: Callable = Callable()) -> void:
if shown_tutorials.get(key, false):
if shown_tutorials.get(key, false) and not key in _REPEATABLE_TUTORIALS:
if on_dismiss.is_valid():
on_dismiss.call()
return
@@ -452,25 +641,112 @@ func _create_ui() -> void:
_make_hud()
_make_upgrade_panel()
_make_gameover_panel()
_make_boss_ui()
_make_win_panel()
_make_pause_panel()
func _make_hud() -> void:
# Score
score_label = _label(Vector2(12, 10), "Score: 0", 22)
# Wave
wave_label = _label(Vector2(12, 38), "Wave: 1", 22)
score_label = _label(Vector2(16, 12), "Score: 0", 30)
wave_label = _label(Vector2(16, 50), "Wave: 1", 30)
_make_recipe_panel()
# HP bar
_label(Vector2(12, 68), "HP", 16)
hp_bar_bg = _crect(Vector2(12, 88), Vector2(200, 16), Color(0.25, 0.04, 0.04))
hp_bar = _crect(Vector2(12, 88), Vector2(200, 16), Color(0.9, 0.15, 0.15))
func _make_recipe_panel() -> void:
const INGREDIENT_NAMES := {
"rock": "Rock",
"stick": "Stick",
"leather": "Leather",
"iron": "Iron",
"metal_plate":"Iron Plate",
#"MetalPlate":"Armor boots"
"essence":"Essence",
"Enchanted_Table": "Ench Table",
"EnchantedSphere": "Enchanted Boots"
}
const RESULT_NAMES := {
"LeatherBoots": "Leather Boots",
"Boulder": "Boulder",
"StickArmor": "Stick Armor",
"LeatherArmor": "Leather Armor",
"PlateArmor": "Plate Armor",
"WoodenShield": "Wooden Shield",
"IronShield": "Iron Shield",
"MetalArmor": "Metal Armor",
"MetalPlate": "Armor boots"
}
# Kill progress toward next upgrade
_label(Vector2(12, 110), "Next upgrade", 16)
progress_bg = _crect(Vector2(12, 130), Vector2(200, 10), Color(0.1, 0.1, 0.25))
progress_bar = _crect(Vector2(12, 130), Vector2(0, 10), Color(0.4, 0.8, 1.0))
const PAD_H := 10
const PAD_V := 8
const SEP := 4
const TITLE_H := 22
const ROW_H := 20
var n := MergeRecipes._list.size()
var content_h := TITLE_H + SEP + n * ROW_H + (n - 1) * SEP
var panel_h := content_h + PAD_V * 2 + 10
const PANEL_W := 260
# Tier display
tier_label = _label(Vector2(12, 148), "", 17)
var panel := Panel.new()
var sb := StyleBoxFlat.new()
sb.bg_color = Color(0.0, 0.0, 0.0, 0.55)
sb.corner_radius_top_left = 6
sb.corner_radius_top_right = 6
sb.corner_radius_bottom_left = 6
sb.corner_radius_bottom_right = 6
panel.add_theme_stylebox_override("panel", sb)
panel.anchor_left = 1.0
panel.anchor_right = 1.0
panel.anchor_top = 0.0
panel.anchor_bottom = 0.0
panel.offset_left = -(PANEL_W + 10)
panel.offset_right = -10
panel.offset_top = 10
panel.offset_bottom = 10 + panel_h
canvas.add_child(panel)
var margin := MarginContainer.new()
margin.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
margin.add_theme_constant_override("margin_left", PAD_H)
margin.add_theme_constant_override("margin_right", PAD_H)
margin.add_theme_constant_override("margin_top", PAD_V)
margin.add_theme_constant_override("margin_bottom", PAD_V)
panel.add_child(margin)
var vbox := VBoxContainer.new()
vbox.add_theme_constant_override("separation", SEP)
margin.add_child(vbox)
var title := Label.new()
title.text = "Рецепты"
title.add_theme_font_size_override("font_size", 17)
title.add_theme_color_override("font_color", Color(1.0, 0.9, 0.5))
title.add_theme_color_override("font_shadow_color", Color(0, 0, 0, 0.8))
title.add_theme_constant_override("shadow_offset_x", 1)
title.add_theme_constant_override("shadow_offset_y", 1)
title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
vbox.add_child(title)
for recipe in MergeRecipes._list:
var a: String = INGREDIENT_NAMES.get(recipe["ingredients"][0], recipe["ingredients"][0])
var b: String = INGREDIENT_NAMES.get(recipe["ingredients"][1], recipe["ingredients"][1])
var scene_name: String = (recipe["result_scene"] as String).get_file().get_basename()
var result: String = RESULT_NAMES.get(scene_name, scene_name)
var row := Label.new()
row.text = "%s + %s%s" % [a, b, result]
row.add_theme_font_size_override("font_size", 15)
row.add_theme_color_override("font_color", Color.WHITE)
row.add_theme_color_override("font_shadow_color", Color(0, 0, 0, 0.8))
row.add_theme_constant_override("shadow_offset_x", 1)
row.add_theme_constant_override("shadow_offset_y", 1)
vbox.add_child(row)
_label(Vector2(16, 92), "HP", 20)
hp_bar_bg = _crect(Vector2(16, 118), Vector2(260, 20), Color(0.25, 0.04, 0.04))
hp_bar = _crect(Vector2(16, 118), Vector2(260, 20), Color(0.9, 0.15, 0.15))
_label(Vector2(16, 146), "Next upgrade", 20)
progress_bg = _crect(Vector2(16, 172), Vector2(260, 14), Color(0.1, 0.1, 0.25))
progress_bar = _crect(Vector2(16, 172), Vector2(0, 14), Color(0.4, 0.8, 1.0))
tier_label = _label(Vector2(16, 194), "", 20)
_make_equipment_slots()
@@ -553,13 +829,92 @@ func _make_gameover_panel() -> void:
restart_btn.connect("pressed", _restart)
vbox.add_child(restart_btn)
func _make_boss_ui() -> void:
boss_timer_label = Label.new()
boss_timer_label.anchor_left = 0.5
boss_timer_label.anchor_right = 0.5
boss_timer_label.anchor_top = 0.0
boss_timer_label.offset_left = -80
boss_timer_label.offset_right = 80
boss_timer_label.offset_top = 8
boss_timer_label.offset_bottom = 54
boss_timer_label.text = "1:30"
boss_timer_label.add_theme_font_size_override("font_size", 38)
boss_timer_label.add_theme_color_override("font_color", Color(0.8, 0.3, 1.0))
boss_timer_label.add_theme_color_override("font_shadow_color", Color(0, 0, 0, 0.9))
boss_timer_label.add_theme_constant_override("shadow_offset_x", 2)
boss_timer_label.add_theme_constant_override("shadow_offset_y", 2)
boss_timer_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
boss_timer_label.visible = false
canvas.add_child(boss_timer_label)
boss_hint_label = Label.new()
boss_hint_label.anchor_left = 0.5
boss_hint_label.anchor_right = 0.5
boss_hint_label.anchor_top = 0.0
boss_hint_label.offset_left = -220
boss_hint_label.offset_right = 220
boss_hint_label.offset_top = 54
boss_hint_label.offset_bottom = 80
boss_hint_label.text = "Push the Ogre into the Portal!"
boss_hint_label.add_theme_font_size_override("font_size", 17)
boss_hint_label.add_theme_color_override("font_color", Color(0.85, 0.7, 1.0))
boss_hint_label.add_theme_color_override("font_shadow_color", Color(0, 0, 0, 0.8))
boss_hint_label.add_theme_constant_override("shadow_offset_x", 1)
boss_hint_label.add_theme_constant_override("shadow_offset_y", 1)
boss_hint_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
boss_hint_label.visible = false
canvas.add_child(boss_hint_label)
func _make_win_panel() -> void:
win_panel = Panel.new()
win_panel.process_mode = Node.PROCESS_MODE_ALWAYS
win_panel.visible = false
canvas.add_child(win_panel)
win_panel.anchor_left = 0.5
win_panel.anchor_right = 0.5
win_panel.anchor_top = 0.5
win_panel.anchor_bottom = 0.5
win_panel.offset_left = -200.0
win_panel.offset_right = 200.0
win_panel.offset_top = -140.0
win_panel.offset_bottom = 140.0
var vbox2 := VBoxContainer.new()
vbox2.name = "VBox"
vbox2.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
vbox2.alignment = BoxContainer.ALIGNMENT_CENTER
vbox2.add_theme_constant_override("separation", 16)
win_panel.add_child(vbox2)
var title2 := Label.new()
title2.text = "VICTORY!"
title2.add_theme_font_size_override("font_size", 42)
title2.add_theme_color_override("font_color", Color(1.0, 0.85, 0.1))
title2.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
vbox2.add_child(title2)
var score_lbl2 := Label.new()
score_lbl2.name = "ScoreLabel"
score_lbl2.add_theme_font_size_override("font_size", 20)
score_lbl2.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
vbox2.add_child(score_lbl2)
var btn2 := Button.new()
btn2.text = "Play Again"
btn2.add_theme_font_size_override("font_size", 18)
btn2.process_mode = Node.PROCESS_MODE_ALWAYS
btn2.connect("pressed", _restart)
vbox2.add_child(btn2)
# ─── Equipment slots ──────────────────────────────────────────────────────────
const _EQUIP_SLOT_SIZE := 54
const _EQUIP_SLOT_GAP := 8
const _EQUIP_SLOT_SIZE := 64
const _EQUIP_SLOT_GAP := 10
const _EQUIP_SLOT_PAD := 3
const _EQUIP_START_X := 12
const _EQUIP_START_Y := 170
const _EQUIP_START_X := 16
const _EQUIP_START_Y := 228
const _EQUIP_EMPTY_COL := Color(0.10, 0.10, 0.16)
const _EQUIP_BORDER_COL := Color(0.30, 0.30, 0.42)
@@ -589,18 +944,18 @@ func _make_equipment_slots() -> void:
var x := _EQUIP_START_X + i * (_EQUIP_SLOT_SIZE + _EQUIP_SLOT_GAP)
var y := _EQUIP_START_Y
var title := _label(Vector2(x, y), titles[i], 12)
var title := _label(Vector2(x, y), titles[i], 16)
title.size.x = _EQUIP_SLOT_SIZE
title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
var border := ColorRect.new()
border.position = Vector2(x, y + 16)
border.position = Vector2(x, y + 22)
border.size = Vector2(_EQUIP_SLOT_SIZE, _EQUIP_SLOT_SIZE)
border.color = _EQUIP_BORDER_COL
canvas.add_child(border)
var fill := ColorRect.new()
fill.position = Vector2(x + _EQUIP_SLOT_PAD, y + 16 + _EQUIP_SLOT_PAD)
fill.position = Vector2(x + _EQUIP_SLOT_PAD, y + 22 + _EQUIP_SLOT_PAD)
fill.size = Vector2(_EQUIP_SLOT_SIZE - _EQUIP_SLOT_PAD * 2, _EQUIP_SLOT_SIZE - _EQUIP_SLOT_PAD * 2)
fill.color = _EQUIP_EMPTY_COL
canvas.add_child(fill)
@@ -610,7 +965,7 @@ func _make_equipment_slots() -> void:
lbl.position = fill.position
lbl.size = fill.size
lbl.text = ""
lbl.add_theme_font_size_override("font_size", 11)
lbl.add_theme_font_size_override("font_size", 14)
lbl.add_theme_color_override("font_color", Color.WHITE)
lbl.add_theme_color_override("font_shadow_color", Color(0, 0, 0, 0.85))
lbl.add_theme_constant_override("shadow_offset_x", 1)
@@ -682,3 +1037,94 @@ func _update_tier_label() -> void:
var shield_str := "-" if st == 0 else str(st)
tier_label.text = "Kick: %d Tough: %d Shield: %s" % [kt, tt, shield_str]
_update_equipment_slots()
# ─── Pause menu ───────────────────────────────────────────────────────────────
const _PAUSE_CRAFT_IMG := "res://assets/Pause_Craft.jpeg"
const _PAUSE_CONTROLS_IMG := "res://assets/Pause_Controls.jpeg"
func _make_pause_panel() -> void:
pause_panel = Panel.new()
pause_panel.process_mode = Node.PROCESS_MODE_ALWAYS
pause_panel.visible = false
var sb := StyleBoxFlat.new()
sb.bg_color = Color(0.05, 0.04, 0.10, 0.96)
sb.border_width_left = 2; sb.border_width_right = 2
sb.border_width_top = 2; sb.border_width_bottom = 2
sb.border_color = Color(0.35, 0.28, 0.55)
sb.corner_radius_top_left = 10; sb.corner_radius_top_right = 10
sb.corner_radius_bottom_left = 10; sb.corner_radius_bottom_right = 10
pause_panel.add_theme_stylebox_override("panel", sb)
pause_panel.anchor_left = 0.5; pause_panel.anchor_right = 0.5
pause_panel.anchor_top = 0.5; pause_panel.anchor_bottom = 0.5
pause_panel.offset_left = -380; pause_panel.offset_right = 380
pause_panel.offset_top = -300; pause_panel.offset_bottom = 300
canvas.add_child(pause_panel)
var vbox := VBoxContainer.new()
vbox.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
vbox.add_theme_constant_override("separation", 12)
var margin := MarginContainer.new()
margin.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
margin.add_theme_constant_override("margin_left", 20)
margin.add_theme_constant_override("margin_right", 20)
margin.add_theme_constant_override("margin_top", 16)
margin.add_theme_constant_override("margin_bottom", 16)
pause_panel.add_child(margin)
margin.add_child(vbox)
var title := Label.new()
title.text = "ПАУЗА"
title.add_theme_font_size_override("font_size", 28)
title.add_theme_color_override("font_color", Color(1.0, 0.9, 0.5))
title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
vbox.add_child(title)
pause_image = TextureRect.new()
pause_image.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
pause_image.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
pause_image.custom_minimum_size = Vector2(0, 380)
pause_image.size_flags_vertical = Control.SIZE_EXPAND_FILL
vbox.add_child(pause_image)
_pause_load_image()
var hbox := HBoxContainer.new()
hbox.alignment = BoxContainer.ALIGNMENT_CENTER
hbox.add_theme_constant_override("separation", 16)
vbox.add_child(hbox)
pause_toggle_btn = _pause_btn("Управление", _on_pause_toggle)
hbox.add_child(pause_toggle_btn)
hbox.add_child(_pause_btn("Продолжить", _toggle_pause_menu))
hbox.add_child(_pause_btn("Главное меню", func() -> void:
get_tree().paused = false
get_tree().change_scene_to_file("res://scenes/MainMenu.tscn")
))
func _pause_btn(text: String, cb: Callable) -> Button:
var b := Button.new()
b.text = text
b.process_mode = Node.PROCESS_MODE_ALWAYS
b.custom_minimum_size = Vector2(160, 48)
b.add_theme_font_size_override("font_size", 17)
b.connect("pressed", cb)
return b
func _pause_load_image() -> void:
var path := _PAUSE_CRAFT_IMG if _pause_showing_craft else _PAUSE_CONTROLS_IMG
pause_image.texture = load(path) as Texture2D if ResourceLoader.exists(path) else null
func _on_pause_toggle() -> void:
_pause_showing_craft = not _pause_showing_craft
pause_toggle_btn.text = "Управление" if _pause_showing_craft else "Рецепты Крафта"
_pause_load_image()
func _toggle_pause_menu() -> void:
var opening := not pause_panel.visible
pause_panel.visible = opening
get_tree().paused = opening
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE if opening else Input.MOUSE_MODE_CAPTURED
if opening:
_pause_showing_craft = true
pause_toggle_btn.text = "Управление"
_pause_load_image()
+150 -3
View File
@@ -3,6 +3,7 @@ extends Control
static var volume: float = 100.0
var settings_panel: Panel
var difficulty_panel: Panel
func _ready() -> void:
process_mode = Node.PROCESS_MODE_ALWAYS
@@ -17,7 +18,7 @@ func _build_ui() -> void:
add_child(bg)
var title := Label.new()
title.text = "KickSurvivors"
title.text = "CraftKick"
title.add_theme_font_size_override("font_size", 52)
title.add_theme_color_override("font_color", Color.WHITE)
title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
@@ -46,17 +47,82 @@ func _build_ui() -> void:
vbox.add_child(_btn("Выход", _on_exit))
_build_settings_panel()
_build_difficulty_panel()
_add_studio_logo()
func _add_studio_logo() -> void:
const PATH := "res://assets/studio_logo.png"
var logo := TextureRect.new()
if ResourceLoader.exists(PATH):
logo.texture = load(PATH) as Texture2D
logo.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
logo.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
logo.anchor_left = 1.0
logo.anchor_right = 1.0
logo.anchor_top = 1.0
logo.anchor_bottom = 1.0
logo.offset_left = -200
logo.offset_right = -16
logo.offset_top = -208
logo.offset_bottom = -16
logo.modulate.a = 0.85
add_child(logo)
func _big_btn(text: String, width: float, cb: Callable) -> Button:
var b := _btn(text, cb)
b.custom_minimum_size = Vector2(width, 72)
b.add_theme_font_size_override("font_size", 18)
return b
func _btn(text: String, cb: Callable) -> Button:
var b := Button.new()
b.text = text
b.custom_minimum_size = Vector2(220, 54)
b.add_theme_font_size_override("font_size", 20)
for state in ["normal", "hover", "pressed", "focus", "disabled"]:
var sb := StyleBoxFlat.new()
sb.bg_color = Color(0.18, 0.13, 0.30) if state == "normal" else (
Color(0.28, 0.20, 0.46) if state == "hover" else
Color(0.12, 0.09, 0.22))
sb.border_width_left = 1
sb.border_width_right = 1
sb.border_width_top = 1
sb.border_width_bottom = 1
sb.border_color = Color(0.50, 0.38, 0.75)
sb.corner_radius_top_left = 6
sb.corner_radius_top_right = 6
sb.corner_radius_bottom_left = 6
sb.corner_radius_bottom_right = 6
sb.content_margin_left = 20
sb.content_margin_right = 20
sb.content_margin_top = 12
sb.content_margin_bottom = 12
b.add_theme_stylebox_override(state, sb)
b.connect("pressed", cb)
return b
static func _make_opaque_panel() -> Panel:
var p := Panel.new()
var sb := StyleBoxFlat.new()
sb.bg_color = Color(0.08, 0.06, 0.14)
sb.border_width_left = 2
sb.border_width_right = 2
sb.border_width_top = 2
sb.border_width_bottom = 2
sb.border_color = Color(0.35, 0.28, 0.55)
sb.corner_radius_top_left = 8
sb.corner_radius_top_right = 8
sb.corner_radius_bottom_left = 8
sb.corner_radius_bottom_right = 8
sb.content_margin_left = 24
sb.content_margin_right = 24
sb.content_margin_top = 20
sb.content_margin_bottom = 20
p.add_theme_stylebox_override("panel", sb)
return p
func _build_settings_panel() -> void:
settings_panel = Panel.new()
settings_panel = _make_opaque_panel()
settings_panel.visible = false
settings_panel.anchor_left = 0.5
settings_panel.anchor_right = 0.5
@@ -105,8 +171,89 @@ func _apply_volume(v: float) -> void:
var db := linear_to_db(v / 100.0) if v > 0.0 else -80.0
AudioServer.set_bus_volume_db(0, db)
func _on_play() -> void:
func _build_difficulty_panel() -> void:
difficulty_panel = _make_opaque_panel()
difficulty_panel.visible = false
difficulty_panel.anchor_left = 0.5
difficulty_panel.anchor_right = 0.5
difficulty_panel.anchor_top = 0.5
difficulty_panel.anchor_bottom = 0.5
difficulty_panel.offset_left = -310
difficulty_panel.offset_right = 310
difficulty_panel.offset_top = -240
difficulty_panel.offset_bottom = 240
add_child(difficulty_panel)
var margin := MarginContainer.new()
margin.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
margin.add_theme_constant_override("margin_left", 24)
margin.add_theme_constant_override("margin_right", 24)
margin.add_theme_constant_override("margin_top", 20)
margin.add_theme_constant_override("margin_bottom", 20)
difficulty_panel.add_child(margin)
var vbox := VBoxContainer.new()
vbox.alignment = BoxContainer.ALIGNMENT_CENTER
vbox.add_theme_constant_override("separation", 16)
margin.add_child(vbox)
var title := Label.new()
title.text = "Выберите сложность"
title.add_theme_font_size_override("font_size", 26)
title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
vbox.add_child(title)
vbox.add_child(_big_btn("Бессмертный\nНет урона · тир пинков от мелких врагов", 540, func() -> void:
GameSettings.difficulty = "immortal"
get_tree().change_scene_to_file("res://scenes/Main.tscn")
))
vbox.add_child(_big_btn("Выживание\nПолучаешь урон · фиксированная сила пинка", 540, func() -> void:
GameSettings.difficulty = "survival"
get_tree().change_scene_to_file("res://scenes/Main.tscn")
))
# Spawn speed row
var spawn_lbl := Label.new()
spawn_lbl.text = "Скорость спавна:"
spawn_lbl.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
spawn_lbl.add_theme_font_size_override("font_size", 16)
spawn_lbl.add_theme_color_override("font_color", Color(0.85, 0.78, 1.0))
vbox.add_child(spawn_lbl)
var hbox := HBoxContainer.new()
hbox.alignment = BoxContainer.ALIGNMENT_CENTER
hbox.add_theme_constant_override("separation", 10)
vbox.add_child(hbox)
var spawn_options := [
["Медленно", 10.0, 15.0],
["Нормально", 8.0, 15.0],
["Быстро", 6.0, 10.0],
]
var spawn_btns: Array[Button] = []
for opt in spawn_options:
var sb_btn := _btn(opt[0] as String, Callable())
sb_btn.custom_minimum_size = Vector2(110, 40)
sb_btn.add_theme_font_size_override("font_size", 15)
var enemy_iv: float = opt[1]
var item_iv: float = opt[2]
sb_btn.connect("pressed", func() -> void:
GameSettings.enemy_spawn_interval = enemy_iv
GameSettings.item_respawn_delay = item_iv
for b in spawn_btns:
b.modulate = Color(1, 1, 1)
sb_btn.modulate = Color(0.7, 1.0, 0.5)
)
hbox.add_child(sb_btn)
spawn_btns.append(sb_btn)
# default: normal
spawn_btns[1].modulate = Color(0.7, 1.0, 0.5)
vbox.add_child(_btn("Назад", func(): difficulty_panel.visible = false))
func _on_play() -> void:
difficulty_panel.visible = true
func _on_settings() -> void:
settings_panel.visible = true
+12 -2
View File
@@ -24,7 +24,7 @@ static var _list: Array[Dictionary] = [
"speed_threshold": 18.0,
},
{
"ingredients": ["leather", "metal_plate"],
"ingredients": ["leather", "iron"],
"result_scene": "res://scenes/PlateArmor.tscn",
"speed_threshold": 18.0,
},
@@ -34,10 +34,20 @@ static var _list: Array[Dictionary] = [
"speed_threshold": 18.0,
},
{
"ingredients": ["iron", "leather"],
"ingredients": ["iron", "rock"],
"result_scene": "res://scenes/IronShield.tscn",
"speed_threshold": 18.0,
},
{
"ingredients": ["iron", "Smith"],
"result_scene": "res://scenes/MetalPlate.tscn",
"speed_threshold": 0.1,
},
{
"ingredients": ["essence", "Enchanted_Table"],
"result_scene": "res://scenes/EnchantedSphere.tscn",
"speed_threshold": 0.1,
}
]
static func find(type_a: String, type_b: String, speed: float) -> Dictionary:
+50 -39
View File
@@ -8,7 +8,7 @@ signal health_changed(current: int, maximum: int)
@export var kick_force: float = 60.0
@export var kick_cooldown: float = 0.6
@export var kick_angle: float = 60.0
@export var max_health: int = 100
@export var max_health: int = 300
var health: int = max_health
var kick_tier: int = 0
@@ -21,6 +21,7 @@ var has_iron_shield: bool = false
var shield_tier: int = 0
var is_shielding: bool = false
var kick_timer: float = 0.0
var interact_timer: float = 0.0
var invincible_timer: float = 0.0
var is_alive: bool = true
var last_move_dir: Vector3 = Vector3.FORWARD
@@ -29,6 +30,7 @@ var _aim_yaw: float = 0.0
var _is_aiming: bool = false
@onready var mesh_node: MeshInstance3D = $player_man
@onready var mesh_node_boot: MeshInstance3D = $boot
@onready var indicator_node: MeshInstance3D = $KickIndicator
@onready var anim_player: AnimationPlayer = $AnimationPlayer2
@@ -42,8 +44,23 @@ func _ready() -> void:
add_to_group("player")
player_mat = mesh_node.get_surface_override_material(0).duplicate() as StandardMaterial3D
mesh_node.set_surface_override_material(0, player_mat)
mesh_node_boot.visible = false
_setup_indicator()
func _apply_boot_mesh(tier: int) -> void:
if tier <= 0:
mesh_node_boot.visible = false
return
mesh_node_boot.visible = true
var tex := load("res://assets/boot%d.png" % tier) as Texture2D
if tex == null:
return
var mat := mesh_node_boot.get_surface_override_material(0)
if mat == null:
mat = StandardMaterial3D.new()
mesh_node_boot.set_surface_override_material(0, mat)
(mat as StandardMaterial3D).albedo_texture = tex
func _setup_indicator() -> void:
indicator_node.position.y = 0.02
indicator_node.mesh = _make_kick_arc_mesh()
@@ -77,19 +94,17 @@ func _make_kick_arc_mesh() -> ArrayMesh:
mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arrays)
return mesh
func _input(event: InputEvent) -> void:
if event is InputEventKey and event.pressed and not event.echo:
if event.keycode == KEY_E:
_try_interact()
func _physics_process(delta: float) -> void:
if not is_alive:
return
is_shielding = shield_tier > 0 and Input.is_key_pressed(KEY_SHIFT)
is_shielding = shield_tier > 0 and Input.is_key_pressed(KEY_SPACE)
_handle_movement(delta)
_handle_kick(delta)
_handle_iframes(delta)
if Input.is_action_just_pressed("ui_accept") and kick_timer <= 0.0:
interact_timer = max(0.0, interact_timer - delta)
if interact_timer <= 0.0:
_try_interact()
if Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) and kick_timer <= 0.0:
_do_kick()
func _handle_movement(delta: float) -> void:
@@ -102,8 +117,16 @@ func _handle_movement(delta: float) -> void:
float(Input.is_key_pressed(KEY_S) or Input.is_key_pressed(KEY_DOWN)) -
float(Input.is_key_pressed(KEY_W) or Input.is_key_pressed(KEY_UP))
)
var is_moving: bool = abs(input_x) > 0.0 or abs(input_z) > 0.0
if is_moving:
if not anim_player.is_playing() or anim_player.current_animation != "walk":
anim_player.play("walk")
else:
if anim_player.current_animation == "walk":
anim_player.stop()
var cam := get_viewport().get_camera_3d()
if (abs(input_x) > 0.0 or abs(input_z) > 0.0) and cam != null:
if is_moving and cam != null:
var cam_fwd := -cam.global_transform.basis.z
cam_fwd.y = 0.0
cam_fwd = cam_fwd.normalized() if cam_fwd.length() > 0.01 else Vector3(0.0, 0.0, -1.0)
@@ -180,7 +203,9 @@ func _do_kick() -> void:
var obj_toughness: int = best.get("toughness_tier") if best.get("toughness_tier") != null else 0
var diff_tier := kick_tier - obj_toughness
var force: float
if diff_tier < 0:
if GameSettings.difficulty == "immortal":
force = 50.0
elif diff_tier < 0:
force = 15.0
elif diff_tier == 0:
force = 50.0
@@ -189,6 +214,7 @@ func _do_kick() -> void:
else:
force = 80.0
best.call("receive_kick", best_dir, force)
SFX.kick_player(get_parent())
FX.hit_spark(best.global_position + Vector3(0, 0.4, 0), get_parent())
_squish_effect()
@@ -211,9 +237,12 @@ func set_aim_direction(yaw_rad: float) -> void:
_is_aiming = true
func _play_kick_blend() -> void:
var tw := create_tween()
var tw := create_tween().set_parallel(true)
tw.tween_method(func(v: float): mesh_node.set_blend_shape_value(0, v), 0.0, 1.0, 0.12)
tw.tween_method(func(v: float): mesh_node.set_blend_shape_value(0, v), 1.0, 0.0, 0.38)
tw.tween_method(func(v: float): mesh_node_boot.set_blend_shape_value(0, v), 0.0, 1.0, 0.12)
tw.chain()
tw.tween_method(func(v: float): mesh_node.set_blend_shape_value(0, v), 1.0, 0.0, 0.28)
tw.tween_method(func(v: float): mesh_node_boot.set_blend_shape_value(0, v), 1.0, 0.0, 0.28)
func _squish_effect() -> void:
var tw := create_tween()
@@ -229,6 +258,8 @@ func receive_kick(direction: Vector3, force: float) -> void:
_squish_effect()
func take_damage(amount: int, attacker_toughness: int = 0) -> void:
if GameSettings.difficulty == "immortal":
return
if not is_alive or invincible_timer > 0.0:
return
invincible_timer = IFRAMES_DURATION
@@ -236,16 +267,19 @@ func take_damage(amount: int, attacker_toughness: int = 0) -> void:
var diff := shield_tier - attacker_toughness
var mod: float = 0.15 if diff >= 2 else (0.30 if diff == 1 else 0.50)
amount = int(amount * mod)
health = min(health - amount, max_health)
emit_signal("health_changed", health, max_health)
SFX.damage(get_parent())
_squish_effect()
if health <= 0:
_die()
func heal(amount: int) -> void:
if not is_alive:
return
health = min(health + amount, max_health)
emit_signal("health_changed", health, max_health)
var tw := create_tween()
tw.tween_property(player_mat, "albedo_color", Color(0.1, 1.0, 0.35), 0.08)
tw.tween_property(player_mat, "albedo_color", BASE_COLOR, 0.3)
func _die() -> void:
is_alive = false
@@ -269,30 +303,19 @@ func apply_upgrade(id: String) -> void:
func apply_upgrade_boots(speed_bonus: float, _tier: int) -> void:
kick_tier += 1
move_speed += speed_bonus
var tw := create_tween()
tw.tween_property(player_mat, "albedo_color", Color(1.0, 0.85, 0.2), 0.1)
tw.tween_property(player_mat, "albedo_color", BASE_COLOR, 0.4)
_apply_boot_mesh(kick_tier)
func apply_upgrade_armor() -> void:
kick_tier += 1
var tw := create_tween()
tw.tween_property(player_mat, "albedo_color", Color(0.7, 0.8, 1.0), 0.1)
tw.tween_property(player_mat, "albedo_color", BASE_COLOR, 0.5)
func apply_upgrade_enchant() -> void:
kick_tier += 1
var tw := create_tween()
tw.tween_property(player_mat, "albedo_color", Color(0.8, 0.2, 1.0), 0.1)
tw.tween_property(player_mat, "albedo_color", BASE_COLOR, 0.6)
func apply_stick_armor() -> bool:
if has_stick_armor:
return false
has_stick_armor = true
toughness_tier += 1
var tw := create_tween()
tw.tween_property(player_mat, "albedo_color", Color(0.7, 0.5, 0.2), 0.1)
tw.tween_property(player_mat, "albedo_color", BASE_COLOR, 0.4)
return true
func apply_leather_armor() -> bool:
@@ -300,9 +323,6 @@ func apply_leather_armor() -> bool:
return false
has_leather_armor = true
toughness_tier += 1
var tw := create_tween()
tw.tween_property(player_mat, "albedo_color", Color(0.8, 0.5, 0.2), 0.1)
tw.tween_property(player_mat, "albedo_color", BASE_COLOR, 0.4)
return true
func apply_plate_armor() -> bool:
@@ -310,9 +330,6 @@ func apply_plate_armor() -> bool:
return false
has_plate_armor = true
toughness_tier += 1
var tw := create_tween()
tw.tween_property(player_mat, "albedo_color", Color(0.6, 0.7, 1.0), 0.1)
tw.tween_property(player_mat, "albedo_color", BASE_COLOR, 0.5)
return true
func apply_wooden_shield() -> bool:
@@ -320,9 +337,6 @@ func apply_wooden_shield() -> bool:
return false
has_wooden_shield = true
shield_tier = max(shield_tier, 1)
var tw := create_tween()
tw.tween_property(player_mat, "albedo_color", Color(0.55, 0.38, 0.18), 0.1)
tw.tween_property(player_mat, "albedo_color", BASE_COLOR, 0.4)
return true
func apply_iron_shield() -> bool:
@@ -330,7 +344,4 @@ func apply_iron_shield() -> bool:
return false
has_iron_shield = true
shield_tier = max(shield_tier, 2)
var tw := create_tween()
tw.tween_property(player_mat, "albedo_color", Color(0.55, 0.58, 0.62), 0.1)
tw.tween_property(player_mat, "albedo_color", BASE_COLOR, 0.5)
return true
+1 -1
View File
@@ -32,7 +32,7 @@ func _ready() -> void:
_tooltip = Label3D.new()
_tooltip.text = "Rock\n+Rock → Boulder\n+Stick → Wood Shield"
_tooltip.billboard = BaseMaterial3D.BILLBOARD_ENABLED
_tooltip.font_size = 28
_tooltip.font_size = 56
_tooltip.outline_size = 6
_tooltip.position = Vector3(0, 1.1, 0)
_tooltip.modulate = Color(1.0, 0.95, 0.8)
+57
View File
@@ -0,0 +1,57 @@
class_name SFX
# Expected files in res://assets/sfx/:
# kick_player.ogg — player kicks something
# kick_enemy.ogg — enemy attacks
# merge.ogg — two objects merge
# damage.ogg — player takes damage
# ambient.ogg — looping background ambience
const _BASE := "res://assets/"
static func _play(name: String, parent: Node, volume_db: float = 0.0, pitch: float = 1.0) -> void:
var path := _BASE + name
if not ResourceLoader.exists(path):
return
var stream := load(path) as AudioStream
if stream == null:
return
var ogg = stream as AudioStreamOggVorbis
if ogg != null:
ogg.loop = false
var p := AudioStreamPlayer.new()
p.stream = stream
p.volume_db = volume_db
p.pitch_scale = pitch + randf_range(-0.06, 0.06)
p.bus = "Master"
parent.add_child(p)
p.play()
p.connect("finished", p.queue_free)
static func kick_player(parent: Node) -> void:
_play("kick_player.ogg", parent, -4.0)
static func kick_enemy(parent: Node) -> void:
_play("kick_enemy.ogg", parent, -6.0)
static func merge(parent: Node) -> void:
_play("merge.ogg", parent, -3.0)
static func damage(parent: Node) -> void:
_play("damage.ogg", parent, -2.0)
static func start_ambient(parent: Node) -> AudioStreamPlayer:
var path := _BASE + "ambient.ogg"
if not ResourceLoader.exists(path):
return null
var stream := load(path) as AudioStream
if stream == null:
return null
var p := AudioStreamPlayer.new()
p.stream = stream
p.volume_db = -14.0
p.bus = "Master"
p.autoplay = true
(stream as AudioStreamOggVorbis).loop = true
parent.add_child(p)
return p
+1
View File
@@ -0,0 +1 @@
uid://d2vxdhi2fmqhd
+1 -1
View File
@@ -32,7 +32,7 @@ func _ready() -> void:
_tooltip = Label3D.new()
_tooltip.text = "Stick\n+Leather → Boots\n+Stick → Stick Armor\n+Rock → Wood Shield"
_tooltip.billboard = BaseMaterial3D.BILLBOARD_ENABLED
_tooltip.font_size = 28
_tooltip.font_size = 56
_tooltip.outline_size = 6
_tooltip.position = Vector3(0, 1.2, 0)
_tooltip.modulate = Color(1.0, 0.95, 0.8)