From dfbd2f34a5494e1fee5f4ee5432e6ad076aed7d4 Mon Sep 17 00:00:00 2001 From: Segey Lapin Date: Sun, 9 Jan 2022 02:40:04 +0300 Subject: [PATCH] GUI/AI improvements... --- autoload/characters.gd | 6 +- characters/vroid1-female.tscn | 25 +- characters/vroid1-man.tscn | 23 +- project.godot | 2 +- scripts/modules/character_hurtboxes.gd | 15 +- scripts/modules/cmdq.gd | 6 +- scripts/modules/npc_bandit.gd | 372 +++++++++++++++++++------ scripts/modules/npc_marker.gd | 2 +- scripts/modules/npc_mystress.gd | 2 +- scripts/modules/npc_student.gd | 2 +- scripts/modules/player_clothes.gd | 2 +- scripts/modules/player_controls.gd | 4 +- ui/main_menu.gd | 32 +++ ui/main_menu.tscn | 60 ++++ ui/save_game.gd | 97 +++++++ ui/save_game.tscn | 66 +++++ ui/theme.tres | 6 + ui/town_menu.gd | 25 ++ ui/town_menu.tscn | 45 +++ 19 files changed, 662 insertions(+), 130 deletions(-) create mode 100644 ui/main_menu.gd create mode 100644 ui/main_menu.tscn create mode 100644 ui/save_game.gd create mode 100644 ui/save_game.tscn create mode 100644 ui/theme.tres create mode 100644 ui/town_menu.gd create mode 100644 ui/town_menu.tscn diff --git a/autoload/characters.gd b/autoload/characters.gd index ce96efa..6fe99e5 100644 --- a/autoload/characters.gd +++ b/autoload/characters.gd @@ -540,6 +540,6 @@ func _physics_process(delta): var player = get_player() if !player: return - if player.has_meta("animation_tree") && !player.has_meta("vehicle"): - if streaming.can_spawn: - character_physics(player) +# if player.has_meta("animation_tree") && !player.has_meta("vehicle"): +# if streaming.can_spawn: +# character_physics(player) diff --git a/characters/vroid1-female.tscn b/characters/vroid1-female.tscn index b68ac1f..73b8406 100644 --- a/characters/vroid1-female.tscn +++ b/characters/vroid1-female.tscn @@ -179,7 +179,7 @@ nodes/TimeScale/position = Vector2( 580, 100 ) nodes/output/position = Vector2( 1120, 120 ) nodes/t1/node = SubResource( 26 ) nodes/t1/position = Vector2( 880, 100 ) -node_connections = [ "output", 0, "t1", "TimeScale", 0, "Animation", "t1", 0, "TimeScale", "t1", 1, "TimeScale 2", "TimeScale 2", 0, "Animation 2" ] +node_connections = [ "output", 0, "t1", "t1", 0, "TimeScale", "t1", 1, "TimeScale 2", "TimeScale 2", 0, "Animation 2", "TimeScale", 0, "Animation" ] [sub_resource type="AnimationNodeAnimation" id=28] animation = "walk1p2" @@ -211,7 +211,7 @@ nodes/TimeScale/position = Vector2( 620, 40 ) nodes/Transition/node = SubResource( 32 ) nodes/Transition/position = Vector2( 905, 264 ) nodes/output/position = Vector2( 1280, 120 ) -node_connections = [ "output", 0, "Transition", "TimeScale", 0, "Animation", "TimeScale 2", 0, "Animation 2", "Transition", 0, "TimeScale", "Transition", 1, "TimeScale 2" ] +node_connections = [ "output", 0, "Transition", "Transition", 0, "TimeScale", "Transition", 1, "TimeScale 2", "TimeScale 2", 0, "Animation 2", "TimeScale", 0, "Animation" ] [sub_resource type="AnimationNodeAnimation" id=34] animation = "07_01-walk" @@ -288,7 +288,7 @@ nodes/TimeScale/position = Vector2( 640, 200 ) nodes/Transition/node = SubResource( 59 ) nodes/Transition/position = Vector2( 860, 220 ) nodes/output/position = Vector2( 1080, 200 ) -node_connections = [ "output", 0, "Transition", "TimeScale", 0, "Animation", "TimeScale 2", 0, "Animation 2", "Transition", 1, "TimeScale 2" ] +node_connections = [ "output", 0, "Transition", "Transition", 1, "TimeScale 2", "TimeScale 2", 0, "Animation 2", "TimeScale", 0, "Animation" ] [sub_resource type="AnimationNodeAnimation" id=61] animation = "female-pray-startled1" @@ -354,7 +354,7 @@ nodes/attack2/position = Vector2( 1140, 300 ) nodes/output/position = Vector2( 1580, 180 ) nodes/speed/node = SubResource( 74 ) nodes/speed/position = Vector2( 540, 60 ) -node_connections = [ "speed", 0, "Animation", "output", 0, "attack2", "TimeScale", 0, "Animation 2", "attack2", 0, "attack1", "attack2", 1, "TimeScale 2", "attack1", 0, "speed", "attack1", 1, "TimeScale", "TimeScale 2", 0, "Animation 3" ] +node_connections = [ "speed", 0, "Animation", "output", 0, "attack2", "TimeScale 2", 0, "Animation 3", "attack2", 0, "attack1", "attack2", 1, "TimeScale 2", "attack1", 0, "speed", "attack1", 1, "TimeScale", "TimeScale", 0, "Animation 2" ] [sub_resource type="AnimationNodeAnimation" id=76] animation = "dagger-sacrifice-counter-p" @@ -648,7 +648,7 @@ nodes/blade_right/position = Vector2( 1400, 100 ) nodes/output/position = Vector2( 1820, -20 ) nodes/state/node = SubResource( 110 ) nodes/state/position = Vector2( 480, 120 ) -node_connections = [ "output", 0, "blade_right", "blade_right", 0, "blade_left", "blade_right", 1, "Animation 2", "blade_left", 0, "all_scale", "blade_left", 1, "Animation", "all_scale", 0, "state" ] +node_connections = [ "output", 0, "blade_right", "all_scale", 0, "state", "blade_left", 0, "all_scale", "blade_left", 1, "Animation", "blade_right", 0, "blade_left", "blade_right", 1, "Animation 2" ] [sub_resource type="AnimationNodeStateMachinePlayback" id=112] @@ -666,7 +666,7 @@ bones/101/bound_children = [ NodePath("wrist_r") ] transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -0.00418961, 0.00654769, 0.00506566 ) [node name="head" type="BoneAttachment" parent="skeleton/Skeleton" index="2"] -transform = Transform( 0.932316, 0.218868, -0.288047, -0.122982, 0.940534, 0.316554, 0.340181, -0.259705, 0.903776, -0.0353679, 1.31372, 0.0207836 ) +transform = Transform( 0.713409, 0.342413, -0.611461, -0.0945617, 0.911515, 0.400091, 0.694399, -0.227615, 0.682673, -0.0411225, 1.35382, -0.0195896 ) bone_name = "Head" [node name="marker_talk" type="Spatial" parent="skeleton/Skeleton/head" index="0"] @@ -696,7 +696,7 @@ transform = Transform( 1, -1.24197e-11, 0, 1.06852e-11, 1, -5.82077e-11, 0, 0, 1 [node name="female-face1" parent="skeleton/Skeleton/head/face" index="0" instance=ExtResource( 3 )] [node name="hips" type="BoneAttachment" parent="skeleton/Skeleton" index="3"] -transform = Transform( 0.988843, 0.0743826, -0.129405, 0.0739601, -0.997197, -0.00811786, -0.129657, -0.0015435, -0.991557, 0.000203862, 0.862472, -0.00645695 ) +transform = Transform( 0.94223, 0.0611767, 0.329466, 0.0446752, -0.997287, 0.0574523, 0.332118, -0.0394095, -0.942444, 0.000203859, 0.89952, -0.00645694 ) bone_name = "Hips" [node name="marker_dagger_sacrifice" type="Spatial" parent="skeleton/Skeleton/hips" index="0"] @@ -711,21 +711,21 @@ monitorable = false shape = SubResource( 2 ) [node name="wrist_r" type="BoneAttachment" parent="skeleton/Skeleton" index="4"] -transform = Transform( -0.155847, 0.968072, -0.196331, 0.907188, 0.218911, 0.359287, 0.390795, -0.122115, -0.912342, 0.21806, 0.798826, -0.0352511 ) +transform = Transform( -0.245569, 0.908447, -0.338258, 0.959945, 0.276457, 0.0455697, 0.134912, -0.313518, -0.939949, 0.210898, 0.839866, 0.0647882 ) bone_name = "wrist_ik_R" [node name="weapon_right" type="Spatial" parent="skeleton/Skeleton/wrist_r" index="0"] transform = Transform( 1, 0, 0, 0, -1.62921e-07, 1, 0, -1, -1.62921e-07, -0.08, 0, -0.01 ) [node name="wrist_l" type="BoneAttachment" parent="skeleton/Skeleton" index="5"] -transform = Transform( -0.119609, -0.729474, 0.673469, -0.929594, 0.320491, 0.182047, -0.34864, -0.604278, -0.716448, -0.256349, 0.818886, 0.0048945 ) +transform = Transform( -0.0838252, -0.864731, 0.495188, -0.980276, 0.160814, 0.114885, -0.178979, -0.47579, -0.861156, -0.181656, 0.840334, -0.0498495 ) bone_name = "wrist_ik_L" [node name="weapon_left" type="Spatial" parent="skeleton/Skeleton/wrist_l" index="0"] transform = Transform( 1, 0, 0, 0, -1.62921e-07, -1, 0, 1, -1.62921e-07, 0.08, 0, -0.01 ) [node name="chest" type="BoneAttachment" parent="skeleton/Skeleton" index="6"] -transform = Transform( 0.991647, -0.0337554, 0.124843, 0.0471192, 0.993257, -0.105626, -0.120448, 0.110622, 0.986529, -0.0143315, 1.02163, -0.0264497 ) +transform = Transform( 0.958586, -0.0332876, -0.283002, 0.0462008, 0.998108, 0.0390467, 0.281199, -0.0505137, 0.958342, -0.00285422, 1.06003, -0.0194018 ) bone_name = "Chest" [node name="chest_hurt" type="Area" parent="skeleton/Skeleton/chest" index="0"] @@ -740,7 +740,7 @@ shape = SubResource( 3 ) [node name="MeshInstance" type="MeshInstance" parent="skeleton/Skeleton" index="7"] [node name="neck" type="BoneAttachment" parent="skeleton/Skeleton" index="8"] -transform = Transform( 0.942651, -0.3302, -0.0496428, 0.329635, 0.94388, -0.0191404, 0.053161, 0.00168132, 0.998576, -0.0108881, 1.24374, 0.020659 ) +transform = Transform( 0.839515, -0.327886, -0.433348, 0.389612, 0.918993, 0.0594129, 0.378795, -0.218737, 0.899283, -0.0168142, 1.28569, -0.00337323 ) bone_name = "Neck" [node name="marker_neck_grab" type="Position3D" parent="skeleton/Skeleton/neck" index="0"] @@ -751,6 +751,7 @@ visible = false tree_root = SubResource( 111 ) anim_player = NodePath("../AnimationPlayer") active = true +process_mode = 0 root_motion_track = NodePath("skeleton/Skeleton:root") parameters/all_scale/scale = 1.0 parameters/blade_left/blend_amount = 0.0 @@ -768,7 +769,7 @@ parameters/state/kneel/TimeScale/scale = 1.0 parameters/state/locomotion/loc/blend_position = Vector2( 0.00252736, 0.00604224 ) parameters/state/locomotion/loc/0/TimeScale/scale = 2.0 "parameters/state/locomotion/loc/0/TimeScale 2/scale" = 1.5 -parameters/state/locomotion/loc/0/t1/current = 0 +parameters/state/locomotion/loc/0/t1/current = 1 parameters/state/locomotion/loc/1/TimeScale/scale = 1.0 "parameters/state/locomotion/loc/1/TimeScale 2/scale" = 1.0 parameters/state/locomotion/loc/1/Transition/current = 1 diff --git a/characters/vroid1-man.tscn b/characters/vroid1-man.tscn index 4d1fc92..052d804 100644 --- a/characters/vroid1-man.tscn +++ b/characters/vroid1-man.tscn @@ -316,7 +316,7 @@ nodes/TimeScale/position = Vector2( 780, 260 ) nodes/Transition/node = SubResource( 118 ) nodes/Transition/position = Vector2( 500, 280 ) nodes/output/position = Vector2( 1000, 260 ) -node_connections = [ "output", 0, "TimeScale", "TimeScale", 0, "Transition", "Transition", 0, "Animation", "Transition", 1, "Animation 2" ] +node_connections = [ "output", 0, "TimeScale", "Transition", 0, "Animation", "Transition", 1, "Animation 2", "TimeScale", 0, "Transition" ] [sub_resource type="AnimationNodeAnimation" id=119] animation = "turn-right" @@ -344,7 +344,7 @@ nodes/TimeScale/position = Vector2( 840, 260 ) nodes/Transition/node = SubResource( 120 ) nodes/Transition/position = Vector2( 560, 260 ) nodes/output/position = Vector2( 1060, 260 ) -node_connections = [ "output", 0, "TimeScale", "TimeScale", 0, "Transition", "Transition", 0, "Animation", "Transition", 1, "Animation 2" ] +node_connections = [ "output", 0, "TimeScale", "Transition", 0, "Animation", "Transition", 1, "Animation 2", "TimeScale", 0, "Transition" ] [sub_resource type="AnimationNodeAnimation" id=123] animation = "dagger-sacrifice-counter-a" @@ -376,7 +376,7 @@ nodes/TimeScale/position = Vector2( 700, 140 ) nodes/Transition/node = SubResource( 125 ) nodes/Transition/position = Vector2( 940, 140 ) nodes/output/position = Vector2( 1240, 140 ) -node_connections = [ "output", 0, "Transition", "TimeScale", 0, "Animation", "TimeScale 2", 0, "Animation 2", "Transition", 0, "TimeScale", "Transition", 1, "TimeScale 2" ] +node_connections = [ "output", 0, "Transition", "Transition", 0, "TimeScale", "Transition", 1, "TimeScale 2", "TimeScale 2", 0, "Animation 2", "TimeScale", 0, "Animation" ] [sub_resource type="AnimationNodeStateMachineTransition" id=55] @@ -527,7 +527,7 @@ nodes/blade_right/position = Vector2( 680, 320 ) nodes/output/position = Vector2( 1040, 120 ) nodes/state/node = SubResource( 70 ) nodes/state/position = Vector2( -179, 86 ) -node_connections = [ "output", 0, "blade_right", "blade_right", 0, "blade_left", "blade_right", 1, "Animation 2", "blade_left", 0, "state", "blade_left", 1, "Animation" ] +node_connections = [ "output", 0, "blade_right", "blade_left", 0, "state", "blade_left", 1, "Animation", "blade_right", 0, "blade_left", "blade_right", 1, "Animation 2" ] [sub_resource type="AnimationNodeStateMachinePlayback" id=72] @@ -543,7 +543,7 @@ bones/94/bound_children = [ NodePath("wrist_r") ] bones/96/bound_children = [ NodePath("wrist_l") ] [node name="wrist_r" type="BoneAttachment" parent="Skeleton" index="2"] -transform = Transform( 0.0279129, 0.998728, 0.041974, 0.0839921, -0.0441852, 0.995486, 0.996075, -0.0242614, -0.0851187, 0.24008, 1.0159, -0.113418 ) +transform = Transform( 0.0279129, 0.998728, 0.041974, 0.083992, -0.0441852, 0.995486, 0.996075, -0.0242614, -0.0851186, 0.24008, 1.0159, -0.0689935 ) bone_name = "wrist_ik_r" [node name="marker_wrist_r_grab" type="Position3D" parent="Skeleton/wrist_r" index="0"] @@ -554,7 +554,7 @@ visible = false transform = Transform( -1.62921e-07, -1, 0, -1.62921e-07, 2.65431e-14, 1, -1, 1.62921e-07, -1.62921e-07, -0.0452205, -0.00161505, -0.0947611 ) [node name="wrist_l" type="BoneAttachment" parent="Skeleton" index="3"] -transform = Transform( 0.531637, -0.84656, 0.0264325, -0.0845947, -0.0220212, 0.996172, -0.842737, -0.531838, -0.0833217, -0.202819, 1.03678, -0.00230364 ) +transform = Transform( 0.531637, -0.84656, 0.0264325, -0.0845947, -0.0220212, 0.996172, -0.842737, -0.531838, -0.0833217, -0.202819, 1.02836, -0.0471478 ) bone_name = "wrist_ik_l" [node name="marker_wrist_l_grab" type="Position3D" parent="Skeleton/wrist_l" index="0"] @@ -565,7 +565,7 @@ visible = false transform = Transform( -1.62921e-07, 1, 0, 1.62921e-07, 2.65431e-14, -1, -1, -1.62921e-07, -1.62921e-07, 0.04, -0.01, -0.089 ) [node name="head" type="BoneAttachment" parent="Skeleton" index="4"] -transform = Transform( 0.985928, 0.0311576, -0.16424, 0.0314512, 0.93036, 0.365296, 0.164184, -0.365322, 0.916287, -0.0322545, 1.69764, -0.00238798 ) +transform = Transform( 0.998981, -0.0174369, -0.0416214, 0.0314635, 0.930306, 0.365432, 0.0323486, -0.366369, 0.929906, -0.0329707, 1.69764, -0.0053772 ) bone_name = "J_Bip_C_Head" [node name="marker_talk" type="Position3D" parent="Skeleton/head" index="0"] @@ -592,7 +592,7 @@ transform = Transform( 0.967007, -0.0921614, 0.237496, 0.0940632, 0.995561, 0.00 shape = SubResource( 149 ) [node name="hips" type="BoneAttachment" parent="Skeleton" index="5"] -transform = Transform( 0.980587, -0.131394, 0.145552, 0.150098, 0.980611, -0.125986, -0.126176, 0.145387, 0.981296, 0.000514592, 1.10104, -0.0117666 ) +transform = Transform( 0.987964, -0.143962, 0.0565838, 0.150106, 0.98061, -0.125986, -0.0373495, 0.132963, 0.990417, 0.000514592, 1.10104, -0.0117666 ) bone_name = "J_Bip_C_Hips" [node name="marker_hips_action" type="Position3D" parent="Skeleton/hips" index="0"] @@ -608,7 +608,7 @@ monitorable = false shape = SubResource( 148 ) [node name="neck" type="BoneAttachment" parent="Skeleton" index="6"] -transform = Transform( 0.991482, -0.0457548, 0.121939, 0.0262054, 0.987196, 0.157347, -0.127577, -0.152812, 0.979986, -0.0277608, 1.60068, 0.0126202 ) +transform = Transform( 0.998943, -0.0318141, 0.033183, 0.0262132, 0.987195, 0.157347, -0.037764, -0.156311, 0.986985, -0.0298461, 1.60068, 0.00997471 ) bone_name = "J_Bip_C_Neck" [node name="marker_neck_grab" type="Position3D" parent="Skeleton/neck" index="0"] @@ -616,7 +616,7 @@ transform = Transform( 0.998758, -0.00781338, 0.0492147, 0.00787775, 0.999969, - visible = false [node name="penis_2" type="BoneAttachment" parent="Skeleton" index="7"] -transform = Transform( 0.980587, 0.061167, -0.186302, 0.150098, -0.845509, 0.512431, -0.126176, -0.530446, -0.838276, 0.00514091, 0.991264, -0.106399 ) +transform = Transform( 0.987964, 0.108698, -0.110052, 0.150106, -0.845508, 0.51243, -0.0373501, -0.522782, -0.851648, 0.0136458, 0.991264, -0.105598 ) bone_name = "penis2" [node name="marker_penis_action" type="Position3D" parent="Skeleton/penis_2" index="0"] @@ -624,7 +624,7 @@ transform = Transform( 0.998824, -0.0252848, -0.0413812, 0.0249792, 0.999657, -0 visible = false [node name="chest" type="BoneAttachment" parent="Skeleton" index="8"] -transform = Transform( 0.991482, -0.0190115, 0.128848, 0.026214, 0.998173, -0.0544356, -0.127578, 0.0573495, 0.990169, -0.0229915, 1.33823, -0.00424174 ) +transform = Transform( 0.998943, -0.0241071, 0.0391486, 0.0262218, 0.998173, -0.0544354, -0.0377648, 0.0554043, 0.997749, -0.0235756, 1.33823, -0.00638926 ) bone_name = "J_Bip_C_Chest" [node name="chest_hurt" type="Area" parent="Skeleton/chest" index="0"] @@ -639,6 +639,7 @@ shape = SubResource( 147 ) tree_root = SubResource( 71 ) anim_player = NodePath("../AnimationPlayer") active = true +process_mode = 0 root_motion_track = NodePath("Skeleton:Root") parameters/blade_left/blend_amount = 0.0 parameters/blade_right/blend_amount = 0.0 diff --git a/project.godot b/project.godot index 6b96325..16fc57b 100644 --- a/project.godot +++ b/project.godot @@ -109,7 +109,7 @@ limits/command_queue/multithreading_queue_size_kb=512 [physics] -common/physics_jitter_fix=1.2 +common/physics_fps=150 3d/physics_engine="Bullet" [rendering] diff --git a/scripts/modules/character_hurtboxes.gd b/scripts/modules/character_hurtboxes.gd index 0cb7d12..c5a7097 100644 --- a/scripts/modules/character_hurtboxes.gd +++ b/scripts/modules/character_hurtboxes.gd @@ -5,15 +5,19 @@ var blood = preload("res://scenes/decals/blood.tscn") var blood_decal = preload("res://scenes/decals/blood1-decal.gltf") var rnd var initialized = false +var root func init(tick): assert(!initialized) if initialized: + printerr("already initialized") return - var root = get_character() + root = get_character(tick) if !root: + printerr("no character?") return var cam = root.get_viewport().get_camera() if !cam.has_meta("player"): + printerr("no player?") return var queue = [root] var hurtboxes = [] @@ -29,9 +33,9 @@ func init(tick): e.connect("area_entered", self, "area_hit", [e]) rnd = RandomNumberGenerator.new() rnd.randomize() + print("initialized ok") initialized = true func area_hit(area, e): - var root = get_character() if area.is_in_group("weapon_hit"): var mo = area.get_meta("owner") if mo == root: @@ -63,14 +67,16 @@ func area_hit(area, e): func update_physics(tick, delta): assert(initialized) - var root = get_character() + root = get_character(tick) if !root: + printerr("no character?") assert(!initialized) return FAILED var space_state: PhysicsDirectSpaceState = root.get_world().direct_space_state var offsets = [Vector3(0, -2, 0)] var cam = root.get_viewport().get_camera() if !cam.has_meta("player"): + printerr("no player?") assert(!initialized) return FAILED var player = cam.get_meta("player") @@ -97,6 +103,9 @@ func update_physics(tick, delta): # var rot = PI * 2.0 * rnd.randf() # decal.global_transform.basis = Basis(normal).scaled(Vector3(scale, 1.0, scale)).rotated(normal, rot) return ERR_BUSY +func stop(tick): + printerr("Why stopped?") + assert(false) func update(tick, delta): return ERR_BUSY diff --git a/scripts/modules/cmdq.gd b/scripts/modules/cmdq.gd index d50005e..bba13ee 100644 --- a/scripts/modules/cmdq.gd +++ b/scripts/modules/cmdq.gd @@ -14,8 +14,8 @@ func init(tick): # process_priority = 0 pass -func can_walk_there(dest: Vector3) -> bool: - var root = get_character() +func can_walk_there(tick: AITick, dest: Vector3) -> bool: + var root = get_character(tick) var space: PhysicsDirectSpaceState = root.get_world().get_direct_space_state() var result = space.intersect_ray(root.global_transform.origin, dest, [root]) if result.has("collider"): @@ -24,7 +24,7 @@ func can_walk_there(dest: Vector3) -> bool: return true func update_physics(tick, delta): - var root = get_character() + var root = get_character(tick) var orientation: Transform assert(root.has_meta("skeleton")) diff --git a/scripts/modules/npc_bandit.gd b/scripts/modules/npc_bandit.gd index 77c3db8..c0dda65 100644 --- a/scripts/modules/npc_bandit.gd +++ b/scripts/modules/npc_bandit.gd @@ -7,7 +7,6 @@ extends AIScriptModule # Called when the node enters the scene tree for the first time. -var root var skel var hair_skel var name @@ -41,14 +40,16 @@ var init_blackboard = { "dot": 0.0 } -func look_at(ch): +func look_at(tick, ch): + var root = get_character(tick) var current = root.global_transform var at = ch.global_transform.origin at.y = current.origin.y root.global_transform = current.looking_at(at, Vector3.UP) -func combat_event(ev, data): - var cam = get_character().get_viewport().get_camera() +func combat_event(ev, data, blackboard): + var root = blackboard.self + var cam = root.get_viewport().get_camera() var player if cam: player = cam.get_meta("player") @@ -62,7 +63,8 @@ func combat_event(ev, data): var dst = where.distance_squared_to(curpos) if dst < guard_distance * guard_distance: if who == player: - blackboard_set("guard", true) + blackboard["guard"] = true +# blackboard_set(tick, "melee_damage", true) "damage": var who = data[0] var weapon = data[1] @@ -72,21 +74,23 @@ func combat_event(ev, data): var dst = where.distance_squared_to(curpos) if dst < attack_distance * attack_distance: if who == player: - blackboard_set("melee_damage", true) + blackboard["melee_damage"] = true +# blackboard_set(tick, "melee_damage", true) -var initialized = false func init(tick): - assert(!initialized) + assert(tick) + assert(!get_memory(tick).has("initialized")) name = "bandit_ai" - root = get_character() + var root = get_character(tick) for e in init_blackboard.keys(): - blackboard_set(e, init_blackboard[e]) + blackboard_set(tick, e, init_blackboard[e]) + blackboard_set(tick, "self", root) assert(root.has_meta("skeleton")) rnd = RandomNumberGenerator.new() rnd.randomize() root.add_to_group("bandits") root.add_to_group("bandit") - combat.connect("event", self, "combat_event") + combat.connect("event", self, "combat_event", [blackboard_get_dict(tick)]) var character_data = root.get_meta("character_data") if character_data.sex == "female": @@ -105,7 +109,7 @@ func init(tick): for e in conf_behaviors.keys(): if !run_behaviors.has(e): run_behaviors[e] = conf_behaviors[e].new() - initialized = true + get_memory(tick).initialized = true var cooldown = 0.0 class base_bhv: @@ -432,85 +436,269 @@ var conf_behaviors: = { } var pdst = INF -func calc_utility(utility: String): +class health_consideration extends AIUtilityScriptedConsideration: + func evalute(tick, delta): + if blackboard_get(tick, "health") <= 0.0: + return 0.0 + var ret = blackboard_get(tick, "health") / 100.0 + return clamp(ret, 0.0, 1.0) +class no_melee_weapon_equipped_consideration extends AIUtilityScriptedConsideration: + func evalute(tick, delta): + if !blackboard_get(tick, "melee_weapon_equipped"): + return 1.0 + return 0.0 +class threat_consideration extends AIUtilityScriptedConsideration: + const engage_distance = 20.0 + func evalute(tick, delta): + if blackboard_get(tick, "enemy_distance") < engage_distance * engage_distance: + return 1.0 + return 0.0 +class enemy_far_consideration extends AIUtilityScriptedConsideration: + func evalute(tick, delta): + if blackboard_get(tick, "enemy_distance") < 1.6 * 1.6: + return 0.0 + return 1.0 +class half_or_more_stamina_consideration extends AIUtilityScriptedConsideration: + func evalute(tick, delta): + if blackboard_get(tick, "stamina") > 50.0: + return 1.0 + return 0.0 +class has_melee_weapon_equipped_consideration extends AIUtilityScriptedConsideration: + func evalute(tick, delta): + if blackboard_get(tick, "melee_weapon_equipped"): + return 1.0 + return 0.0 +class melee_attack_ready_consideration extends AIUtilityScriptedConsideration: + func evalute(tick, delta): + if blackboard_get(tick, "attack_cooldown") <= 0.0: + return 1.0 + return 0.0 +class twenty_or_more_stamina_consideration extends AIUtilityScriptedConsideration: + func evalute(tick, delta): + if blackboard_get(tick, "stamina") > 20.0: + return 1.0 + return 0.0 +class melee_attack_distance_consideration extends AIUtilityScriptedConsideration: + const attack_distance = 2.0 + func evalute(tick, delta): + if blackboard_get(tick, "enemy_distance") < attack_distance * attack_distance: + return 1.0 + return 0.0 +class need_healing_consideration extends AIUtilityScriptedConsideration: + func evalute(tick, delta): + if blackboard_get(tick, "health") >= 100.0: + return 0.0 + var ret = 1.0 - blackboard_get(tick, "health") / 100.0 + return clamp(ret, 0.0, 1.0) +class need_rest_consideration extends AIUtilityScriptedConsideration: + func evalute(tick, delta): + if blackboard_get(tick, "stamina") >= 100.0: + return 0.0 + return clamp(1.0 - blackboard_get(tick, "stamina") / 100.0, 0.0, 1.0) +class critical_health_consideration extends AIUtilityScriptedConsideration: + func evalute(tick, delta): + if blackboard_get(tick, "health") < 10.0: + return 1.0 + return 0.0 +class critical_stamina_consideration extends AIUtilityScriptedConsideration: + func evalute(tick, delta): + if blackboard_get(tick, "stamina") < 10.0: + return 1.0 + return 0.0 +class flee_or_more_distance_consideration extends AIUtilityScriptedConsideration: + const flee_distance = 5.0 + func evalute(tick, delta): + if blackboard_get(tick, "enemy_distance") >= flee_distance * flee_distance: + return 1.0 + return 0.0 +class dangerous_distance_consideration extends AIUtilityScriptedConsideration: + const flee_distance = 5.0 + func evalute(tick, delta): + if blackboard_get(tick, "enemy_distance") < flee_distance * flee_distance: + return 1.0 + return 0.0 +class ready_to_flee_consideration extends AIUtilityScriptedConsideration: + func evalute(tick, delta): + if blackboard_get(tick, "flee_cooldown") < 0.0: + return 1.0 + return 0.0 +class has_energy_consideration extends AIUtilityScriptedConsideration: + func evalute(tick, delta): + if blackboard_get(tick, "stamina") >= 10.0: + return 1.0 + return 0.0 +class ready_to_guard_consideration extends AIUtilityScriptedConsideration: + func evalute(tick, delta): + if blackboard_get(tick, "guard_cooldown") < 0.0: + return 1.0 + return 0.0 +class guarding_consideration extends AIUtilityScriptedConsideration: + func evalute(tick, delta): + if blackboard_get(tick, "guard"): + return 1.0 + return 0.0 +class melee_damage_consideration extends AIUtilityScriptedConsideration: + func evalute(tick, delta): + if blackboard_get(tick, "melee_damage"): + return 1.0 + return 0.0 +var considerations_data = { + "take_melee_weapon": { + "considerations": [ + {"c": health_consideration.new(), "score": 1.0}, + {"c": no_melee_weapon_equipped_consideration.new(), "score": 1.0}, + {"c": threat_consideration.new(), "score": 1.0} + ], + }, + "approach": { + "considerations": [ + {"c": health_consideration.new(), "score": 1.0}, + {"c": enemy_far_consideration.new(), "score": 1.0}, + {"c": half_or_more_stamina_consideration.new(), "score": 1.0}, + {"c": threat_consideration.new(), "score": 1.0} + ], + }, + "melee_attack": { + "considerations": [ + {"c": health_consideration.new(), "score": 1.0}, + {"c": has_melee_weapon_equipped_consideration.new(), "score": 1.0}, + {"c": melee_attack_ready_consideration.new(), "score": 1.0}, + {"c": twenty_or_more_stamina_consideration.new(), "score": 1.0}, + {"c": melee_attack_distance_consideration.new(), "score": 1.0} + ], + }, + "flee": { + "considerations": [ + {"c": health_consideration.new(), "score": 1.0}, + {"c": ready_to_flee_consideration.new(), "score": 1.0}, + {"c": has_energy_consideration.new(), "score": 1.0}, + {"c": dangerous_distance_consideration.new(), "score": 1.0}, + ], + }, + "guard": { + "considerations": [ + {"c": health_consideration.new(), "score": 1.0}, + {"c": ready_to_guard_consideration.new(), "score": 1.0}, + {"c": guarding_consideration.new(), "score": 1.0}, + ], + }, + "unconcious": { + "considerations": [ + {"c": critical_health_consideration.new(), "score": 1.0} + ], + }, + "rest": { + "considerations": [ + {"c": critical_stamina_consideration.new(), "score": 1.0}, + {"c": flee_or_more_distance_consideration.new(), "score": 1.0} + ], + }, + "get_melee_damage": { + "considerations": [ + {"c": health_consideration.new(), "score": 1.0}, + {"c": melee_damage_consideration.new(), "score": 1.0}, + ] + } +} +func calc_utility(tick: AITick, utility: String, delta: float): + var v = 0.0 + if considerations_data.has(utility): + v = 1.0 + for b in considerations_data[utility].considerations: + assert(b.c) + v *= b.c._evalute(tick, delta) * b.score + if v <= 0.0: + break match utility: "take_melee_weapon": - if blackboard_get("health") <= 0.0: - return 0.0 - if blackboard_get("melee_weapon_equipped"): - return 0.0 - else: - if blackboard_get("enemy_distance") < engage_distance * engage_distance: - return 110.0 + v *= 110.0 +# if blackboard_get(tick, "health") <= 0.0: +# return 0.0 +# if blackboard_get(tick, "melee_weapon_equipped"): +# return 0.0 +# else: +# if blackboard_get(tick, "enemy_distance") < engage_distance * engage_distance: +# return 110.0 "approach": - if blackboard_get("health") <= 0.0: - return 0.0 - if blackboard_get("enemy_distance") < 1.6 * 1.6: - return 0.0 - if blackboard_get("stamina") > 50.0 && blackboard_get("enemy_distance") < engage_distance * engage_distance: - return 10.0 + (blackboard_get("enemy_distance") - 10.0) / 6.0 + v *= 100.0 +# if blackboard_get(tick, "health") <= 0.0: +# return 0.0 +# if blackboard_get(tick, "enemy_distance") < 1.6 * 1.6: +# return 0.0 +# if blackboard_get(tick, "stamina") > 50.0 && blackboard_get(tick, "enemy_distance") < engage_distance * engage_distance: +# return 10.0 + (blackboard_get(tick, "enemy_distance") - 10.0) / 6.0 "melee_attack": - if blackboard_get("health") <= 0.0: - return 0.0 - if blackboard_get("melee_weapon_equipped"): - if blackboard_get("attack_cooldown") <= 0.0: - var d = attack_distance * attack_distance - if blackboard_get("stamina") > 20.0 && blackboard_get("enemy_distance") <= d: - return 50.0 + v *= 50.0 +# if blackboard_get(tick, "health") <= 0.0: +# return 0.0 +# if blackboard_get(tick, "melee_weapon_equipped"): +# if blackboard_get(tick, "attack_cooldown") <= 0.0: +# var d = attack_distance * attack_distance +# if blackboard_get(tick, "stamina") > 20.0 && blackboard_get(tick, "enemy_distance") <= d: +# return 50.0 "flee": - if blackboard_get("health") <= 0.0: - return 0.0 - if blackboard_get("flee_cooldown") > 0.0: - return 0.0 - if blackboard_get("stamina") <= 50.0 && blackboard_get("stamina") > 10.0 && blackboard_get("enemy_distance") < flee_distance * flee_distance: - return 100.0 + clamp((100.0 - blackboard_get("stamina")), 0, 90.0) * 2.0 - if blackboard_get("stamina") <= 10.0 && blackboard_get("enemy_distance") <= flee_distance * flee_distance * 0.5: - return 250.0 - if blackboard_get("stamina") <= 50.0 && blackboard_get("enemy_distance") < engage_distance * engage_distance: - if blackboard_get("randf") < 0.3: - return 100.0 - if blackboard_get("enemy_distance") < 1.4 * 1.4: - return 150.0 - if blackboard_get("health") < 50 && blackboard_get("health") > 15: - return 160 + v *= 300.0 +# if blackboard_get(tick, "health") <= 0.0: +# return 0.0 +# if blackboard_get(tick, "flee_cooldown") > 0.0: +# return 0.0 +# if blackboard_get(tick, "stamina") <= 50.0 && blackboard_get(tick, "stamina") > 10.0 && blackboard_get(tick, "enemy_distance") < flee_distance * flee_distance: +# return 100.0 + clamp((100.0 - blackboard_get(tick, "stamina")), 0, 90.0) * 2.0 +# if blackboard_get(tick, "stamina") <= 10.0 && blackboard_get(tick, "enemy_distance") <= flee_distance * flee_distance * 0.5: +# return 250.0 +# if blackboard_get(tick, "stamina") <= 50.0 && blackboard_get(tick, "enemy_distance") < engage_distance * engage_distance: +# if blackboard_get(tick, "randf") < 0.3: +# return 100.0 +# if blackboard_get(tick, "enemy_distance") < 1.4 * 1.4: +# return 150.0 +# if blackboard_get(tick, "health") < 50 && blackboard_get(tick, "health") > 15: +# return 160 "guard": - if blackboard_get("health") <= 0.0: - return 0.0 - if blackboard_get("guard_cooldown") > 0.0: - return 0.0 - elif blackboard_get("guard"): - blackboard_set("guard", false) - return 300.0 -# elif blackboard_get("enemy_distance") < guard_distance * guard_distance * 0.3 && blackboard_get("stamina") > 10.0: + if blackboard_get(tick, "guard"): + blackboard_set(tick, "guard", false) + v *= 900.0 +# if blackboard_get(tick, "health") <= 0.0: +# return 0.0 +# if blackboard_get(tick, "guard_cooldown") > 0.0: +# return 0.0 +# elif blackboard_get(tick, "guard"): +# blackboard_set(tick, "guard", false) +# return 400.0 +# elif blackboard_get(tick, "enemy_distance") < guard_distance * guard_distance * 0.3 && blackboard_get(tick, "stamina") > 10.0: # return 80 -# elif blackboard_get("enemy_distance") < attack_distance * attack_distance * 0.3: +# elif blackboard_get(tick, "enemy_distance") < attack_distance * attack_distance * 0.3: # return 10.0 "unconcious": - if blackboard_get("health") < 10: - return 2000 + v *= 2000.0 +# if blackboard_get(tick, "health") < 10: +# return 2000 "rest": - if blackboard_get("stamina") >= 100.0: - return 0.0 - if blackboard_get("stamina") <= 10.0 && blackboard_get("enemy_distance") >= flee_distance * flee_distance: - return 100.0 + blackboard_get("enemy_distance") / 10.0 + v *= 150.0 +# if blackboard_get(tick, "stamina") >= 100.0: +# return 0.0 +# if blackboard_get(tick, "stamina") <= 10.0 && blackboard_get(tick, "enemy_distance") >= flee_distance * flee_distance: +# return 100.0 + blackboard_get(tick, "enemy_distance") / 10.0 "get_melee_damage": - if blackboard_get("health") <= 0.0: - return 0.0 - if blackboard_get("melee_damage"): - blackboard_set("melee_damage", false) - print("DAMAGE2 ", blackboard_get("health")) - return 1000 + v *= 3000.0 + if blackboard_get(tick, "melee_damage"): + blackboard_set(tick, "melee_damage", false) +# if blackboard_get(tick, "health") <= 0.0: +# return 0.0 +# if blackboard_get(tick, "melee_damage"): +# blackboard_set(tick, "melee_damage", false) +# print("DAMAGE2 ", blackboard_get(tick, "health")) +# return 1000 _: assert(false) - return 0.0 + return v var last_behavior -func select_behavior(): +func select_behavior(tick, delta): var best_behavior var best_utility best_behavior = "rest" best_utility = 0.0 for e in conf_behaviors.keys(): - var utility = calc_utility(e) + var utility = calc_utility(tick, e, delta) if e == last_behavior: utility *= 2.0 if best_utility < utility: @@ -524,21 +712,23 @@ var last_running = [] var current_running = [] var run_behaviors = {} func update_physics(tick, delta): - assert(initialized) + assert(get_memory(tick).initialized) + var root = get_character(tick) assert(root) var cam = root.get_viewport().get_camera() if !cam: return if !cam.has_meta("player"): return + blackboard_set(tick, "self", get_character(tick)) var space: PhysicsDirectSpaceState = root.get_world().get_direct_space_state() var o = root.global_transform.origin var p = cam.get_meta("player").global_transform pdst = o.distance_squared_to(p.origin) - blackboard_set("enemy_distance", pdst) - blackboard_set("randf", rnd.randf()) - blackboard_set("enemy_pos", p.origin) - blackboard_set("space", space) + blackboard_set(tick, "enemy_distance", pdst) + blackboard_set(tick, "randf", rnd.randf()) + blackboard_set(tick, "enemy_pos", p.origin) + blackboard_set(tick, "space", space) # var adest = o + (p.origin - o).normalized() * min(2.0, sqrt(pdst)) var adest = p.origin var away = (o - p.origin).normalized() @@ -548,14 +738,14 @@ func update_physics(tick, delta): var enemy_dir: Vector3 = Transform(p.basis, Vector3()).xform(Vector3(0, 0, -1)) var root_dir: Vector3 = Transform(root.global_transform.basis, Vector3()).xform(Vector3(0, 0, -1)) var dot = root_dir.dot(enemy_dir) - blackboard_set("dot", dot) + blackboard_set(tick, "dot", dot) var prev_state = state match state: 0: last_running = current_running.duplicate() current_running = [] - var bhv = select_behavior() + var bhv = select_behavior(tick, delta) if last_bhv != bhv: # print("behavior: ", bhv) last_bhv = bhv @@ -591,10 +781,10 @@ func update_physics(tick, delta): if !e in last_running: if !e.active: e.activate() - e.run(delta, blackboard_get_dict()) + e.run(delta, blackboard_get_dict(tick)) #FIXME: mess :( if e == run_behaviors["flee"]: - blackboard_set("flee_cooldown", 2.0 + rnd.randf() * 3.0) + blackboard_set(tick, "flee_cooldown", 2.0 + rnd.randf() * 3.0) if e.finished && e.active: # print("in current run but finished") e.stop() @@ -609,16 +799,16 @@ func update_physics(tick, delta): state = 3 3: state = 0 - if blackboard_get("stamina") < 100.0: - blackboard_set("stamina", blackboard_get("stamina") + delta) - if blackboard_get("attack_cooldown") > 0.0: - blackboard_set("attack_cooldown", blackboard_get("attack_cooldown") - delta) - if blackboard_get("guard_cooldown") > 0.0: - blackboard_set("guard_cooldown", blackboard_get("guard_cooldown") - delta) - if blackboard_get("flee_cooldown") > 0.0: - blackboard_set("flee_cooldown", blackboard_get("flee_cooldown") - delta) - blackboard_set("stamina", clamp(blackboard_get("stamina"), 0, 100.0)) - blackboard_set("health", clamp(blackboard_get("health"), 0, 100.0)) + if blackboard_get(tick, "stamina") < 100.0: + blackboard_set(tick, "stamina", blackboard_get(tick, "stamina") + delta) + if blackboard_get(tick, "attack_cooldown") > 0.0: + blackboard_set(tick, "attack_cooldown", blackboard_get(tick, "attack_cooldown") - delta) + if blackboard_get(tick, "guard_cooldown") > 0.0: + blackboard_set(tick, "guard_cooldown", blackboard_get(tick, "guard_cooldown") - delta) + if blackboard_get(tick, "flee_cooldown") > 0.0: + blackboard_set(tick, "flee_cooldown", blackboard_get(tick, "flee_cooldown") - delta) + blackboard_set(tick, "stamina", clamp(blackboard_get(tick, "stamina"), 0, 100.0)) + blackboard_set(tick, "health", clamp(blackboard_get(tick, "health"), 0, 100.0)) return ERR_BUSY func update(tick, delta): return ERR_BUSY diff --git a/scripts/modules/npc_marker.gd b/scripts/modules/npc_marker.gd index 8c14024..faecc87 100644 --- a/scripts/modules/npc_marker.gd +++ b/scripts/modules/npc_marker.gd @@ -7,7 +7,7 @@ extends AIScriptModule # Called when the node enters the scene tree for the first time. func init(tick): - var root = get_character() + var root = get_character(tick) assert(root.has_meta("skeleton")) var cmdq = [] if root.has_meta("cmdqueue"): diff --git a/scripts/modules/npc_mystress.gd b/scripts/modules/npc_mystress.gd index 96ef8ee..9b53975 100644 --- a/scripts/modules/npc_mystress.gd +++ b/scripts/modules/npc_mystress.gd @@ -25,7 +25,7 @@ var material = preload("res://scenes/clothes/mystress_clothes.material") #} #var state = PRAYING func init(tick): - root = get_character() + root = get_character(tick) assert(root.has_meta("skeleton")) root.add_to_group("mystress") # tween = Tween.new() diff --git a/scripts/modules/npc_student.gd b/scripts/modules/npc_student.gd index 6d0c89a..6c21788 100644 --- a/scripts/modules/npc_student.gd +++ b/scripts/modules/npc_student.gd @@ -24,7 +24,7 @@ var material_male = preload("res://scenes/clothes/clothes-male.material") func init(tick): name = "student_ai" - root = get_character() + root = get_character(tick) assert(root.has_meta("skeleton")) root.add_to_group("students") root.add_to_group("student") diff --git a/scripts/modules/player_clothes.gd b/scripts/modules/player_clothes.gd index bfc1adf..f2a241c 100644 --- a/scripts/modules/player_clothes.gd +++ b/scripts/modules/player_clothes.gd @@ -16,7 +16,7 @@ var garments_head = [] var basedir = "res://scenes/clothes/" var material = preload("res://scenes/clothes/clothes-male.material") func init(tick): - root = get_character() + root = get_character(tick) assert(root.has_meta("skeleton")) call_deferred("setup_markers") diff --git a/scripts/modules/player_controls.gd b/scripts/modules/player_controls.gd index b85a94c..1d701cb 100644 --- a/scripts/modules/player_controls.gd +++ b/scripts/modules/player_controls.gd @@ -11,7 +11,7 @@ var cam var fps_cam var motion = Vector2() func init(tick): - var root = get_character() + var root = get_character(tick) assert(root.has_meta("skeleton")) var attack = false @@ -33,7 +33,7 @@ func update(tick, delta): func update_physics(tick, delta): var orientation: Transform - var root = get_character() + var root = get_character(tick) if !root.has_meta("cam"): return cam = root.get_meta("cam") diff --git a/ui/main_menu.gd b/ui/main_menu.gd new file mode 100644 index 0000000..f5e8702 --- /dev/null +++ b/ui/main_menu.gd @@ -0,0 +1,32 @@ +extends Control + + +# Declare member variables here. Examples: +# var a = 2 +# var b = "text" + + +# Called when the node enters the scene tree for the first time. +func _ready(): + controls.is_gui = true + $v/quit.connect("pressed", self, "quit_pressed") + $v/load_game.connect("pressed", self, "load_game_pressed") + $v/new_game.connect("pressed", self, "new_game_pressed") + $v/edit_ai.connect("pressed", self, "edit_ai_pressed") + +func quit_pressed(): + get_tree().quit() +func load_game_pressed(): + controls.is_gui = true + hide() +# var main = preload("res://world.tscn") +# get_tree().change_scene_to(main) + controls.menu.nosave = true + controls.menu.popup() +func new_game_pressed(): + controls.is_gui = false + var main = preload("res://world.tscn") + get_tree().change_scene_to(main) +func edit_ai_pressed(): + var ai_graph = preload("res://ui/ai_graph.tscn") + get_tree().change_scene_to(ai_graph) diff --git a/ui/main_menu.tscn b/ui/main_menu.tscn new file mode 100644 index 0000000..49e0ff2 --- /dev/null +++ b/ui/main_menu.tscn @@ -0,0 +1,60 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://ui/theme.tres" type="Theme" id=1] +[ext_resource path="res://ui/main_menu.gd" type="Script" id=2] + +[node name="main_menu" type="Control"] +anchor_right = 1.0 +anchor_bottom = 1.0 +script = ExtResource( 2 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="ColorRect" type="ColorRect" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +color = Color( 0.137255, 0.235294, 0.34902, 1 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="v" type="VBoxContainer" parent="."] +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -72.0 +margin_top = -92.0 +margin_right = 72.0 +margin_bottom = 92.0 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="load_game" type="Button" parent="v"] +margin_right = 144.0 +margin_bottom = 43.0 +theme = ExtResource( 1 ) +text = "Load game" + +[node name="new_game" type="Button" parent="v"] +margin_top = 47.0 +margin_right = 144.0 +margin_bottom = 90.0 +theme = ExtResource( 1 ) +text = "New Game" + +[node name="edit_ai" type="Button" parent="v"] +margin_top = 94.0 +margin_right = 144.0 +margin_bottom = 137.0 +theme = ExtResource( 1 ) +text = "Edit AI" + +[node name="quit" type="Button" parent="v"] +margin_top = 141.0 +margin_right = 144.0 +margin_bottom = 184.0 +theme = ExtResource( 1 ) +text = "Quit" diff --git a/ui/save_game.gd b/ui/save_game.gd new file mode 100644 index 0000000..3b27a60 --- /dev/null +++ b/ui/save_game.gd @@ -0,0 +1,97 @@ +extends WindowDialog + +var save_path = "user://saves" + +var next_save_id = 0 +var nosave = false +func _ready(): + print("save/load ready") + $v/quit.connect("pressed", self, "exit_game") + $v/return.connect("pressed", self, "close") + $v/save/new_save.connect("pressed", self, "save_game") + connect("about_to_show", self, "about_to_show") + connect("popup_hide", self, "popup_hide") +func exit_game(): + controls.is_gui = false + get_tree().quit() +func close(): + controls.is_gui = false + hide() +func save_game(): + scenario.prepare_save_data() + print("next_save_id: ", next_save_id) + var filename = save_path + "/" + str(next_save_id) + ".sav" + var f = File.new() + if f.open(filename, File.WRITE) == OK: + print("saving to ", filename) + f.store_string(JSON.print(scenario.save_data, "\t", false)) + f.close() + print("userdata = ", OS.get_user_data_dir()) + controls.is_gui = false + hide() + +func load_game(file_name): + controls.is_gui = false + nosave = false + var f = File.new() + if f.open(save_path + "/" + file_name, File.READ) == OK: + var s = f.get_as_text() + var result = JSON.parse(s) + scenario.save_data = result.result + scenario.restart_scene() + else: + print("Can't open ", file_name) + hide() +func popup_hide(): + yield(get_tree().create_timer(0.5), "timeout") + controls.is_gui = false + hide() + +func about_to_show(): + print("save/load about to show") + if nosave: + if $v/save/new_save.visible: + $v/save/new_save.hide() + else: + if !$v/save/new_save.visible: + $v/save/new_save.show() + var d: = Directory.new() + var f: = File.new() + var theme = Theme.new() + var font: DynamicFont = preload("res://fonts/DefaultFont.tres") + theme.default_font = font + for e in $v/save/s/v.get_children(): + e.queue_free() + if d.dir_exists(save_path): + if d.open(save_path) == OK: + d.list_dir_begin() + var file_name = d.get_next() + while file_name != "": + if file_name in [".", ".."]: + file_name = d.get_next() + continue + var fid = file_name.replace(".sav", "") + if fid.is_valid_integer(): + next_save_id = max(next_save_id, int(fid) + 1) + print(file_name) + var t = f.get_modified_time(save_path + "/" + file_name) + var ts = OS.get_datetime_from_unix_time(t) + var b = Button.new() + b.theme = theme + b.text = "Load " + str(ts.year) + "." + str(ts.month) + "." + str(ts.day) + b.text += " " + str(ts.hour) + ":" + str(ts.minute) + ":" + str(ts.second) + print(b.text) + $v/save/s/v.add_child(b) + b.connect("pressed", self, "load_game", [file_name]) + $v/save/s/v.update() + $v/save/s.update() + $v/save.update() + $v.update() + update() + $v/quit.update() + file_name = d.get_next() + d.list_dir_end() + else: + d.make_dir_recursive(save_path) + print("next_save_id: ", next_save_id) + update() diff --git a/ui/save_game.tscn b/ui/save_game.tscn new file mode 100644 index 0000000..7ab2fc1 --- /dev/null +++ b/ui/save_game.tscn @@ -0,0 +1,66 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://fonts/DefaultFont.tres" type="DynamicFont" id=1] +[ext_resource path="res://ui/save_game.gd" type="Script" id=2] + +[node name="save_game" type="WindowDialog"] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = 10.0 +margin_top = 30.0 +margin_right = -10.0 +margin_bottom = -30.0 +script = ExtResource( 2 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="v" type="VBoxContainer" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="return" type="Button" parent="v"] +margin_right = 1004.0 +margin_bottom = 43.0 +custom_fonts/font = ExtResource( 1 ) +text = "Return to game" + +[node name="save" type="VBoxContainer" parent="v"] +margin_top = 47.0 +margin_right = 1004.0 +margin_bottom = 493.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="new_save" type="Button" parent="v/save"] +margin_right = 1004.0 +margin_bottom = 43.0 +custom_fonts/font = ExtResource( 1 ) +text = "New save" +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="s" type="ScrollContainer" parent="v/save"] +margin_top = 47.0 +margin_right = 1004.0 +margin_bottom = 446.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="v" type="VBoxContainer" parent="v/save/s"] + +[node name="quit" type="Button" parent="v"] +margin_top = 497.0 +margin_right = 1004.0 +margin_bottom = 540.0 +custom_fonts/font = ExtResource( 1 ) +text = "Quit game" diff --git a/ui/theme.tres b/ui/theme.tres new file mode 100644 index 0000000..c03b113 --- /dev/null +++ b/ui/theme.tres @@ -0,0 +1,6 @@ +[gd_resource type="Theme" load_steps=2 format=2] + +[ext_resource path="res://fonts/DefaultFont.tres" type="DynamicFont" id=1] + +[resource] +default_font = ExtResource( 1 ) diff --git a/ui/town_menu.gd b/ui/town_menu.gd new file mode 100644 index 0000000..0846db4 --- /dev/null +++ b/ui/town_menu.gd @@ -0,0 +1,25 @@ +extends Control + +func _ready(): + $buttons/return.connect("pressed", self, "finish") + $buttons/upgrade.connect("pressed", self, "upgrade") + $buttons/teleport_to_town.connect("pressed", self, "teleport") + set_physics_process(false) +func finish(): + controls.is_gui = false + hide() +func upgrade(): + controls.is_gui = false + hide() + scenario.camp_level += 1 + scenario.camp.queue_free() + scenario.camp = streaming.setup_bandit_camp(scenario.camp_site) +func teleport(): + set_physics_process(true) + +func _physics_process(delta): + var cam = get_viewport().get_camera() + if cam: + var player = cam.get_meta("player") + player.global_transform.origin = scenario.camp.global_transform.origin + Vector3(0, 10, 0) + set_physics_process(false) diff --git a/ui/town_menu.tscn b/ui/town_menu.tscn new file mode 100644 index 0000000..b639b53 --- /dev/null +++ b/ui/town_menu.tscn @@ -0,0 +1,45 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://ui/theme.tres" type="Theme" id=1] +[ext_resource path="res://ui/town_menu.gd" type="Script" id=2] + +[node name="town_menu" type="Control"] +anchor_right = 1.0 +anchor_bottom = 1.0 +script = ExtResource( 2 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="buttons" type="VBoxContainer" parent="."] +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -20.0 +margin_top = -20.0 +margin_right = 20.0 +margin_bottom = 20.0 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="upgrade" type="Button" parent="buttons"] +margin_right = 217.0 +margin_bottom = 43.0 +theme = ExtResource( 1 ) +text = "Upgrade town" + +[node name="teleport_to_town" type="Button" parent="buttons"] +margin_top = 47.0 +margin_right = 217.0 +margin_bottom = 90.0 +theme = ExtResource( 1 ) +text = "Teleport to town" + +[node name="return" type="Button" parent="buttons"] +margin_top = 94.0 +margin_right = 217.0 +margin_bottom = 137.0 +theme = ExtResource( 1 ) +text = "Return"