diff --git a/assets/models/buildings/building_home_A_blue.bin b/assets/models/buildings/building_home_A_blue.bin new file mode 100644 index 0000000..e39e8b6 Binary files /dev/null and b/assets/models/buildings/building_home_A_blue.bin differ diff --git a/assets/models/buildings/building_home_A_blue.gltf b/assets/models/buildings/building_home_A_blue.gltf new file mode 100644 index 0000000..885c574 --- /dev/null +++ b/assets/models/buildings/building_home_A_blue.gltf @@ -0,0 +1,136 @@ +{ + "asset" : { + "generator" : "Khronos glTF Blender I/O v3.4.50", + "version" : "2.0" + }, + "scene" : 0, + "scenes" : [ + { + "name" : "Scene", + "nodes" : [ + 0 + ] + } + ], + "nodes" : [ + { + "mesh" : 0, + "name" : "building_home_A_blue" + } + ], + "materials" : [ + { + "name" : "hexagons_medieval", + "pbrMetallicRoughness" : { + "baseColorTexture" : { + "index" : 0 + }, + "metallicFactor" : 0, + "roughnessFactor" : 0.5 + } + } + ], + "meshes" : [ + { + "name" : "building_home_A_blue", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "TEXCOORD_0" : 1, + "NORMAL" : 2 + }, + "indices" : 3, + "material" : 0 + } + ] + } + ], + "textures" : [ + { + "sampler" : 0, + "source" : 0 + } + ], + "images" : [ + { + "mimeType" : "image/png", + "name" : "hexagons_medieval", + "uri" : "hexagons_medieval.png" + } + ], + "accessors" : [ + { + "bufferView" : 0, + "componentType" : 5126, + "count" : 1540, + "max" : [ + 0.3959798812866211, + 0.9300001263618469, + 0.385000079870224 + ], + "min" : [ + -0.39597994089126587, + -2.086162709247219e-08, + -0.46865156292915344 + ], + "type" : "VEC3" + }, + { + "bufferView" : 1, + "componentType" : 5126, + "count" : 1540, + "type" : "VEC2" + }, + { + "bufferView" : 2, + "componentType" : 5126, + "count" : 1540, + "type" : "VEC3" + }, + { + "bufferView" : 3, + "componentType" : 5123, + "count" : 3033, + "type" : "SCALAR" + } + ], + "bufferViews" : [ + { + "buffer" : 0, + "byteLength" : 18480, + "byteOffset" : 0, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 12320, + "byteOffset" : 18480, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 18480, + "byteOffset" : 30800, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 6066, + "byteOffset" : 49280, + "target" : 34963 + } + ], + "samplers" : [ + { + "magFilter" : 9729, + "minFilter" : 9987 + } + ], + "buffers" : [ + { + "byteLength" : 55348, + "uri" : "building_home_A_blue.bin" + } + ] +} diff --git a/assets/models/buildings/building_home_A_blue.gltf.import b/assets/models/buildings/building_home_A_blue.gltf.import new file mode 100644 index 0000000..4889ad9 --- /dev/null +++ b/assets/models/buildings/building_home_A_blue.gltf.import @@ -0,0 +1,42 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://digqjcku7u6jw" +path="res://.godot/imported/building_home_A_blue.gltf-3d8bffb321af199d2bf47d5e9358bb70.scn" + +[deps] + +source_file="res://assets/models/buildings/building_home_A_blue.gltf" +dest_files=["res://.godot/imported/building_home_A_blue.gltf-3d8bffb321af199d2bf47d5e9358bb70.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 diff --git a/assets/models/buildings/hexagons_medieval.png b/assets/models/buildings/hexagons_medieval.png new file mode 100644 index 0000000..14cdc25 Binary files /dev/null and b/assets/models/buildings/hexagons_medieval.png differ diff --git a/assets/models/buildings/hexagons_medieval.png.import b/assets/models/buildings/hexagons_medieval.png.import new file mode 100644 index 0000000..8c580c2 --- /dev/null +++ b/assets/models/buildings/hexagons_medieval.png.import @@ -0,0 +1,41 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ikdyfxy2qnbi" +path.s3tc="res://.godot/imported/hexagons_medieval.png-ea132e7b0754db3463363d12b2f4f568.s3tc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} + +[deps] + +source_file="res://assets/models/buildings/hexagons_medieval.png" +dest_files=["res://.godot/imported/hexagons_medieval.png-ea132e7b0754db3463363d12b2f4f568.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 diff --git a/assets/models/characters/Knight.glb b/assets/models/characters/Knight.glb new file mode 100644 index 0000000..717b56c Binary files /dev/null and b/assets/models/characters/Knight.glb differ diff --git a/assets/models/characters/Knight.glb.import b/assets/models/characters/Knight.glb.import new file mode 100644 index 0000000..6115b77 --- /dev/null +++ b/assets/models/characters/Knight.glb.import @@ -0,0 +1,42 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://c7dnarple2ye6" +path="res://.godot/imported/Knight.glb-f3b84697960dc30f97048f59f901a6e9.scn" + +[deps] + +source_file="res://assets/models/characters/Knight.glb" +dest_files=["res://.godot/imported/Knight.glb-f3b84697960dc30f97048f59f901a6e9.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 diff --git a/assets/models/characters/Knight_knight_texture.png b/assets/models/characters/Knight_knight_texture.png new file mode 100644 index 0000000..a56eae7 Binary files /dev/null and b/assets/models/characters/Knight_knight_texture.png differ diff --git a/assets/models/characters/Knight_knight_texture.png.import b/assets/models/characters/Knight_knight_texture.png.import new file mode 100644 index 0000000..2358a37 --- /dev/null +++ b/assets/models/characters/Knight_knight_texture.png.import @@ -0,0 +1,44 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://n1j7b5ws4ee0" +path.s3tc="res://.godot/imported/Knight_knight_texture.png-fbfd6db275b893706e62960fa115ac3a.s3tc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} +generator_parameters={ +"md5": "af4707185c3e9844f7ed166c1a2e24f8" +} + +[deps] + +source_file="res://assets/models/characters/Knight_knight_texture.png" +dest_files=["res://.godot/imported/Knight_knight_texture.png-fbfd6db275b893706e62960fa115ac3a.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 diff --git a/assets/models/characters/Skeleton_Mage.glb b/assets/models/characters/Skeleton_Mage.glb new file mode 100644 index 0000000..5f85aea Binary files /dev/null and b/assets/models/characters/Skeleton_Mage.glb differ diff --git a/assets/models/characters/Skeleton_Mage.glb.import b/assets/models/characters/Skeleton_Mage.glb.import new file mode 100644 index 0000000..5df0fa7 --- /dev/null +++ b/assets/models/characters/Skeleton_Mage.glb.import @@ -0,0 +1,42 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://7sbngaphdxht" +path="res://.godot/imported/Skeleton_Mage.glb-dfda87ec6175e75ab440ca2eec40520e.scn" + +[deps] + +source_file="res://assets/models/characters/Skeleton_Mage.glb" +dest_files=["res://.godot/imported/Skeleton_Mage.glb-dfda87ec6175e75ab440ca2eec40520e.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 diff --git a/assets/models/characters/Skeleton_Mage_skeleton_texture.png b/assets/models/characters/Skeleton_Mage_skeleton_texture.png new file mode 100644 index 0000000..00bf24b Binary files /dev/null and b/assets/models/characters/Skeleton_Mage_skeleton_texture.png differ diff --git a/assets/models/characters/Skeleton_Mage_skeleton_texture.png.import b/assets/models/characters/Skeleton_Mage_skeleton_texture.png.import new file mode 100644 index 0000000..24be617 --- /dev/null +++ b/assets/models/characters/Skeleton_Mage_skeleton_texture.png.import @@ -0,0 +1,44 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://wjwg0opxh8we" +path.s3tc="res://.godot/imported/Skeleton_Mage_skeleton_texture.png-ddebdfcfc8bd13280cab68f2d8b07b2b.s3tc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} +generator_parameters={ +"md5": "661544b1e8ba10b5a0c98b638eae6d0b" +} + +[deps] + +source_file="res://assets/models/characters/Skeleton_Mage_skeleton_texture.png" +dest_files=["res://.godot/imported/Skeleton_Mage_skeleton_texture.png-ddebdfcfc8bd13280cab68f2d8b07b2b.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 diff --git a/assets/models/characters/Skeleton_Minion.glb b/assets/models/characters/Skeleton_Minion.glb new file mode 100644 index 0000000..3b7e7ee Binary files /dev/null and b/assets/models/characters/Skeleton_Minion.glb differ diff --git a/assets/models/characters/Skeleton_Minion.glb.import b/assets/models/characters/Skeleton_Minion.glb.import new file mode 100644 index 0000000..3dd92de --- /dev/null +++ b/assets/models/characters/Skeleton_Minion.glb.import @@ -0,0 +1,42 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://dkn5fqfvkqog5" +path="res://.godot/imported/Skeleton_Minion.glb-71f08c897190630c8e5ae9e5beda9052.scn" + +[deps] + +source_file="res://assets/models/characters/Skeleton_Minion.glb" +dest_files=["res://.godot/imported/Skeleton_Minion.glb-71f08c897190630c8e5ae9e5beda9052.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 diff --git a/assets/models/characters/Skeleton_Minion_skeleton_texture.png b/assets/models/characters/Skeleton_Minion_skeleton_texture.png new file mode 100644 index 0000000..00bf24b Binary files /dev/null and b/assets/models/characters/Skeleton_Minion_skeleton_texture.png differ diff --git a/assets/models/characters/Skeleton_Minion_skeleton_texture.png.import b/assets/models/characters/Skeleton_Minion_skeleton_texture.png.import new file mode 100644 index 0000000..b224441 --- /dev/null +++ b/assets/models/characters/Skeleton_Minion_skeleton_texture.png.import @@ -0,0 +1,44 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://caa8qxgnpgv61" +path.s3tc="res://.godot/imported/Skeleton_Minion_skeleton_texture.png-9dcb8889e4229fae505e24dc5a110852.s3tc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} +generator_parameters={ +"md5": "661544b1e8ba10b5a0c98b638eae6d0b" +} + +[deps] + +source_file="res://assets/models/characters/Skeleton_Minion_skeleton_texture.png" +dest_files=["res://.godot/imported/Skeleton_Minion_skeleton_texture.png-9dcb8889e4229fae505e24dc5a110852.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 diff --git a/assets/models/characters/Skeleton_Warrior.glb b/assets/models/characters/Skeleton_Warrior.glb new file mode 100644 index 0000000..769e85c Binary files /dev/null and b/assets/models/characters/Skeleton_Warrior.glb differ diff --git a/assets/models/characters/Skeleton_Warrior.glb.import b/assets/models/characters/Skeleton_Warrior.glb.import new file mode 100644 index 0000000..96523c3 --- /dev/null +++ b/assets/models/characters/Skeleton_Warrior.glb.import @@ -0,0 +1,42 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://cjgucsfp8qn1m" +path="res://.godot/imported/Skeleton_Warrior.glb-87a31fa24e48c23f04684ddfdaed2d10.scn" + +[deps] + +source_file="res://assets/models/characters/Skeleton_Warrior.glb" +dest_files=["res://.godot/imported/Skeleton_Warrior.glb-87a31fa24e48c23f04684ddfdaed2d10.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 diff --git a/assets/models/characters/Skeleton_Warrior_skeleton_texture.png b/assets/models/characters/Skeleton_Warrior_skeleton_texture.png new file mode 100644 index 0000000..00bf24b Binary files /dev/null and b/assets/models/characters/Skeleton_Warrior_skeleton_texture.png differ diff --git a/assets/models/characters/Skeleton_Warrior_skeleton_texture.png.import b/assets/models/characters/Skeleton_Warrior_skeleton_texture.png.import new file mode 100644 index 0000000..dcc36c7 --- /dev/null +++ b/assets/models/characters/Skeleton_Warrior_skeleton_texture.png.import @@ -0,0 +1,44 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cvee751avas5j" +path.s3tc="res://.godot/imported/Skeleton_Warrior_skeleton_texture.png-66c57b76e95467b6ce503b8825ef03ca.s3tc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} +generator_parameters={ +"md5": "661544b1e8ba10b5a0c98b638eae6d0b" +} + +[deps] + +source_file="res://assets/models/characters/Skeleton_Warrior_skeleton_texture.png" +dest_files=["res://.godot/imported/Skeleton_Warrior_skeleton_texture.png-66c57b76e95467b6ce503b8825ef03ca.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 diff --git a/scenes/enemy/enemy.tscn b/scenes/enemy/enemy.tscn index 07d319c..1af9693 100644 --- a/scenes/enemy/enemy.tscn +++ b/scenes/enemy/enemy.tscn @@ -3,17 +3,12 @@ [ext_resource type="Script" uid="uid://vy6hyqok0p8b" path="res://scenes/enemy/init.gd" id="1"] [ext_resource type="Script" uid="uid://b07aajhufqvb3" path="res://scenes/enemy/detection.gd" id="2"] [ext_resource type="Resource" uid="uid://cj1shmjwf0xeo" path="res://scenes/enemy/enemy_stats.tres" id="8"] +[ext_resource type="PackedScene" path="res://assets/models/characters/Skeleton_Minion.glb" id="9"] [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_1"] radius = 0.4 height = 1.5 -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_1"] -albedo_color = Color(0.8, 0.1, 0.1, 1) - -[sub_resource type="SphereMesh" id="SphereMesh_1"] -material = SubResource("StandardMaterial3D_1") - [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_2"] radius = 0.4 height = 1.5 @@ -40,8 +35,10 @@ stats = ExtResource("8") [node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=1011138038] shape = SubResource("CapsuleShape3D_1") -[node name="Mesh" type="MeshInstance3D" parent="." unique_id=1598094615] -mesh = SubResource("SphereMesh_1") +[node name="Mesh" type="Node3D" parent="." unique_id=1598094615] + +[node name="Model" parent="Mesh" instance=ExtResource("9")] +transform = Transform3D(-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, -0.75, 0) [node name="HitArea" type="Area3D" parent="." unique_id=893463784] collision_layer = 4 @@ -62,7 +59,7 @@ collision_layer = 0 shape = SubResource("SphereShape3D_1") [node name="Healthbar" type="Sprite3D" parent="." unique_id=1008728031] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, 0) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0) billboard = 1 [node name="SubViewport" type="SubViewport" parent="Healthbar" unique_id=1219060718] diff --git a/scenes/enemy/init.gd b/scenes/enemy/init.gd index 63f883b..5c4a32c 100644 --- a/scenes/enemy/init.gd +++ b/scenes/enemy/init.gd @@ -1,25 +1,56 @@ extends CharacterBody3D +const SKELETON_WARRIOR: PackedScene = preload("res://assets/models/characters/Skeleton_Warrior.glb") +const SKELETON_MAGE: PackedScene = preload("res://assets/models/characters/Skeleton_Mage.glb") + @export var stats: EnemyStats var gravity: float = ProjectSettings.get_setting("physics/3d/default_gravity") var spawn_scale: float = 1.0 -var hover_t: float = 0.0 -var mesh_base_y: float = 0.0 +var anim_player: AnimationPlayer = null +var current_anim: String = "" +var attack_lock_until: float = 0.0 +var is_dying: bool = false func _ready() -> void: add_to_group("enemies") if is_in_group("boss"): BossData.register(self, stats, spawn_scale) BossData.set_stat(self, "spawn_position", global_position) + _swap_model(SKELETON_MAGE, 1.3) else: EnemyData.register(self, stats, spawn_scale) EnemyData.set_stat(self, "spawn_position", global_position) EventBus.entity_died.connect(_on_entity_died) + EventBus.attack_executed.connect(_on_attack_executed) + call_deferred("_check_variant") + call_deferred("_init_anim") + +func _init_anim() -> void: + anim_player = get_node_or_null("Mesh/Model/AnimationPlayer") + _play_anim("Idle") + +func _check_variant() -> void: + if is_in_group("boss"): + return + if is_in_group("red_enemies") or is_in_group("invasion"): + _swap_model(SKELETON_WARRIOR, 1.0) + anim_player = get_node_or_null("Mesh/Model/AnimationPlayer") + _play_anim("Idle") + +func _swap_model(new_scene: PackedScene, scale_factor: float = 1.0) -> void: var mesh: Node3D = get_node_or_null("Mesh") - if mesh: - mesh_base_y = mesh.position.y - _apply_appearance(mesh) + if not mesh: + return + var old: Node = mesh.get_node_or_null("Model") + if old: + old.queue_free() + var new_model: Node3D = new_scene.instantiate() + new_model.name = "Model" + new_model.scale = Vector3(scale_factor, scale_factor, scale_factor) + new_model.position = Vector3(0, -0.75, 0) + new_model.rotation.y = PI + mesh.add_child(new_model) func _exit_tree() -> void: if is_in_group("boss"): @@ -28,29 +59,41 @@ func _exit_tree() -> void: EnemyData.deregister(self) func _on_entity_died(entity: Node) -> void: - if entity == self: - queue_free() + if entity != self: + return + is_dying = true + _play_anim("Death_A", false) + get_tree().create_timer(1.0).timeout.connect(queue_free) -func _process(delta: float) -> void: - hover_t += delta - var mesh: Node3D = get_node_or_null("Mesh") - if mesh: - mesh.position.y = mesh_base_y + sin(hover_t * 3.0) * 0.08 +func _on_attack_executed(attacker: Node, _pos: Vector3, _dir: Vector3, _damage: float) -> void: + if attacker != self: + return + _play_anim("1H_Melee_Attack_Chop", false) + attack_lock_until = Time.get_ticks_msec() / 1000.0 + 0.5 -func _apply_appearance(mesh: Node3D) -> void: - if mesh is MeshInstance3D: - var mat := StandardMaterial3D.new() - if is_in_group("boss"): - mat.albedo_color = Color(0.6, 0.15, 0.7, 1) - mat.emission_enabled = true - mat.emission = Color(0.8, 0.2, 0.9, 1) - mat.emission_energy_multiplier = 0.4 - else: - mat.albedo_color = Color(0.7, 0.25, 0.25, 1) - mat.emission_enabled = true - mat.emission = Color(0.9, 0.3, 0.2, 1) - mat.emission_energy_multiplier = 0.25 - (mesh as MeshInstance3D).material_override = mat +func _process(_delta: float) -> void: + if is_dying: + return + var now: float = Time.get_ticks_msec() / 1000.0 + if now < attack_lock_until: + return + if velocity.length() > 0.1: + _play_anim("Running_A") + else: + _play_anim("Idle") + +func _play_anim(anim_name: String, loop: bool = true) -> void: + if not anim_player: + return + if current_anim == anim_name: + return + if not anim_player.has_animation(anim_name): + return + var anim: Animation = anim_player.get_animation(anim_name) + if anim: + anim.loop_mode = Animation.LOOP_LINEAR if loop else Animation.LOOP_NONE + anim_player.play(anim_name) + current_anim = anim_name func _physics_process(delta: float) -> void: if not is_on_floor(): diff --git a/scenes/player/init.gd b/scenes/player/init.gd index dfdf588..16d0b11 100644 --- a/scenes/player/init.gd +++ b/scenes/player/init.gd @@ -2,6 +2,10 @@ extends CharacterBody3D @export var stats: PlayerStats +var anim_player: AnimationPlayer = null +var current_anim: String = "" +var attack_lock_until: float = 0.0 + func _ready() -> void: add_to_group("player") PlayerData.init_from_resource(stats) @@ -10,3 +14,46 @@ func _ready() -> void: PlayerData.returning_from_dungeon = false elif PlayerData.dungeon_cleared: PlayerData.clear_cache() + anim_player = get_node_or_null("Mesh/Model/AnimationPlayer") + _play_anim("Idle") + EventBus.attack_executed.connect(_on_attack_executed) + EventBus.entity_died.connect(_on_entity_died) + EventBus.player_respawned.connect(_on_player_respawned) + +func _process(_delta: float) -> void: + if not PlayerData.alive: + return + var now: float = Time.get_ticks_msec() / 1000.0 + if now < attack_lock_until: + return + if velocity.length() > 0.1: + _play_anim("Running_A") + else: + _play_anim("Idle") + +func _play_anim(anim_name: String, loop: bool = true) -> void: + if not anim_player: + return + if current_anim == anim_name: + return + if not anim_player.has_animation(anim_name): + return + var anim: Animation = anim_player.get_animation(anim_name) + if anim: + anim.loop_mode = Animation.LOOP_LINEAR if loop else Animation.LOOP_NONE + anim_player.play(anim_name) + current_anim = anim_name + +func _on_attack_executed(attacker: Node, _pos: Vector3, _dir: Vector3, _damage: float) -> void: + if attacker != self: + return + _play_anim("1H_Melee_Attack_Chop", false) + attack_lock_until = Time.get_ticks_msec() / 1000.0 + 0.5 + +func _on_entity_died(entity: Node) -> void: + if entity != PlayerData: + return + _play_anim("Death_A", false) + +func _on_player_respawned(_player: Node) -> void: + _play_anim("Idle") diff --git a/scenes/player/movement.gd b/scenes/player/movement.gd index 24c32bf..ffeafab 100644 --- a/scenes/player/movement.gd +++ b/scenes/player/movement.gd @@ -25,6 +25,11 @@ func _physics_process(delta: float) -> void: if direction: player.velocity.x = direction.x * PlayerData.speed player.velocity.z = direction.z * PlayerData.speed + var world_yaw: float = atan2(-direction.x, -direction.z) + var local_yaw: float = world_yaw - player.rotation.y + var mesh: Node3D = player.get_node_or_null("Mesh") as Node3D + if mesh: + mesh.rotation.y = lerp_angle(mesh.rotation.y, local_yaw, 10.0 * delta) else: player.velocity.x = move_toward(player.velocity.x, 0, PlayerData.speed) player.velocity.z = move_toward(player.velocity.z, 0, PlayerData.speed) diff --git a/scenes/player/player.tscn b/scenes/player/player.tscn index f0f603a..b828482 100644 --- a/scenes/player/player.tscn +++ b/scenes/player/player.tscn @@ -7,15 +7,12 @@ [ext_resource type="Script" uid="uid://b05nkuryipwny" path="res://scenes/player/targeting.gd" id="8"] [ext_resource type="Script" uid="uid://dhomrampxola4" path="res://scenes/player/role/role.gd" id="10"] [ext_resource type="Resource" uid="uid://btd0g0oiulssq" path="res://scenes/player/player_stats.tres" id="14"] +[ext_resource type="PackedScene" path="res://assets/models/characters/Knight.glb" id="15"] [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_1"] radius = 0.3 height = 1.8 -[sub_resource type="CapsuleMesh" id="CapsuleMesh_1"] -radius = 0.3 -height = 1.8 - [node name="Player" type="CharacterBody3D" unique_id=197716516] script = ExtResource("1") stats = ExtResource("14") @@ -23,8 +20,10 @@ stats = ExtResource("14") [node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=311205642] shape = SubResource("CapsuleShape3D_1") -[node name="Mesh" type="MeshInstance3D" parent="." unique_id=1514179122] -mesh = SubResource("CapsuleMesh_1") +[node name="Mesh" type="Node3D" parent="." unique_id=1514179122] + +[node name="Model" parent="Mesh" instance=ExtResource("15")] +transform = Transform3D(-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, -0.9, 0) [node name="CameraPivot" type="Node3D" parent="." unique_id=1881685457] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, 0) diff --git a/scenes/tavern/tavern.tscn b/scenes/tavern/tavern.tscn index 7779554..49206a0 100644 --- a/scenes/tavern/tavern.tscn +++ b/scenes/tavern/tavern.tscn @@ -2,24 +2,11 @@ [ext_resource type="Script" path="res://scenes/tavern/init.gd" id="1"] [ext_resource type="Resource" path="res://scenes/tavern/tavern_stats.tres" id="2"] +[ext_resource type="PackedScene" path="res://assets/models/buildings/building_home_A_blue.gltf" id="3"] [sub_resource type="BoxShape3D" id="BoxShape3D_tavern"] size = Vector3(5, 3, 5) -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_tavern"] -albedo_color = Color(0.45, 0.3, 0.15, 1) - -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_roof"] -albedo_color = Color(0.3, 0.15, 0.08, 1) - -[sub_resource type="BoxMesh" id="BoxMesh_tavern"] -size = Vector3(5, 3, 5) -material = SubResource("StandardMaterial3D_tavern") - -[sub_resource type="PrismMesh" id="PrismMesh_roof"] -size = Vector3(5.4, 2, 5.4) -material = SubResource("StandardMaterial3D_roof") - [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_health_bg"] bg_color = Color(0.3, 0.1, 0.1, 1) @@ -33,12 +20,10 @@ stats = ExtResource("2") [node name="CollisionShape3D" type="CollisionShape3D" parent="."] shape = SubResource("BoxShape3D_tavern") -[node name="Mesh" type="MeshInstance3D" parent="."] -mesh = SubResource("BoxMesh_tavern") +[node name="Mesh" type="Node3D" parent="."] -[node name="Roof" type="MeshInstance3D" parent="."] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.5, 0) -mesh = SubResource("PrismMesh_roof") +[node name="Model" parent="Mesh" instance=ExtResource("3")] +transform = Transform3D(2.5, 0, 0, 0, 2.5, 0, 0, 0, 2.5, 0, -1.5, 0) [node name="Healthbar" type="Sprite3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4, 0) diff --git a/systems/ai_system.gd b/systems/ai_system.gd index fc86752..d3c5213 100644 --- a/systems/ai_system.gd +++ b/systems/ai_system.gd @@ -54,6 +54,7 @@ func _chase(entity: Node, data: Dictionary, data_source: Node) -> void: direction.y = 0 entity.velocity.x = direction.x * base.speed entity.velocity.z = direction.z * base.speed + _face_target(entity, data["target"]) func _attack(entity: Node, data: Dictionary, data_source: Node, delta: float) -> void: data["attack_timer"] -= delta @@ -72,8 +73,21 @@ func _attack(entity: Node, data: Dictionary, data_source: Node, delta: float) -> data["attack_timer"] = base.attack_cooldown var scale: float = data.get("scale", 1.0) EventBus.damage_requested.emit(entity, data["target"], base.attack_damage * scale) + EventBus.attack_executed.emit(entity, entity.global_position, -entity.global_transform.basis.z, base.attack_damage * scale) entity.velocity.x = 0 entity.velocity.z = 0 + _face_target(entity, data["target"]) + +func _face_target(entity: Node3D, target: Node3D) -> void: + if not is_instance_valid(target): + return + var to_target: Vector3 = target.global_position - entity.global_position + to_target.y = 0 + if to_target.length() < 0.01: + return + var yaw: float = atan2(-to_target.x, -to_target.z) + var delta: float = get_physics_process_delta_time() + entity.rotation.y = lerp_angle(entity.rotation.y, yaw, 8.0 * delta) func _return_to_spawn(entity: Node, data: Dictionary, data_source: Node, delta: float) -> void: var spawn_pos: Vector3 = data["spawn_position"]