From d6c8a24f5ad79985c11c000a59b855d24e160ba4 Mon Sep 17 00:00:00 2001 From: Segey Lapin Date: Tue, 26 Oct 2021 21:51:45 +0300 Subject: [PATCH] stuff --- .gitignore | 2 + autoload/characters.gd | 604 + autoload/controls.gd | 192 + autoload/doors.gd | 72 + autoload/freezer.gd | 131 + autoload/inventory.gd | 89 + autoload/map.gd | 52 + autoload/map.tscn | 16 + autoload/marker.gd | 213 + autoload/scenario.gd | 17 + autoload/streaming.gd | 296 + autoload/streaming.tscn | 12 + camera/camera_pos.tscn | 26 + camera/environment.tres | 15 + camera/fps_cam_pos.tscn | 13 + characters/character.gd | 12 + characters/vroid1-female.tscn | 734 + characters/vroid1-man-animate.bin | Bin 0 -> 8618888 bytes characters/vroid1-man-animate.gltf | 259662 +++++++++++++++++++ characters/vroid1-man-animate.gltf.import | 1064 + characters/vroid1-man-at.tres | 3 + characters/vroid1-man-xat.tres | 210 + characters/vroid1-man.tscn | 531 + cleanup.sh | 4 + export_presets.cfg | 24 + objects/Material.material | Bin 0 -> 741 bytes objects/foundation.tscn | 21 + objects/house.gd | 15 + objects/palace.bin | Bin 0 -> 234880 bytes objects/palace.gd | 123 + objects/palace.gltf | 889 + objects/palace.gltf.import | 1064 + objects/palace.material | Bin 0 -> 1610 bytes objects/palace.tscn | 6 + objects/palace_001.material | Bin 0 -> 1618 bytes objects/trailer-house.bin | Bin 0 -> 777028 bytes objects/trailer-house.gd | 151 + objects/trailer-house.gltf | 901 + objects/trailer-house.gltf.import | 1064 + objects/trailer-house.tscn | 6 + road/road.material | Bin 0 -> 739 bytes road/road.png | Bin 0 -> 27034 bytes road/road.png.import | 37 + road/road_elements.bin | Bin 0 -> 18732 bytes road/road_elements.gltf | 600 + road/road_elements.gltf.import | 1064 + scripts/import/car_import.gd | 20 + scripts/import/import_clothes.gd | 14 + scripts/modules/character_hurtboxes.gd | 74 + scripts/modules/cmdq.gd | 236 + scripts/modules/npc_marker.gd | 38 + scripts/modules/npc_nun.gd | 142 + scripts/modules/npc_sacrifice.gd | 53 + scripts/modules/npc_student.gd | 145 + scripts/modules/player_clothes.gd | 81 + scripts/modules/player_controls.gd | 108 + world.gd | 110 + world.tscn | 103 + 58 files changed, 271059 insertions(+) create mode 100644 .gitignore create mode 100644 autoload/characters.gd create mode 100644 autoload/controls.gd create mode 100644 autoload/doors.gd create mode 100644 autoload/freezer.gd create mode 100644 autoload/inventory.gd create mode 100644 autoload/map.gd create mode 100644 autoload/map.tscn create mode 100644 autoload/marker.gd create mode 100644 autoload/scenario.gd create mode 100644 autoload/streaming.gd create mode 100644 autoload/streaming.tscn create mode 100644 camera/camera_pos.tscn create mode 100644 camera/environment.tres create mode 100644 camera/fps_cam_pos.tscn create mode 100644 characters/character.gd create mode 100644 characters/vroid1-female.tscn create mode 100644 characters/vroid1-man-animate.bin create mode 100644 characters/vroid1-man-animate.gltf create mode 100644 characters/vroid1-man-animate.gltf.import create mode 100644 characters/vroid1-man-at.tres create mode 100644 characters/vroid1-man-xat.tres create mode 100644 characters/vroid1-man.tscn create mode 100644 cleanup.sh create mode 100644 export_presets.cfg create mode 100644 objects/Material.material create mode 100644 objects/foundation.tscn create mode 100644 objects/house.gd create mode 100644 objects/palace.bin create mode 100644 objects/palace.gd create mode 100644 objects/palace.gltf create mode 100644 objects/palace.gltf.import create mode 100644 objects/palace.material create mode 100644 objects/palace.tscn create mode 100644 objects/palace_001.material create mode 100644 objects/trailer-house.bin create mode 100644 objects/trailer-house.gd create mode 100644 objects/trailer-house.gltf create mode 100644 objects/trailer-house.gltf.import create mode 100644 objects/trailer-house.tscn create mode 100644 road/road.material create mode 100644 road/road.png create mode 100644 road/road.png.import create mode 100644 road/road_elements.bin create mode 100644 road/road_elements.gltf create mode 100644 road/road_elements.gltf.import create mode 100644 scripts/import/car_import.gd create mode 100644 scripts/import/import_clothes.gd create mode 100644 scripts/modules/character_hurtboxes.gd create mode 100644 scripts/modules/cmdq.gd create mode 100644 scripts/modules/npc_marker.gd create mode 100644 scripts/modules/npc_nun.gd create mode 100644 scripts/modules/npc_sacrifice.gd create mode 100644 scripts/modules/npc_student.gd create mode 100644 scripts/modules/player_clothes.gd create mode 100644 scripts/modules/player_controls.gd create mode 100644 world.gd create mode 100644 world.tscn diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ebbdeb4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.import +*.scn diff --git a/autoload/characters.gd b/autoload/characters.gd new file mode 100644 index 0000000..641e006 --- /dev/null +++ b/autoload/characters.gd @@ -0,0 +1,604 @@ +extends Characters_ + + +# Declare member variables here. Examples: +# var a = 2 +# var b = "text" + + +# Called when the node enters the scene tree for the first time. + +# Called every frame. 'delta' is the elapsed time since the previous frame. +#func _process(delta): + +onready var female = preload("res://characters/vroid1-female.tscn") +onready var male = preload("res://characters/vroid1-man.tscn") +onready var face_ctrl = preload("res://scenes/face/head_comtrol.tscn") +onready var modules = { +# "physics": load("res://scripts/modules/character_physics.gd"), + "cmdq": load("res://scripts/modules/cmdq.gd"), + "marker": load("res://scripts/modules/npc_marker.gd"), + "sacrifice": load("res://scripts/modules/npc_sacrifice.gd"), + "nun": load("res://scripts/modules/npc_nun.gd"), + "player": load("res://scripts/modules/player_controls.gd"), + "player_clothes": load("res://scripts/modules/player_clothes.gd"), + "hurtboxes": load("res://scripts/modules/character_hurtboxes.gd"), + "student": load("res://scripts/modules/npc_student.gd") +} + +var face_data_path = "res://scenes/face/" +var hair_data_path = "res://scenes/hair/" +var female_faces = [] +var male_faces = [] +var female_hairs = [] +var male_hairs = [] +var hair_materials = [] + +var name_data = {} +var rnd + +var roommates = {} + +#var _crowd: DetourCrowdManager + +func _ready(): + set_root_motion_mod(Transform()) + var fd = File.new() + fd.open("res://data/names.json", File.READ) + var names = fd.get_as_text() + var result = JSON.parse(names) + name_data = result.result + rnd = RandomNumberGenerator.new() + var data_fd: = File.new() + for g in ["male", "female"]: + var fp = face_data_path + g + "-face.tscn" + if data_fd.file_exists(fp): + match g: + "female": + female_faces.push_back(fp) + "male": + male_faces.push_back(fp) + for id in range(10000): + var fp_m = face_data_path + "male-face" + str(id) + ".tscn" + var fp_f = face_data_path + "female-face" + str(id) + ".tscn" + var hp_m = hair_data_path + "male-hair" + str(id) + ".tscn" + var hp_f = hair_data_path + "female-hair" + str(id) + ".tscn" + var mat = hair_data_path + "hair" + str(id) + ".tres" + if data_fd.file_exists(fp_m): + male_faces.push_back(fp_m) + if data_fd.file_exists(fp_f): + female_faces.push_back(fp_f) + if data_fd.file_exists(hp_m): + male_hairs.push_back(hp_m) + if data_fd.file_exists(hp_f): + female_hairs.push_back(hp_f) + if data_fd.file_exists(mat): + hair_materials.push_back(mat) + assert(male_faces.size() > 0) + assert(female_faces.size() > 0) + assert(male_hairs.size() > 0) + assert(female_hairs.size() > 0) + assert(hair_materials.size() > 0) + +func get_relationship(obj1, obj2, s) -> int: + var stats1 = {} + var stats2 = {} + if obj1.has_meta("stats"): + stats1 = obj1.get_meta("stats") + if obj2.has_meta("stats"): + stats2 = obj2.get_meta("stats") + if !stats2.has("relationships"): + return 0 + var rel = stats2.relationships + var cid = stats1.firstname + stats1.lastname + if !rel.has(cid): + return 0 + var rel_data = rel[cid] + if rel_data.has(s): + return rel_data[s] + return 0 +func set_relationships(obj1, obj2, s, v: int) -> void: + assert(obj1) + assert(obj2) + var stats1 = {} + var stats2 = {} + if obj1.has_meta("stats"): + stats1 = obj1.get_meta("stats") + if obj2.has_meta("stats"): + stats2 = obj2.get_meta("stats") + if !stats2.has("relationships"): + stats2.relationships = {} + var rel = stats2.relationships + var cid = stats1.firstname + stats1.lastname + if !rel.has(cid): + rel[cid] = {} + rel[cid][s] = v + print(stats2) + obj2.set_meta("stats", stats2) +func get_face_node(sc: Node) -> Node: + var face_node_paths = ["skeleton/Skeleton/head/face", "Skeleton/head/face"] + for e in face_node_paths: + if sc.has_node(e): + print("face node: ", e) + return sc.get_node(e) + assert(0) + return null + +func get_hair_node(sc: Node) -> Node: + var hair_node_paths = ["skeleton/Skeleton/head/hair", "Skeleton/head/hair"] + for e in hair_node_paths: + if sc.has_node(e): + print("hair node: ", e) + return sc.get_node(e) + assert(0) + return null +func compose_kinematic_character(g, enable_modules = [], face = -1, hair = -1, hair_mat = -1): + var body = KinematicBody.new() + var cshape = CollisionShape.new() + body.add_child(cshape) + var capsule = CapsuleShape.new() + var character_data = { + "sex": g, + "modules": enable_modules + } + var face_scene: PackedScene + var hair_scene: PackedScene + var face_i: Node + var hair_i: Node + var face_node: Node + var hair_node: Node + match g: + "female": + if face == -1: + face = rnd.randi() % female_faces.size() + if hair == -1: + hair = rnd.randi() % female_hairs.size() + face_scene = load(female_faces[face]) + hair_scene = load(female_hairs[hair]) + capsule.radius = 0.2 + capsule.height = 1.1 + capsule.margin = 0.05 + cshape.translation.x = 0 + cshape.translation.y = 0.751 + cshape.translation.z = 0 + cshape.rotation = Vector3(-PI/2.0, 0, 0) + var i = female.instance() + body.add_child(i) + i.transform = Transform() + face_node = get_face_node(i) + hair_node = get_hair_node(i) + "male": + if face == -1: + face = rnd.randi() % male_faces.size() + if hair == -1: + hair = rnd.randi() % male_hairs.size() + face_scene = load(male_faces[face]) + hair_scene = load(male_hairs[hair]) + capsule.radius = 0.3 + capsule.height = 1.2 + capsule.margin = 0.05 + cshape.translation.x = 0 + cshape.translation.y = 0.899 + cshape.translation.z = 0 + cshape.rotation = Vector3(-PI/2.0, 0, 0) + var i = male.instance() + body.add_child(i) + i.transform = Transform() + face_node = get_face_node(i) + hair_node = get_hair_node(i) + assert(face_node) + face_i = face_scene.instance() + face_i.add_to_group("face") + prepare_extra_skeleton(face_i, "face") + hair_i = hair_scene.instance() + hair_i.add_to_group("hair") + prepare_extra_skeleton(hair_i, "hair") + if hair_mat == -1: + hair_mat = rnd.randi() % hair_materials.size() + var hmat = load(hair_materials[hair_mat]) + assert(hmat) + set_hair_material(hair_i, hmat) + for e in face_node.get_children(): + e.queue_free() + for e in hair_node.get_children(): + e.queue_free() + face_node.add_child(face_i) + hair_node.add_child(hair_i) + var face_ctrl_i = face_ctrl.instance() + face_ctrl_i.active = true + face_i.add_child(face_ctrl_i) + face_i.set_meta("body", body) + body.set_meta("face_control", face_ctrl_i) + body.set_meta("face_playback", "parameters/state/playback") + face_ctrl_i.add_to_group("face") + face_i.transform = Transform() + character_data.face = face + character_data.hair = hair + character_data.hair_mat = hair_mat + cshape.shape = capsule + body.set_meta("character_data", character_data) + for e in enable_modules: + assert(modules.has(e)) + if modules.has(e): + assert(modules[e]) + var obj = modules[e].new() + body.add_child(obj) + setup_character_physics(body) + body.add_to_group("character") + return body + +func replace_character(obj, g, enable_modules = [], face = -1, hair = -1, hair_mat = -1): + assert(obj) + var xform = obj.global_transform + var p = obj.get_parent() + obj.queue_free() + var body = compose_kinematic_character(g, enable_modules, face, hair, hair_mat) + p.add_child(body) + body.global_transform = xform + var orientation = Transform() + orientation.basis = xform.basis + body.set_meta("orientation", orientation) + return body +const basedir = "res://scenes/clothes/" +func prepare_extra_skeleton(obj, g): + var queue = [obj] + while queue.size() > 0: + var item = queue.pop_front() + if item is Skeleton: + item.add_to_group(g) + break + for g in item.get_children(): + queue.push_back(g) +func set_hair_material(hair, mat: Material): + assert(mat) + var queue = [hair] + while queue.size() > 0: + var item = queue.pop_front() + if item is MeshInstance: + item.set_surface_material(0, mat) + break + for g in item.get_children(): + queue.push_back(g) +func setup_garments(obj, garments, garments_head, material): + var skel = obj.get_meta("skeleton") + var hair_skel = obj.get_meta("hair_skeleton") + + if obj.has_meta("garments"): + print("Can remove garments") + var d = obj.get_meta("garments") + var db = d.body_data + var dh = d.head_data + for e in db + dh: + print("remove: ", e) +# obj.remove_child(e) + if e.get_parent() == obj: + obj.remove_child(e) + e.queue_free() + var gdata_body = [] + for g in garments: + var m: MeshInstance = MeshInstance.new() + m.name = g + print("loading: ", basedir + g + ".mesh") + var geo: ArrayMesh = load(basedir + g + ".mesh") + assert(geo) + print("mesh: ", geo, "mat: ", material) + geo.surface_set_material(0, material) + m.mesh = geo +# m.skeleton = m.get_path_to(root.get_meta("skeleton")) +# = root.get_meta("skeleton") + skel.add_child(m) + m.transform = Transform() + gdata_body.push_back(m) + var gdata_head = [] + for g in garments_head: + var m: MeshInstance = MeshInstance.new() + m.name = g + var geo: ArrayMesh = load(basedir + g + ".mesh") + print("mesh: ", geo, "mat: ", material) + geo.surface_set_material(0, material) + m.mesh = geo +# m.skeleton = m.get_path_to(root.get_meta("skeleton")) +# = root.get_meta("skeleton") + hair_skel.add_child(m) + m.transform = Transform() + gdata_head.push_back(m) + var gdata = { + "body": garments, + "head": garments_head, + "material": material, + "body_data": gdata_body, + "head_data": gdata_head + } + obj.set_meta("garments", gdata) + +func lastname(): + var lastnames = name_data.lastname + var d = lastnames.size() + return lastnames[rnd.randi() % d].to_lower().capitalize() + +func firstname(g): + var firstnames = name_data[g].firstname + var d = firstnames.size() + return firstnames[rnd.randi() % d].to_lower().capitalize() + +func generate_stats(npc: Node): + var stats = npc.get_meta("stats") + var strength = 10 + rnd.randi() % 100 + var max_health = 10 + rnd.randi() % 100 + var max_stamina = 10 + rnd.randi() % 100 + stats.tiredness = 0.0 + stats.hunger = 0.0 + stats.thirst = 0.0 + stats.libido = 0.0 + stats.toilet = 0.0 + stats.stress = 0.0 + stats.health = max_health + stats.stamina = max_stamina + stats.max_health = max_health + stats.max_stamina = max_stamina + stats.violence = rnd.randi() % (int(strength * 0.5)) + stats.xp = 0 + npc.set_meta("stats", stats) +var stat_changes = { + "sleep":{ + "tiredness": -0.3, + "stress": -0.03 + }, + "eating": { + "hunger": -0.9, + "stress": -0.01 + }, + "drinking": { + "thirst": -2.8, + "stress": -0.01 + }, + "use_tap": { + "thirst": -2.8, + "stress": -0.01 + }, + "locomotion": { + "tiredness": 0.0015, + "hunger": 0.025, + "thirst": 0.045, + "stress": 0.0001, + "libido": 0.00015, + "toilet": 0.0002 + } +} +func update_stats(npc: Node): + var stats = npc.get_meta("stats") + if stats.tiredness < 10.0: + if stats.stamina < stats.max_stamina: + stats.stamina += 0.1 + stats.stamina = clamp(stats.stamina, 0, stats.max_stamina) + var animtree = npc.get_meta("animation_tree") + var state = animtree["parameters/state/playback"].get_current_node() + if state in stat_changes.keys(): + for s in stat_changes[state].keys(): + stats[s] += stat_changes[state][s] + if stats[s] < 0: + stats[s] = 0.0 + npc.set_meta("stats", stats) + +# Action part should be integrated into SmartObjectManager +func check_leave_smart(npc: Node): + return + if !npc.has_meta("smart_object"): + return + var sm = npc.get_meta("smart_object") + var new_goal = calculate_goal(npc) + if !sm.is_in_group(new_goal): +# var animtree = npc.get_meta("animation_tree") +# animtree["parameters/state/playback"].travel("locomotion") + npc.remove_meta("smart_object") + +func calculate_goal(npc: Node): + var utility = { + "sleep": ["tiredness", 900], + "hungry": ["hunger", 1000], + "thirsty": ["thirst", 1300], + "relieve_stress": ["stress", 800], + "have_sex": ["libido", 500], + "idle": ["", 600] + } + var stats = npc.get_meta("stats") + var rutility = -10000 + var goal = "idle" + var last_goal = "" + var last_utility = -1 + if npc.has_meta("last_goal"): + last_goal = npc.get_meta("last_goal") + goal = npc.get_meta("last_goal") + if npc.has_meta("last_utility"): + last_utility = int(npc.get_meta("last_utility")) + rutility = int(npc.get_meta("last_utility") * 2.0) + for k in utility.keys(): + var st = 1.0 + if utility[k][0] != "": + st = stats[utility[k][0]] + var mul = utility[k][1] + var cutil = int(st * mul) + if rutility < cutil: + rutility = cutil + goal = k + npc.set_meta("last_goal", goal) + if goal == last_goal: + npc.set_meta("last_utility", last_utility) + else: + npc.set_meta("last_utility", rutility) + + return goal + +var cooldown = 0.0 + +var close_groups = {} + +func walkto_(npc, target): + assert(npc.has_meta("agent_id")) + if npc.has_mete("agent_id"): + walkto_agent(npc, target) +# if npc.has_meta("_target"): +# var otarget = npc.get_meta("_target") +# if target == otarget: +# return +# assert(npc.has_meta("agent_id")) +# npc.set_meta("_target", target) +## print("walk to ", target) +## print("walk to ", target) +## print("walk to ", target) +# var agent_id = npc.get_meta("agent_id") +# if target is Spatial: +# get_crowd().set_agent_target_position(agent_id, target.global_transform.origin) +# elif target is Vector3: +# get_crowd().set_agent_target_position(agent_id, target) + +#func update_to_agent(root): +# if !_crowd: +# return +# if !root.has_meta("agent_id"): +# _crowd.add_agent(root, 0, false, PoolRealArray([0.2, 1.5, 0.3, 3.0])) +# if !root.has_meta("agent_id"): +# return +# if !root.has_meta("_target"): +# return +# var velocity = root.get_meta("agent_velocity") +# if velocity.length() == 0: +# characters.set_walk_speed(root, 0, 0) +# else: +## print("agent_velocity=", velocity) +# var vel1 = velocity +# vel1.y = 0 +# var xform: = Transform().looking_at(vel1, Vector3.UP) +# xform = xform.orthonormalized() +# var orientation = root.get_meta("orientation") +# orientation.basis = orientation.basis.slerp(xform.basis, get_physics_process_delta_time()) +# root.set_meta("orientation", orientation) +# characters.set_walk_speed(root, clamp(vel1.length() / 6.5, 0.0, 1.0), 0) +# +#func character_physics(root): +# var delta = get_physics_process_delta_time() +# var animtree = root.get_meta("animation_tree") +# var orientation = root.get_meta("orientation") +# var root_motion = animtree.get_root_motion_transform() +# orientation *= root_motion +# var h_velocity = orientation.origin / delta +# var velocity: = Vector3() +# velocity.x = h_velocity.x +# velocity.z = h_velocity.z +# velocity.y = h_velocity.y +## if root.has_meta("climb"): +## print("has climb meta") +## if root.has_meta("cmdqueue"): +## print("+has cmdqueue") +# if !root.has_meta("vehicle") && !root.has_meta("cmdqueue"): +# if root is KinematicBody: +# if !root.is_on_floor(): +# velocity += Vector3(0, -9.8, 0) +# velocity = root.move_and_slide(velocity, Vector3.UP, true, 4, 0.785, false) +# elif root.has_meta("cmdqueue") && root.has_meta("cmdq_walk"): +# if root is KinematicBody: +# if !root.is_on_floor() && !root.has_meta("climb"): +# velocity += Vector3(0, -9.8, 0) +# velocity = root.move_and_slide(velocity, Vector3.UP, true, 4, 0.785, false) +# elif root.has_meta("cmdqueue") && root.has_meta("climb"): +# if root is KinematicBody: +# velocity.y = h_velocity.y +# velocity = root.move_and_slide(velocity, Vector3.UP, true, 4, 0.785, false) +# orientation.origin = Vector3() +# orientation = orientation.orthonormalized() +# root.global_transform.basis = orientation.basis +# root.set_meta("orientation", orientation) +# if root.has_meta("vehicle"): +# var vehicle: VehicleBody = get_meta("vehicle") +# if has_meta("vehicle_offset"): +# var xform = get_meta("vehicle_offset") +# root.global_transform = vehicle.global_transform * xform +# if root.has_node("blackboard"): +# var bb = root.get_node("blackboard") +# bb.set("velocity", velocity) +# update_to_agent(root) + +func check_main_animtree(item): + if !item is AnimationTree: + return false + for g in ["hair", "face"]: + if item.is_in_group(g): + return false + return true + +func check_main_skeleton(item): + if !item is Skeleton: + return false + for g in ["hair", "face"]: + if item.is_in_group(g): + return false + return true + +func setup_character_physics(root): + var queue = [root] + while queue.size() > 0: + var item = queue.pop_front() + if check_main_animtree(item): + root.set_meta("animation_tree", item) + if check_main_skeleton(item): + root.set_meta("skeleton", item) + if item is Skeleton && item.is_in_group("hair"): + root.set_meta("hair_skeleton", item) + if item is Skeleton && item.is_in_group("face"): + root.set_meta("face_skeleton", item) + for e in item.get_children(): + queue.push_back(e) +# var velocity = Vector3() + var orientation = Transform() + if root.is_inside_tree(): + orientation = root.global_transform + orientation.origin = Vector3() + root.set_meta("orientation", orientation) + +func _process(delta): + if cooldown > 0.0: + cooldown -= delta + return + for e in get_tree().get_nodes_in_group("character"): + var gr = [] + for o in get_tree().get_nodes_in_group("character"): + if e == o: + continue + var e_org = e.global_transform.origin + var o_org = o.global_transform.origin + if e_org.distance_to(o_org) < 1.2: + gr.push_back(o) + close_groups[e] = gr + if e.has_meta("animation_tree"): + var animtree = e.get_meta("animation_tree") + var state = animtree["parameters/state/playback"].get_current_node() + var face_playback = e.get_meta("face_playback") + var face_ctrl = e.get_meta("face_control") + var p = face_ctrl[face_playback] + if state == "sleeping": + if p.get_current_node() != "sleeping": + p.travel("sleeping") + else: + if p.get_current_node() != "locomotion": + p.travel("locomotion") + cooldown = 0.2 +func get_player(): + var c = get_viewport().get_camera() + if !c: + return null + if !c.has_meta("player"): + return null + var player = c.get_meta("player") + if !player: + return null + return player + +func _physics_process(delta): + var player = get_player() + if !player: + return + if player.has_meta("animation_tree") && !player.has_meta("vehicle"): + character_physics(player) +# for e in get_tree().get_nodes_in_group("character") + [player]: +# if e && e.has_meta("animation_tree"): +# character_physics(e) diff --git a/autoload/controls.gd b/autoload/controls.gd new file mode 100644 index 0000000..bb3694d --- /dev/null +++ b/autoload/controls.gd @@ -0,0 +1,192 @@ +extends Node + +var is_gui = false + +var rot_cam = Vector3() +var mouse_sens = 0.3 +var camera_anglev = 0 + +var fps_mode = false +var tmp_fps_mode = false +var focus_cam: Camera +var cam_focused: bool = false + +var menu: Node +func display_menu(): + menu.popup() + + +func _ready(): + focus_cam = Camera.new() + add_child(focus_cam) + focus_cam.set_as_toplevel(true) +# var escape_menu = preload("res://ui/save_game.tscn") +# menu = escape_menu.instance() +# add_child(menu) + +func is_fps_mode(): + return fps_mode || tmp_fps_mode + +func _input(event): + if !is_gui: + Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) + if event is InputEventMouseMotion && !is_gui: + rot_cam.y = deg2rad(-event.relative.x * mouse_sens) + var changev = -event.relative.y * mouse_sens + var player + if get_viewport().get_camera().has_meta("player"): + player = get_viewport().get_camera().get_meta("player") + if !player: + return + var cam = player.get_meta("cam") + var fps_cam = player.get_meta("fps_cam") + if cam.current: + if camera_anglev + changev > -30 and camera_anglev + changev < 40: + camera_anglev += changev + rot_cam.x = deg2rad(changev) + elif fps_cam.current: + if camera_anglev + changev > -60 and camera_anglev + changev < 60: + camera_anglev += changev + rot_cam.x = deg2rad(changev) +func focus_camera(obj): + if !obj: + print("NOTHING TO FOCUS") + return + if cam_focused: + return + print("FOCUS") + var cur_cam = get_viewport().get_camera() + var player = cur_cam.get_meta("player") + var cam = player.get_meta("cam") + focus_cam.global_transform = cam.global_transform + var do = obj.global_transform.origin + focus_cam.look_at(do, Vector3.UP) + cam_focused = true + focus_cam.set_meta("camera", cur_cam) + focus_cam.set_current(true) + focus_cam.set_meta("player", player) +func unfocus_camera(): + cam_focused = false + var ncam = focus_cam.get_meta("camera") + ncam.set_current(true) + +func fix_cam(state, _delta): + var player = get_viewport().get_camera().get_meta("player") + if !is_fps_mode(): + var cam = player.get_meta("cam") + var cam_rot_y = cam.get_meta("cam_rot_y") + var cam_rot_x = cam.get_meta("cam_rot_x") + cam_rot_y.rotate_y(rot_cam.y) + cam_rot_x.rotate_x(rot_cam.x) + else: + if !player.has_meta("vehicle") && !player.has_meta("cmdqueue"): + var fps_cam = player.get_meta("fps_cam") + var fps_cam_rot_x = fps_cam.get_meta("fps_cam_rot_x") + var o: Transform = player.get_meta("orientation") + o.basis = o.basis.rotated(Vector3(0, 1, 0), rot_cam.y) + fps_cam_rot_x.rotate_x(rot_cam.x) + player.set_meta("orientation", o) + + rot_cam.y = 0 + rot_cam.x = 0 +func get_player(): + var c = get_viewport().get_camera() + assert(c) + if !c: + return null + assert(c.has_meta("player")) + if !c.has_meta("player"): + return null + var player = c.get_meta("player") + assert(player) + if !player: + return null + assert(player) + return player + +func switch_fps_mode(value): + var player = get_player() + print(player) + if !player: + return + assert(player != null) + var cam = player.get_meta("cam") + var fps_cam = player.get_meta("fps_cam") + var cam_rot_y = cam.get_meta("cam_rot_y") + if !value: + cam.current = true + player.show_face() + #need to convert to globals + cam_rot_y.rotation.y = player.rotation.y + else: + fps_cam.current = true + player.hide_face() + +var tmp_fps_cooldown = 0.0 + + +func _process(delta): + var c = get_viewport().get_camera() + if !c: + return + + if !c.has_meta("player"): + return + + var player = get_player() + if !player: + return + if !is_gui && Input.is_action_just_pressed("ui_cancel"): + is_gui = true + Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) + display_menu() + if !is_gui && Input.get_mouse_mode() != Input.MOUSE_MODE_CAPTURED: + Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) + elif is_gui && Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED: + Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) + var cam = player.get_meta("cam") + var fps_cam = player.get_meta("fps_cam") + var cam_pos = cam.get_meta("cam_pos") + var cam_arm = cam.get_meta("cam_arm") + cam_pos.global_transform.origin = player.global_transform.origin + cam.look_at(player.global_transform.origin + Vector3(0, 1.9, 0), Vector3.UP) + + if Input.is_action_just_pressed("fps_mode") && !tmp_fps_mode: + fps_mode = !fps_mode + switch_fps_mode(fps_mode) + if !fps_mode && !tmp_fps_mode && !player.has_meta("vehicle"): + var s = cam_arm.global_transform.origin + var t = cam.global_transform.origin + if tmp_fps_cooldown <= 0.0: + if s.distance_to(t) < 0.3: + tmp_fps_mode = true + switch_fps_mode(tmp_fps_mode) + tmp_fps_cooldown = 1.0 + if !fps_mode && tmp_fps_mode: + var s = cam_arm.global_transform.origin + var t = cam.global_transform.origin + if tmp_fps_cooldown <= 0.0: + if s.distance_to(t) > 0.4: + tmp_fps_mode = false + switch_fps_mode(tmp_fps_mode) + tmp_fps_cooldown = 3.0 + if tmp_fps_cooldown > 0.0: + tmp_fps_cooldown -= delta + +var spawn_delay = 0.5 +func _physics_process(delta): + if spawn_delay > 0.5: + spawn_delay -= delta + return + var c = get_viewport().get_camera() + if !c: + return + if !c.has_meta("player"): + return + var player = c.get_meta("player") + if !player: + return + var space = player.get_world().space + var state = PhysicsServer.space_get_direct_state(space) + fix_cam(state, delta) + diff --git a/autoload/doors.gd b/autoload/doors.gd new file mode 100644 index 0000000..fed16fe --- /dev/null +++ b/autoload/doors.gd @@ -0,0 +1,72 @@ +extends Node + + +# Declare member variables here. Examples: +# var a = 2 +# var b = "text" +var door_list = {} + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + +func register_door(obj: Node, name, door_obj, axis, cangle, oangle, spd): + assert(obj) + assert(door_obj) + var root_name = str(obj.get_path()) + if !door_list.has(root_name): + door_list[root_name] = {} + var base = door_obj.transform + door_list[root_name][name] = {} + door_list[root_name][name].obj = door_obj + door_list[root_name][name].base = base + door_list[root_name][name].axis = axis + door_list[root_name][name].cangle = cangle + door_list[root_name][name].oangle = oangle + door_list[root_name][name].cur_angle = cangle + door_list[root_name][name].speed = spd + door_list[root_name][name].active = false + door_list[root_name][name].state = 0 +func open_door(obj, name): + var root_name = str(obj.get_path()) + if !door_list.has(root_name): + return + door_list[root_name][name].active = true + door_list[root_name][name].state = 1 +func close_door(obj, name): + var root_name = str(obj.get_path()) + if !door_list.has(root_name): + return + door_list[root_name][name].active = true + door_list[root_name][name].state = 0 +func is_active(obj, name): + var root_name = str(obj.get_path()) + if !door_list.has(root_name): + return false + return door_list[root_name][name].active +func get_state(obj, name): + var root_name = str(obj.get_path()) + if !door_list.has(root_name): + return -1 + return door_list[root_name][name].state +func _process(delta): + for e in door_list.keys(): + for j in door_list[e].keys(): + var m = door_list[e][j] + if m.active: + var change = min(1.0, m.speed * delta) + match m.state: + 0: + if abs(m.cur_angle - m.cangle) < 0.001: + m.cur_angle = m.cangle + m.active = false + else: + m.cur_angle = lerp_angle(m.cur_angle, m.cangle, change) + 1: + if abs(m.cur_angle - m.oangle) < 0.001: + m.cur_angle = m.oangle + m.active = false + else: + m.cur_angle = lerp_angle(m.cur_angle, m.oangle, change) + m.obj.transform.basis = m.base.basis.rotated(m.axis, m.cur_angle) + diff --git a/autoload/freezer.gd b/autoload/freezer.gd new file mode 100644 index 0000000..4db14e2 --- /dev/null +++ b/autoload/freezer.gd @@ -0,0 +1,131 @@ +extends Node + + +# Declare member variables here. Examples: +# var a = 2 +# var b = "text" + + +# Called when the node enters the scene tree for the first time. +var freeze_dist = 20.0 +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func freeze_character(c): + var pos = c.transform + var sp = Spatial.new() + var pp = c.get_parent() + var character_data = {} + var stats = {} + if c.has_meta("character_data"): + character_data = c.get_meta("character_data") + if c.has_meta("stats"): + stats = c.get_meta("stats") + pp.add_child(sp) + sp.transform = pos + sp.add_to_group("frozen") + sp.set_meta("character_data", character_data) + var animtree: AnimationTree = c.get_meta("animation_tree") + assert(animtree) + var animation_node = animtree["parameters/state/playback"].get_current_node() + sp.set_meta("animation_node", animation_node) +# sp.set_meta("animation_tree", str(c.get_path_to(animtree))) + sp.set_meta("stats", stats) + if characters.get_crowd(): + characters.get_crowd().remove_agent(c) + c.queue_free() + +func prepare_save_data() -> bool: + if !freeze_all(): + return false + scenario.save_data.characters = [] + for c in get_tree().get_nodes_in_group("frozen"): + var n = {} + n.character_data = c.get_meta("character_data") + n.stats = c.get_meta("stats") + n.animation_node = c.get_meta("animation_node") + n.xform = var2str(c.global_transform) + scenario.save_data.characters.push_back(n) + return true +func get_player(): + var c = get_viewport().get_camera() + if !c: + return null + if !c.has_meta("player"): + return null + var player = c.get_meta("player") + if !player: + return null + return player + +func unfreeze_character(c): + var data = c.get_meta("character_data") + var stats = c.get_meta("stats") + print("HAIR: ", data.hair, " ", data.hair_mat) + var nc = characters.replace_character(c, data.sex, data.modules, data.face, data.hair, data.hair_mat) + nc.set_meta("stats", stats) + var animtree: AnimationTree = nc.get_meta("animation_tree") + assert(animtree) + var animation_node = c.get_meta("animation_node") + animtree["parameters/state/playback"].start(animation_node) + animtree["parameters/state/playback"].travel(animation_node) + nc.set_meta("saved_anim_state", animation_node) +var state = 0 +var delay = 0.0 +func freeze_all() -> bool: + var player = get_player() + var ok = true + for c in get_tree().get_nodes_in_group("character"): + if c == player: + continue + elif c.name.begins_with("npc_spawn"): + c.queue_free() + continue + elif c.name == "npc" && !c.has_meta("animation_tree"): + print("bad ", c.name, " ", c.get_meta_list()) + for e in c.get_meta_list(): + print("bad", c.get_meta(e)) + c.queue_free() + continue + assert(c.has_meta("animation_tree")) + if c.has_meta("animation_tree"): + freeze_character(c) + else: + ok = false + assert(ok) + return ok +func _process(delta): + var cam = get_viewport().get_camera() + var player = get_player() + if !player: + return + var cpos = cam.global_transform.origin + match state: + 0: + characters.set_process(false) + for c in get_tree().get_nodes_in_group("character"): + if c == player: + continue + var p = c.global_transform.origin + if p.distance_squared_to(cpos) > freeze_dist * freeze_dist: + if c.has_meta("animation_tree"): + freeze_character(c) + characters.set_process(true) + state = 1 + delay = 1.0 +# print("spawned: ", get_tree().get_nodes_in_group("character").size()) +# print("frozen: ", get_tree().get_nodes_in_group("frozen").size()) + 1: + characters.set_process(false) + for c in get_tree().get_nodes_in_group("frozen"): + var p = c.global_transform.origin + if p.distance_squared_to(cpos) < 0.25 * freeze_dist * freeze_dist: + print("unfreeze") + unfreeze_character(c) + characters.set_process(true) + if delay > 0.0: + delay -= delta + else: + state = 0 diff --git a/autoload/inventory.gd b/autoload/inventory.gd new file mode 100644 index 0000000..621b629 --- /dev/null +++ b/autoload/inventory.gd @@ -0,0 +1,89 @@ +extends Node +signal pick_up(item_name, obj) + +func _ready(): + pass + +var items = { + "s_dagger": false +} + +var item_dialogue = { + "s_dagger": { + "item_fullname": "sacrificial dagger", + "item_artname": "the sacrificial dagger", + "item_msg": "You see ancient dagger a small piece of metal with nothing special about it except the feeling of uneasiness and understanding that this is not ordinary weapon, but something with different purpose than just defeating the enemy. Something to thank bloodthirsty gods? Or avoid their wrath.", + "item_take_msg": "You fill freezing touch of the rough dagger at your hand. You feel the touch of ancient history, of many many veins opened, and lots of hearts pierced.", + "item_leave_msg": "You left the dagger be." + } +} + +onready var item_scenes = { + "s_dagger": load("res://scenes/weapons/sacrificial_dagger.tscn") +} +onready var item_collision_scenes = { + "s_dagger": load("res://scenes/weapons/dagger_collision.tscn") +} +func equip(obj, item_name): + if obj.has_meta("equipped"): + return + print("EQUIP ", item_name) + assert(obj) + assert(item_scenes.has(item_name)) + var r = item_scenes[item_name].instance() + var c = item_collision_scenes[item_name].instance() + obj.add_child(r) + r.add_child(c) + r.transform = Transform() + c.transform = Transform() + print("EQUIP ", item_name, " OK", obj, r) + obj.set_meta("equipped", item_name) +func register_pick_up(m, obj, item_name): + var mdata = { + "method": "pick_up", + "item": item_name, + "item_obj": obj + } + markers.init_marker(self, m, mdata) + +func pick_up_dialogue(item, item_obj): + return +# if controls.is_gui: +# return +# Dialogic.set_autosave(false) +# var scene = "pick_up_item" +# print("SCENE: ", scene) +# controls.is_gui = true +# var dialogue = Dialogic.start(scene, false) +# Dialogic.set_variable("item_name", item) +# Dialogic.set_variable("item_fullname", item_dialogue[item].item_fullname) +# Dialogic.set_variable("item_artname", item_dialogue[item].item_artname) +# Dialogic.set_variable("item_msg", item_dialogue[item].item_msg) +# Dialogic.set_variable("item_take_msg", item_dialogue[item].item_take_msg) +# Dialogic.set_variable("item_leave_msg", item_dialogue[item].item_leave_msg) +# add_child(dialogue) +# dialogue.connect("timeline_end", self, "finish_dialogue", [dialogue]) +# dialogue.connect("dialogic_signal", self, "signal_process", [dialogue]) +# dialogue.set_meta("item", item) +# dialogue.set_meta("item_obj", item_obj) +func finish_dialogue(dname, d): + controls.is_gui = false + d.queue_free() + +func signal_process(s, d): + var item = d.get_meta("item") + var item_obj = d.get_meta("item_obj") + match s: + "item_accepted": + items[item] = true + emit_signal("pick_up", item, item_obj) + "item_rejected": + pass +func pick_up(obj): + if items.has(obj.item) && items[obj.item]: + return + if item_dialogue.has(obj.item): + pick_up_dialogue(obj.item, obj.item_obj) + else: + items[obj.item] = true + emit_signal("pick_up", obj.item, obj.item_obj) diff --git a/autoload/map.gd b/autoload/map.gd new file mode 100644 index 0000000..cf28113 --- /dev/null +++ b/autoload/map.gd @@ -0,0 +1,52 @@ +tool +extends Node +export var noise: OpenSimplexNoise +export var curve: Curve +# +#var points = [] +##var rg: RoadGrid +#var setup = false +# +#func _ready(): +# if curve: +# curve.bake() +# else: +# curve = Curve.new() +# curve.min_value = -300 +# curve.max_value = 300 +# curve.add_point(Vector2(0, -300)) +# curve.add_point(Vector2(1, 300)) +# curve.bake() +# rg.build(curve, noise) +# setup = true +# +#func _init(): +# rg = Roads.get_road_grid() + +# var center = Vector2(0, 0) +# points.push_back(center) +# randomize() +# var npatches = 8 +# var sa = randf() * 2.0 * PI +# var center_count = 15 + randi() % 5 +# var center_step = 500 +# var centers = [] +# while centers.size() < center_count: +# var center_x = clamp(center_step * ((randi() % 100) - 50), -10000, 10000) +# var center_y = clamp(center_step * ((randi() % 100) - 50), -10000, 10000) +# var c = Vector2(center_x, center_y) +# if !c in centers: +# centers.push_back(c) +# for cx in centers: +# for e in range(npatches * 8): +# var a = sa + sqrt(e) * 8.0 +# var r = 0 if e == 0 else 100 + e * 100.0 + 50 * randf() +# var x = cos(a) * r + cx.x +# var y = sin(a) * r + cx.y +# var d = Vector2(x, y) +# points.push_back(d) +# print("voronoi start") +# var diagram = Voronoi.generate_diagram(points, 11) +# print("voronoi end, processing") +# rg.process_diagram(diagram) +# print("processing done") diff --git a/autoload/map.tscn b/autoload/map.tscn new file mode 100644 index 0000000..4b2bc77 --- /dev/null +++ b/autoload/map.tscn @@ -0,0 +1,16 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://autoload/map.gd" type="Script" id=1] + +[sub_resource type="OpenSimplexNoise" id=2] + +[sub_resource type="Curve" id=1] +min_value = -300.0 +max_value = 300.0 +bake_resolution = 200 +_data = [ Vector2( 0, -259.615 ), 0.0, 0.0, 0, 0, Vector2( 0.975, 300 ), 0.0, 0.0, 0, 0 ] + +[node name="Map" type="Node"] +script = ExtResource( 1 ) +noise = SubResource( 2 ) +curve = SubResource( 1 ) diff --git a/autoload/marker.gd b/autoload/marker.gd new file mode 100644 index 0000000..39ef729 --- /dev/null +++ b/autoload/marker.gd @@ -0,0 +1,213 @@ +extends Node + +var marker_list = [] +var label_count = 10 +var labels = [] +var max_dist = 4 +var current_marker +var cam + +func node_added(node): + if node.name.begins_with("marker_"): + if !node in marker_list: + marker_list.push_back(node) +func node_removed(node): + marker_list.erase(node) + +var state = 0 +func _ready(): + get_tree().connect("node_added", self, "node_added") + get_tree().connect("node_removed", self, "node_removed") + var root = get_tree().get_root() + var queue = [root] + while queue.size() > 0: + var item = queue.pop_front() + if item.name.begins_with("marker_"): + marker_list.push_back(item) + for e in item.get_children(): + queue.push_back(e) + +func see_through_marker(m): + if !m.has_meta("marker_data"): + return false + var md = m.get_meta("marker_data") + if md.has("see_through") && md.see_through == true: + return true + return false + +func _process(delta): + if state == 0: + var root = get_tree().get_root() + for _e in range(label_count): + var tl = Label.new() + root.add_child(tl) + tl.hide() + labels.push_back(tl) + state = 1 + if state == 1: + var cam = get_viewport().get_camera() + if !cam.has_meta("player"): + return + var player = cam.get_meta("player") + assert(player) + var size = get_viewport().size + var center = size/2 + var visible_markers = [] + var wstate = cam.get_world().direct_space_state + for e in marker_list: + var cam_pos = cam.global_transform.origin + var player_pos = player.global_transform.origin + var marker_pos = e.global_transform.origin + if player_pos.distance_squared_to(marker_pos) < max_dist * max_dist: + var lpos = cam.global_transform.xform_inv(marker_pos) + if lpos.z < 0: + if see_through_marker(e) && e.visible: + visible_markers.push_back(e) + elif e.visible: + var xlist = [player] + if e.has_meta("marker_data"): + var md = e.get_meta("marker_data") + if !md.has("obj"): + e.hide() + else: + if md.obj is PhysicsBody: + xlist.push_back(md.obj) + else: + e.hide() + + var result = wstate.intersect_ray(cam_pos, marker_pos, xlist) + if !result.has("collider") || !result.collider: + visible_markers.push_back(e) + + var free_labels = [] + var process_markers = visible_markers.duplicate() + for e in labels: + var l: Label = e + if l.has_meta("marker"): +# var n = l.get_meta("marker") +# if n in visible_markers: +# process_markers.erase(n) +# else: + l.remove_meta("marker") + free_labels.push_back(l) + l.hide() + else: + free_labels.push_back(l) + l.hide() + if free_labels.size() == 0: + state = 2 + return + for e in process_markers: + if free_labels.size() == 0: + break + var pos = cam.unproject_position(e.global_transform.origin) + var l = free_labels.pop_front() + var t = InputMap.get_action_list("activate")[0].as_text() + ": " + if e.name.ends_with("_door"): + t += "Open" + elif e.name.ends_with("_container"): + t += "Access" + elif e.name.ends_with("_pickup"): + t += "Pick up" + elif e.name.ends_with("_vehicleseat") || e.name.ends_with("_seat"): + t += "Sit" + elif e.name.ends_with("_exit"): + t += "Exit" + elif e.name.ends_with("_talk"): + t += "Talk" + elif e.name.ends_with("_action"): + t += "Action" + elif e.name.ends_with("_grab"): + t += "Grab" + elif e.name.ends_with("_take"): + t += "Take" + elif e.name.ends_with("_sacrifice"): + t += "Sacrifice" + l.set_meta("marker", e) + l.text = t + l.add_color_override("font_color", Color(0.6,0.6,1,1)) + l.rect_position = pos - l.rect_size / 2.0 + l.show() + var current = null + var cur_d = INF + for l in labels: + if l.visible: + var d = l.rect_position.distance_squared_to(center) + if !current: + cur_d = d + current = l + else: + if cur_d > d: + current = l + cur_d = d + if current: + current.add_color_override("font_color", Color(0.9,0.9,1,1)) + current_marker = current.get_meta("marker") + else: + current_marker = null + + state = 2 + + if state == 2: + state = 1 +# var player = get_viewport().get_camera().get_meta("player") +# if !controls.is_gui && !player.has_meta("group_behavior") && !player.has_meta("") +# if Input.is_action_just_pressed("activate"): +# var marker = current_marker +# if marker && marker.has_meta("marker_data"): +# var md = marker.get_meta("marker_data") +# print("marker_data: ", md) +# if md.has("obj"): +# print("obj: ", md.obj.name) +# if md.has("obj") && md.has("method"): +# print("activate ", md.obj.name, " ", md.method) +# md.obj.call_deferred(md.method, md) +func activate_marker(): + print("Activate marker") + var marker = current_marker + if marker && marker.has_meta("marker_data"): + var md = marker.get_meta("marker_data") + print("marker_data: ", md) + if md.has("obj"): + print("obj: ", md.obj.name) + if md.has("obj") && md.has("method"): + print("activate ", md.obj.name, " ", md.method) + md.obj.call_deferred(md.method, md) + +func init_markers(obj, marker_info): + var queue = [obj] + while queue.size() > 0: + var item = queue.pop_front() + if item.name.begins_with("marker_"): + if marker_info.has(item.name): + marker_info[item.name].marker_obj = item + for e in item.get_children(): + queue.push_back(e) + queue = [obj] + while queue.size() > 0: + var item = queue.pop_front() + if item.name.begins_with("marker_"): + var marker_data = {} + marker_data.obj = obj + if marker_info.has(item.name): + var o = marker_info[item.name] + for k in o.keys(): + marker_data[k] = o[k] + if o.has("see_through") && o.see_through: + item.hide() + item.set_meta("marker_data", marker_data) + for e in item.get_children(): + queue.push_back(e) +func init_marker(m, obj, data): + assert(m) + assert(obj) + assert(data) + var marker_data = {} + marker_data.obj = m + for e in data.keys(): + marker_data[e] = data[e] + if data.has("see_through") && data.see_through: + obj.hide() + obj.set_meta("marker_data", marker_data) + if !obj in marker_list: + marker_list.push_back(obj) diff --git a/autoload/scenario.gd b/autoload/scenario.gd new file mode 100644 index 0000000..0dd2c5d --- /dev/null +++ b/autoload/scenario.gd @@ -0,0 +1,17 @@ +extends Node + + +# 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(): + pass # Replace with function body. + +var save_data = {} + +# Called every frame. 'delta' is the elapsed time since the previous frame. +#func _process(delta): +# pass diff --git a/autoload/streaming.gd b/autoload/streaming.gd new file mode 100644 index 0000000..0ce8a79 --- /dev/null +++ b/autoload/streaming.gd @@ -0,0 +1,296 @@ +extends Node + +export var trailer_house: PackedScene +export var palace: PackedScene +export var car: PackedScene + +onready var obj_names = { + "palace": palace, + "trailer_house": trailer_house +} + +var done = false + +class radial_grid: + var radial_points = [] + var max_r = 0.0 + var grid = [] + var width: int = 0 + var height: int = 0 + var nodes = [] + func build(poly, center): + var height = center.y + max_r = 0.0 + for p in range(poly.size()): + var ep1 = poly[p] + ep1.y = height + var ep2 = poly[(p + 1) % poly.size()] + ep2.y = height + var d = (ep2 - ep1).normalized() + radial_points.push_back(ep1) + var dst = ep1.distance_to(ep2) + while dst > 32: + ep1 += d * 32 + radial_points.push_back(ep1) + dst -= 32 + for p in range(radial_points.size()): + var ep = radial_points[p] + var dst = ep.distance_to(center) + if max_r < dst: + max_r = dst + width = radial_points.size() + height = int(max_r / 32) + grid.resize(width * height) + for p in range(width): + var start = radial_points[p] + var end = center + var step = (end - start).normalized() * (end - start).length() / float(height + 1) + var val = start + for q in range(height): + grid[p * height + q] = {"position": val, "node": null} + func get_grid_node(x, y): + return grid[x * height + y].node + func set_grid_node(x, y, node): + if !node in nodes: + nodes.push_back(node) + grid[x * height + y].node = node + func place_grid(aabb: AABB, node) -> void: + for u in range(width): + for v in range(height): + if aabb.has_point(grid[u * height + v].position): + set_grid_node(u, v, node) + func get_pos(x, y): + return grid[x * height + y].position + +onready var grid = radial_grid.new() + +func debug_poly(poly): + for k in range(poly.size()): + var p1 = poly[k] + var p2 = poly[(k + 1) % poly.size()] + var l = p1.distance_to(p2) + var d = (p2 - p1).normalized() + var pt = p1 + while l > 0.0: + for e in range(0, 30, 2): + var mi = MeshInstance.new() + mi.mesh = CubeMesh.new() + get_tree().root.add_child(mi) + mi.global_transform.origin = pt + Vector3(0, e, 0) + pt += d * 5.0 + l -= 5.0 + +func calc_border(poly, offt): + var height = RoadsData.get_site_avg_height(0) + var border = [] + border.resize(poly.size()) + for k in range(poly.size()): + var i = k - 1 + if i < 0: + i += poly.size() + var p1 = poly[i] + var p2 = poly[k] + var p3 = poly[(k + 1) % poly.size()] + var p1x = Vector2(p1.x, p1.z) + var p2x = Vector2(p2.x, p2.z) + var p3x = Vector2(p2.x, p2.z) + var p4x = Vector2(p3.x, p3.z) + var n1 = (p2x - p1x).tangent().normalized() + var n2 = (p4x - p3x).tangent().normalized() + p1x -= n1 * offt + p2x -= n1 * offt + p3x -= n2 * offt + p4x -= n2 * offt + + var xp = Geometry.segment_intersects_segment_2d(p1x, p2x, p3x, p4x) + if !xp: + xp = p2x.linear_interpolate(p3x, 0.5) - (n1 + n2).normalized() * offt + var tp = Vector3(xp.x, height, xp.y) + border[k] = tp + return border + +var towns = 0 +func setup_town(site): + if !RoadsData.site_is_town(site): + print("site ", site, " type: ", RoadsData.get_site_type(site)) + return + var poly = RoadsData.get_site_polygon_3d(site) + var height = RoadsData.get_site_avg_height(site) + var border2 = calc_border(poly, 60) + var aabbs = [] + var poly2 = [] + poly2.resize(border2.size()) + for p in range(border2.size()): + poly2[p] = Vector2(border2[p].x, border2[p].z) + var center = Vector3() + for p in poly: + center += p + center /= poly.size() + center.y = height + grid.build(border2, center) + var radial_points = grid.radial_points + var max_r = 0.0 + for p in range(radial_points.size()): + var ep = radial_points[p] + var dst = ep.distance_to(center) + if max_r < dst: + max_r = dst + for p in range(radial_points.size()): + var ep = radial_points[p] + var d = (center - ep).normalized() + var dst = ep.distance_to(center) + print(dst) + if dst < 64.0 + 12 + 8 + 4: + continue + var step = 16.0 + var pstart = ep + while dst > 0.0: + var ok = true + if !Geometry.is_point_in_polygon(Vector2(pstart.x, pstart.z), poly2): + ok = false + if ok: + for b in aabbs: + if b.has_point(pstart): + ok = false + if ok: + var xform = Transform(Basis(), pstart).looking_at(pstart + d, Vector3.UP) + stream_obj("trailer_house", xform) + var aabb = AABB(pstart, Vector3()) + aabb = aabb.grow(20) + aabbs.push_back(aabb) + print("placed to: ", pstart) + pstart = pstart + d * step + dst -= step + towns += 1 + +func setup_first_town(): + assert(!done) + var poly = RoadsData.get_site_polygon_3d(0) + var height = RoadsData.get_site_avg_height(0) + var border = calc_border(poly, 32) + var border1a = calc_border(poly, 42) + var border2 = calc_border(poly, 60) + + var poly2 = [] + poly2.resize(border2.size()) + for p in range(border2.size()): + poly2[p] = Vector2(border2[p].x, border2[p].z) + var center = Vector3() + for p in poly: + center += p + center /= poly.size() + center.y = height + grid.build(border2, center) + var radial_points = grid.radial_points + var max_r = 0.0 + for p in range(radial_points.size()): + var ep = radial_points[p] + var dst = ep.distance_to(center) + if max_r < dst: + max_r = dst + var u = radial_points.size() + var v = int(max_r / 32) + var grid = [] + grid.resize(u * v) + for p in range(u): + var start = radial_points[p] + var end = center + var step = (end - start).normalized() * (end - start).length() / float(v + 1) + var val = start + for q in range(v): + grid[p * v + q] = {"position": val} + var aabbs = [] + var palace_aabb = AABB(center, Vector3()) + palace_aabb = palace_aabb.grow(48) + print(palace_aabb) + aabbs.push_back(palace_aabb) + stream_obj("palace", Transform(Basis(), center)) + + for p in range(radial_points.size()): + var ep = radial_points[p] + var d = (center - ep).normalized() + var dst = ep.distance_to(center) + print(dst) + if dst < 64.0 + 12 + 8 + 4: + continue + var step = 16.0 + var pstart = ep + while dst > 0.0: + var ok = true + if !Geometry.is_point_in_polygon(Vector2(pstart.x, pstart.z), poly2): + ok = false + if ok: + for b in aabbs: + if b.has_point(pstart): + ok = false + if ok: + var xform = Transform(Basis(), pstart).looking_at(pstart + d, Vector3.UP) + stream_obj("trailer_house", xform) + var aabb = AABB(pstart, Vector3()) + aabb = aabb.grow(20) + aabbs.push_back(aabb) + print("placed to: ", pstart) + pstart = pstart + d * step + dst -= step + towns += 1 + done = true + +func _ready(): + for k in obj_names.keys(): + Spawner.add_scene(k, obj_names[k]) + +# Called every frame. 'delta' is the elapsed time since the previous frame. +var delay = 3.0 +var state = 0 +func _process(delta): + match state: + 0: + delay -= delta + if delay < 0: + state = 1 + 1: + Spawner.update_view(self, 300) + var sc = get_tree().root + var viewport: = get_viewport() + if !viewport: + return + var cam: = viewport.get_camera() + if !cam: + return + var cam_xform: = cam.global_transform + +func stream_obj(obj: String, xform: Transform): + Spawner.place_scene(obj, xform) +func _physics_process(delta): + var cam = get_viewport().get_camera() + if !cam: + return + match state: + 1: + var space_state = get_viewport().get_world().direct_space_state + # probaly should not be here + for n in get_tree().get_nodes_in_group("spawn"): + var ok = false + if !n.is_in_group("keep"): + var where = n.get_global_transform().origin + var from = where + var to = where + from.y -= 8.0 + to.y += 8.0 + var result = space_state.intersect_ray(from, to) + if result.empty() || !result.has("collider"): + continue + if result.collider: + n.global_transform.origin = result.position + ok = true + if ok || n.is_in_group("keep"): + if n.is_in_group("male"): + characters.replace_character(n, "male", ["cmdq", "marker", "hurtboxes", "student"]) + elif n.is_in_group("female"): + characters.replace_character(n, "female", ["cmdq", "marker", "hurtboxes", "student"]) + elif n.is_in_group("car"): + var c = car.instance() + var p = get_tree().root + p.add_child(c) + c.global_transform = n.global_transform + n.queue_free() diff --git a/autoload/streaming.tscn b/autoload/streaming.tscn new file mode 100644 index 0000000..473b595 --- /dev/null +++ b/autoload/streaming.tscn @@ -0,0 +1,12 @@ +[gd_scene load_steps=5 format=2] + +[ext_resource path="res://autoload/streaming.gd" type="Script" id=1] +[ext_resource path="res://objects/trailer-house.tscn" type="PackedScene" id=2] +[ext_resource path="res://objects/palace.tscn" type="PackedScene" id=3] +[ext_resource path="res://scenes/vehicles/car.tscn" type="PackedScene" id=4] + +[node name="streaming" type="Node"] +script = ExtResource( 1 ) +trailer_house = ExtResource( 2 ) +palace = ExtResource( 3 ) +car = ExtResource( 4 ) diff --git a/camera/camera_pos.tscn b/camera/camera_pos.tscn new file mode 100644 index 0000000..378cd99 --- /dev/null +++ b/camera/camera_pos.tscn @@ -0,0 +1,26 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://camera/environment.tres" type="Environment" id=1] + +[sub_resource type="SphereShape" id=1] +radius = 0.1 + +[node name="camera_pos" type="Spatial"] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 6.75037, 0 ) + +[node name="rot_y" type="Spatial" parent="."] + +[node name="rot_x" type="Spatial" parent="rot_y"] + +[node name="SpringArm" type="SpringArm" parent="rot_y/rot_x"] +transform = Transform( 1, 0, 0, 0, 0.903013, 0.429613, 0, -0.429613, 0.903013, 0, 1.75, 0.2 ) +shape = SubResource( 1 ) +spring_length = 2.0 +margin = 0.04 + +[node name="camera_offset" type="Spatial" parent="rot_y/rot_x/SpringArm"] + +[node name="Camera" type="Camera" parent="rot_y/rot_x/SpringArm/camera_offset"] +transform = Transform( 1, 0, 0, 0, 0.900455, -0.434948, 0, 0.434948, 0.900455, 0, 0, 0 ) +environment = ExtResource( 1 ) +far = 350.0 diff --git a/camera/environment.tres b/camera/environment.tres new file mode 100644 index 0000000..f4c6c6d --- /dev/null +++ b/camera/environment.tres @@ -0,0 +1,15 @@ +[gd_resource type="Environment" load_steps=2 format=2] + +[sub_resource type="ProceduralSky" id=1] + +[resource] +background_mode = 2 +background_sky = SubResource( 1 ) +ambient_light_energy = 0.7 +fog_enabled = true +fog_color = Color( 0.447059, 0.501961, 0.552941, 1 ) +fog_sun_color = Color( 1, 0.901961, 0.701961, 1 ) +fog_sun_amount = 0.25 +fog_depth_end = 250.0 +fog_depth_curve = 0.196146 +dof_blur_far_quality = 0 diff --git a/camera/fps_cam_pos.tscn b/camera/fps_cam_pos.tscn new file mode 100644 index 0000000..6d78e86 --- /dev/null +++ b/camera/fps_cam_pos.tscn @@ -0,0 +1,13 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://camera/environment.tres" type="Environment" id=1] + +[node name="fps_cam_pos" type="Spatial"] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.75, -0.2 ) + +[node name="fos_cam_rot_y" type="Spatial" parent="."] + +[node name="fps_cam_rot_x" type="Spatial" parent="fos_cam_rot_y"] + +[node name="fps_camera" type="Camera" parent="fos_cam_rot_y/fps_cam_rot_x"] +environment = ExtResource( 1 ) diff --git a/characters/character.gd b/characters/character.gd new file mode 100644 index 0000000..8f4db18 --- /dev/null +++ b/characters/character.gd @@ -0,0 +1,12 @@ +extends KinematicBody + + +func _ready(): + add_to_group("characters") + +func hide_face(): + $"vroid1-man/Skeleton/head/face".hide() + $"vroid1-man/Skeleton/head/hair".hide() +func show_face(): + $"vroid1-man/Skeleton/head/face".show() + $"vroid1-man/Skeleton/head/hair".show() diff --git a/characters/vroid1-female.tscn b/characters/vroid1-female.tscn new file mode 100644 index 0000000..7a9f044 --- /dev/null +++ b/characters/vroid1-female.tscn @@ -0,0 +1,734 @@ +[gd_scene load_steps=138 format=2] + +[ext_resource path="res://scenes/characters/vroid1-female.gltf" type="PackedScene" id=1] +[ext_resource path="res://scenes/hair/female-hair1.tscn" type="PackedScene" id=2] +[ext_resource path="res://scenes/face/female-face1.tscn" type="PackedScene" id=3] + +[sub_resource type="SphereShape" id=1] +radius = 0.13 + +[sub_resource type="SphereShape" id=2] +radius = 0.14 + +[sub_resource type="BoxShape" id=3] +extents = Vector3( 0.13, 0.16, 0.06 ) + +[sub_resource type="AnimationNodeAnimation" id=4] +animation = "blend-right-arm-blade" + +[sub_resource type="AnimationNodeAnimation" id=5] +animation = "blend-left-arm-blade" + +[sub_resource type="AnimationNodeTimeScale" id=6] + +[sub_resource type="AnimationNodeBlend2" id=7] +filter_enabled = true +filters = [ "skeleton/Skeleton:hand_l", "skeleton/Skeleton:index_1_l", "skeleton/Skeleton:index_2_l", "skeleton/Skeleton:index_3_end_l", "skeleton/Skeleton:index_3_l", "skeleton/Skeleton:little_1_l", "skeleton/Skeleton:little_2_l", "skeleton/Skeleton:little_3_end_l", "skeleton/Skeleton:little_3_l", "skeleton/Skeleton:middle_1_l", "skeleton/Skeleton:middle_2_l", "skeleton/Skeleton:middle_3_end_l", "skeleton/Skeleton:middle_3_l", "skeleton/Skeleton:ring_1_l", "skeleton/Skeleton:ring_2_l", "skeleton/Skeleton:ring_3_end_l", "skeleton/Skeleton:ring_3_l", "skeleton/Skeleton:thumb_1_l", "skeleton/Skeleton:thumb_2_l", "skeleton/Skeleton:thumb_3_end_l", "skeleton/Skeleton:thumb_3_l" ] + +[sub_resource type="AnimationNodeBlend2" id=8] +filter_enabled = true +filters = [ "skeleton/Skeleton:hand_r", "skeleton/Skeleton:index_1_r", "skeleton/Skeleton:index_2_r", "skeleton/Skeleton:index_3_end_r", "skeleton/Skeleton:index_3_r", "skeleton/Skeleton:little_1_r", "skeleton/Skeleton:little_2_r", "skeleton/Skeleton:little_3_end_r", "skeleton/Skeleton:little_3_r", "skeleton/Skeleton:middle_1_r", "skeleton/Skeleton:middle_2_r", "skeleton/Skeleton:middle_3_end_r", "skeleton/Skeleton:middle_3_r", "skeleton/Skeleton:ring_1_r", "skeleton/Skeleton:ring_2_r", "skeleton/Skeleton:ring_3_end_r", "skeleton/Skeleton:ring_3_r", "skeleton/Skeleton:thumb_1_r", "skeleton/Skeleton:thumb_2_r", "skeleton/Skeleton:thumb_3_end_r", "skeleton/Skeleton:thumb_3_r" ] + +[sub_resource type="AnimationNodeAnimation" id=9] +animation = "climb1" + +[sub_resource type="AnimationNodeTimeScale" id=10] + +[sub_resource type="AnimationNodeBlendTree" id=11] +nodes/Animation/node = SubResource( 9 ) +nodes/Animation/position = Vector2( 235, 191 ) +nodes/TimeScale/node = SubResource( 10 ) +nodes/TimeScale/position = Vector2( 480, 160 ) +nodes/output/position = Vector2( 760, 160 ) +node_connections = [ "output", 0, "TimeScale", "TimeScale", 0, "Animation" ] + +[sub_resource type="AnimationNodeAnimation" id=12] +animation = "climb1a" + +[sub_resource type="AnimationNodeTimeScale" id=13] + +[sub_resource type="AnimationNodeBlendTree" id=14] +nodes/Animation/node = SubResource( 12 ) +nodes/Animation/position = Vector2( 354, 279 ) +nodes/TimeScale/node = SubResource( 13 ) +nodes/TimeScale/position = Vector2( 763, 297 ) +nodes/output/position = Vector2( 1220, 300 ) +node_connections = [ "output", 0, "TimeScale", "TimeScale", 0, "Animation" ] + +[sub_resource type="AnimationNodeBlendTree" id=15] + +[sub_resource type="AnimationNodeAnimation" id=16] +animation = "start-grabbed" + +[sub_resource type="AnimationNodeTimeScale" id=17] + +[sub_resource type="AnimationNodeBlendTree" id=18] +nodes/Animation/node = SubResource( 16 ) +nodes/Animation/position = Vector2( 380, 100 ) +nodes/TimeScale/node = SubResource( 17 ) +nodes/TimeScale/position = Vector2( 592, 184 ) +nodes/output/position = Vector2( 860, 120 ) +node_connections = [ "output", 0, "TimeScale", "TimeScale", 0, "Animation" ] + +[sub_resource type="AnimationNodeAnimation" id=19] +animation = "female-idle-to-kneel1" + +[sub_resource type="AnimationNodeTimeScale" id=20] + +[sub_resource type="AnimationNodeBlendTree" id=21] +nodes/Animation/node = SubResource( 19 ) +nodes/Animation/position = Vector2( 390, 274 ) +nodes/TimeScale/node = SubResource( 20 ) +nodes/TimeScale/position = Vector2( 826, 273 ) +nodes/output/position = Vector2( 1180, 280 ) +node_connections = [ "output", 0, "TimeScale", "TimeScale", 0, "Animation" ] + +[sub_resource type="AnimationNodeAnimation" id=22] +animation = "11_01-idle" + +[sub_resource type="AnimationNodeAnimation" id=23] +animation = "10_01-idle" + +[sub_resource type="AnimationNodeTimeScale" id=24] + +[sub_resource type="AnimationNodeTimeScale" id=25] + +[sub_resource type="AnimationNodeTransition" id=26] +input_count = 2 +xfade_time = 0.4 +input_0/name = "idle1" +input_0/auto_advance = true +input_1/name = "idle2" +input_1/auto_advance = true + +[sub_resource type="AnimationNodeBlendTree" id=27] +nodes/Animation/node = SubResource( 23 ) +nodes/Animation/position = Vector2( 55, 117 ) +"nodes/Animation 2/node" = SubResource( 22 ) +"nodes/Animation 2/position" = Vector2( 80, 260 ) +nodes/TimeScale/node = SubResource( 25 ) +nodes/TimeScale/position = Vector2( 580, 100 ) +"nodes/TimeScale 2/node" = SubResource( 24 ) +"nodes/TimeScale 2/position" = Vector2( 380, 240 ) +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", "TimeScale 2", 0, "Animation 2", "t1", 0, "TimeScale", "t1", 1, "TimeScale 2" ] + +[sub_resource type="AnimationNodeAnimation" id=28] +animation = "walk1p2" + +[sub_resource type="AnimationNodeAnimation" id=29] +animation = "walk1p1" + +[sub_resource type="AnimationNodeTimeScale" id=30] + +[sub_resource type="AnimationNodeTimeScale" id=31] + +[sub_resource type="AnimationNodeTransition" id=32] +input_count = 2 +input_0/name = "state 0" +input_0/auto_advance = true +input_1/name = "state 1" +input_1/auto_advance = true + +[sub_resource type="AnimationNodeBlendTree" id=33] +nodes/Animation/node = SubResource( 29 ) +nodes/Animation/position = Vector2( 140, 100 ) +"nodes/Animation 2/node" = SubResource( 28 ) +"nodes/Animation 2/position" = Vector2( 180, 260 ) +nodes/TimeScale/node = SubResource( 31 ) +nodes/TimeScale/position = Vector2( 620, 40 ) +"nodes/TimeScale 2/node" = SubResource( 30 ) +"nodes/TimeScale 2/position" = Vector2( 610, 231 ) +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", "Transition", 0, "TimeScale", "Transition", 1, "TimeScale 2", "TimeScale 2", 0, "Animation 2" ] + +[sub_resource type="AnimationNodeAnimation" id=34] +animation = "07_01-walk" + +[sub_resource type="AnimationNodeTimeScale" id=35] + +[sub_resource type="AnimationNodeBlendTree" id=36] +nodes/Animation/node = SubResource( 34 ) +nodes/Animation/position = Vector2( 128, 154 ) +nodes/TimeScale/node = SubResource( 35 ) +nodes/TimeScale/position = Vector2( 420, 160 ) +nodes/output/position = Vector2( 640, 160 ) +node_connections = [ "output", 0, "TimeScale", "TimeScale", 0, "Animation" ] + +[sub_resource type="AnimationNodeAnimation" id=37] +animation = "07_03-walk" + +[sub_resource type="AnimationNodeTimeScale" id=38] + +[sub_resource type="AnimationNodeBlendTree" id=39] +nodes/Animation/node = SubResource( 37 ) +nodes/Animation/position = Vector2( 220, 120 ) +nodes/TimeScale/node = SubResource( 38 ) +nodes/TimeScale/position = Vector2( 580, 120 ) +nodes/output/position = Vector2( 840, 140 ) +node_connections = [ "output", 0, "TimeScale", "TimeScale", 0, "Animation" ] + +[sub_resource type="AnimationNodeAnimation" id=40] +animation = "walk1p2" + +[sub_resource type="AnimationNodeAnimation" id=41] +animation = "walk1p1" + +[sub_resource type="AnimationNodeTimeScale" id=42] + +[sub_resource type="AnimationNodeTimeScale" id=43] + +[sub_resource type="AnimationNodeTransition" id=44] +input_count = 2 +input_0/name = "state 0" +input_0/auto_advance = true +input_1/name = "state 1" +input_1/auto_advance = true + +[sub_resource type="AnimationNodeBlendTree" id=45] +graph_offset = Vector2( 0, -259 ) +nodes/Animation/node = SubResource( 41 ) +nodes/Animation/position = Vector2( 200, 80 ) +"nodes/Animation 2/node" = SubResource( 40 ) +"nodes/Animation 2/position" = Vector2( 200, 280 ) +nodes/TimeScale/node = SubResource( 43 ) +nodes/TimeScale/position = Vector2( 660, 60 ) +"nodes/TimeScale 2/node" = SubResource( 42 ) +"nodes/TimeScale 2/position" = Vector2( 580, 260 ) +nodes/Transition/node = SubResource( 44 ) +nodes/Transition/position = Vector2( 920, 120 ) +nodes/output/position = Vector2( 1260, 160 ) +node_connections = [ "output", 0, "Transition", "TimeScale", 0, "Animation", "Transition", 0, "TimeScale", "Transition", 1, "TimeScale 2", "TimeScale 2", 0, "Animation 2" ] + +[sub_resource type="AnimationNodeAnimation" id=46] +animation = "walk1p2" + +[sub_resource type="AnimationNodeAnimation" id=47] +animation = "walk1p1" + +[sub_resource type="AnimationNodeTimeScale" id=48] + +[sub_resource type="AnimationNodeTimeScale" id=49] + +[sub_resource type="AnimationNodeTransition" id=50] +input_count = 2 +xfade_time = 0.2 +input_0/name = "state 0" +input_0/auto_advance = true +input_1/name = "state 1" +input_1/auto_advance = true + +[sub_resource type="AnimationNodeBlendTree" id=51] +graph_offset = Vector2( 0, -294.25 ) +nodes/Animation/node = SubResource( 47 ) +nodes/Animation/position = Vector2( 208, 136 ) +"nodes/Animation 2/node" = SubResource( 46 ) +"nodes/Animation 2/position" = Vector2( 230, 287 ) +nodes/TimeScale/node = SubResource( 49 ) +nodes/TimeScale/position = Vector2( 660, 80 ) +"nodes/TimeScale 2/node" = SubResource( 48 ) +"nodes/TimeScale 2/position" = Vector2( 680, 260 ) +nodes/Transition/node = SubResource( 50 ) +nodes/Transition/position = Vector2( 1000, 140 ) +nodes/output/position = Vector2( 1260, 140 ) +node_connections = [ "output", 0, "Transition", "TimeScale", 0, "Animation", "Transition", 0, "TimeScale", "Transition", 1, "TimeScale 2", "TimeScale 2", 0, "Animation 2" ] + +[sub_resource type="AnimationNodeBlendSpace2D" id=52] +blend_point_0/node = SubResource( 27 ) +blend_point_0/pos = Vector2( 0, 0 ) +blend_point_1/node = SubResource( 33 ) +blend_point_1/pos = Vector2( 0.2, 0 ) +blend_point_2/node = SubResource( 36 ) +blend_point_2/pos = Vector2( 0.2, -1 ) +blend_point_3/node = SubResource( 39 ) +blend_point_3/pos = Vector2( 0.2, 1 ) +blend_point_4/node = SubResource( 45 ) +blend_point_4/pos = Vector2( 0.6, 0 ) +blend_point_5/node = SubResource( 51 ) +blend_point_5/pos = Vector2( 0.4, 0 ) + +[sub_resource type="AnimationNodeBlendTree" id=53] +graph_offset = Vector2( 0, -95 ) +nodes/loc/node = SubResource( 52 ) +nodes/loc/position = Vector2( 580, 80 ) +nodes/output/position = Vector2( 960, 160 ) +node_connections = [ "output", 0, "loc" ] + +[sub_resource type="AnimationNodeBlendTree" id=54] + +[sub_resource type="AnimationNodeAnimation" id=55] +animation = "female-pray-startled-walk1-loop" + +[sub_resource type="AnimationNodeAnimation" id=56] +animation = "female-pray-startled-walk1-loop" + +[sub_resource type="AnimationNodeTimeScale" id=57] + +[sub_resource type="AnimationNodeTimeScale" id=58] + +[sub_resource type="AnimationNodeTransition" id=59] +input_count = 2 +input_0/name = "state 0" +input_0/auto_advance = true +input_1/name = "state 1" +input_1/auto_advance = true + +[sub_resource type="AnimationNodeBlendTree" id=60] +nodes/Animation/node = SubResource( 56 ) +nodes/Animation/position = Vector2( 200, 280 ) +"nodes/Animation 2/node" = SubResource( 55 ) +"nodes/Animation 2/position" = Vector2( 200, 420 ) +nodes/TimeScale/node = SubResource( 58 ) +nodes/TimeScale/position = Vector2( 640, 200 ) +"nodes/TimeScale 2/node" = SubResource( 57 ) +"nodes/TimeScale 2/position" = Vector2( 640, 360 ) +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", "Transition", 1, "TimeScale 2", "TimeScale 2", 0, "Animation 2" ] + +[sub_resource type="AnimationNodeAnimation" id=61] +animation = "female-pray-startled1" + +[sub_resource type="AnimationNodeTimeScale" id=62] + +[sub_resource type="AnimationNodeBlendTree" id=63] +nodes/Animation/node = SubResource( 61 ) +nodes/Animation/position = Vector2( 181, 220 ) +nodes/TimeScale/node = SubResource( 62 ) +nodes/TimeScale/position = Vector2( 590, 212 ) +nodes/output/position = Vector2( 880, 160 ) +node_connections = [ "output", 0, "TimeScale", "TimeScale", 0, "Animation" ] + +[sub_resource type="AnimationNodeAnimation" id=64] +animation = "female-pray-complete" + +[sub_resource type="AnimationNodeTimeScale" id=65] + +[sub_resource type="AnimationNodeBlendTree" id=66] +nodes/Animation/node = SubResource( 64 ) +nodes/Animation/position = Vector2( 585, 170 ) +nodes/TimeScale/node = SubResource( 65 ) +nodes/TimeScale/position = Vector2( 865, 191 ) +nodes/output/position = Vector2( 1280, 180 ) +node_connections = [ "output", 0, "TimeScale", "TimeScale", 0, "Animation" ] + +[sub_resource type="AnimationNodeAnimation" id=67] +animation = "idle-lying-tied-attack1" + +[sub_resource type="AnimationNodeAnimation" id=68] +animation = "idle-lying-tied-attack2" + +[sub_resource type="AnimationNodeAnimation" id=69] +animation = "idle-lying-tied-loop" + +[sub_resource type="AnimationNodeTimeScale" id=70] + +[sub_resource type="AnimationNodeTimeScale" id=71] + +[sub_resource type="AnimationNodeOneShot" id=72] + +[sub_resource type="AnimationNodeOneShot" id=73] + +[sub_resource type="AnimationNodeTimeScale" id=74] + +[sub_resource type="AnimationNodeBlendTree" id=75] +graph_offset = Vector2( -12, 62 ) +nodes/Animation/node = SubResource( 69 ) +nodes/Animation/position = Vector2( 222, 131 ) +"nodes/Animation 2/node" = SubResource( 67 ) +"nodes/Animation 2/position" = Vector2( 220, 280 ) +"nodes/Animation 3/node" = SubResource( 68 ) +"nodes/Animation 3/position" = Vector2( 238, 428 ) +nodes/TimeScale/node = SubResource( 71 ) +nodes/TimeScale/position = Vector2( 500, 240 ) +"nodes/TimeScale 2/node" = SubResource( 70 ) +"nodes/TimeScale 2/position" = Vector2( 500, 380 ) +nodes/attack1/node = SubResource( 72 ) +nodes/attack1/position = Vector2( 800, 120 ) +nodes/attack2/node = SubResource( 73 ) +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", "attack1", 0, "speed", "attack1", 1, "TimeScale", "attack2", 0, "attack1", "attack2", 1, "TimeScale 2", "TimeScale 2", 0, "Animation 3" ] + +[sub_resource type="AnimationNodeAnimation" id=76] +animation = "dagger-sacrifice-counter-p" + +[sub_resource type="AnimationNodeTimeScale" id=77] + +[sub_resource type="AnimationNodeBlendTree" id=78] +graph_offset = Vector2( 0, -259 ) +nodes/Animation/node = SubResource( 76 ) +nodes/Animation/position = Vector2( 440, 160 ) +nodes/TimeScale/node = SubResource( 77 ) +nodes/TimeScale/position = Vector2( 760, 140 ) +nodes/output/position = Vector2( 1000, 180 ) +node_connections = [ "output", 0, "TimeScale", "TimeScale", 0, "Animation" ] + +[sub_resource type="AnimationNodeAnimation" id=79] +animation = "sleeping1-loop" + +[sub_resource type="AnimationNodeTimeScale" id=80] + +[sub_resource type="AnimationNodeBlendTree" id=81] +nodes/Animation/node = SubResource( 79 ) +nodes/Animation/position = Vector2( 321, 172 ) +nodes/TimeScale/node = SubResource( 80 ) +nodes/TimeScale/position = Vector2( 600, 160 ) +nodes/output/position = Vector2( 800, 140 ) +node_connections = [ "output", 0, "TimeScale", "TimeScale", 0, "Animation" ] + +[sub_resource type="AnimationNodeAnimation" id=82] +animation = "female-pray-startled-walk1-stand" + +[sub_resource type="AnimationNodeTimeScale" id=83] + +[sub_resource type="AnimationNodeBlendTree" id=84] +graph_offset = Vector2( 0, -259 ) +nodes/Animation/node = SubResource( 82 ) +nodes/Animation/position = Vector2( 120, 160 ) +nodes/TimeScale/node = SubResource( 83 ) +nodes/TimeScale/position = Vector2( 640, 100 ) +nodes/output/position = Vector2( 1040, 80 ) +node_connections = [ "output", 0, "TimeScale", "TimeScale", 0, "Animation" ] + +[sub_resource type="AnimationNodeAnimation" id=121] +animation = "start-walking" + +[sub_resource type="AnimationNodeTimeScale" id=122] + +[sub_resource type="AnimationNodeBlendTree" id=115] +nodes/Animation/node = SubResource( 121 ) +nodes/Animation/position = Vector2( 189, 171 ) +nodes/TimeScale/node = SubResource( 122 ) +nodes/TimeScale/position = Vector2( 420, 160 ) +nodes/output/position = Vector2( 640, 160 ) +node_connections = [ "output", 0, "TimeScale", "TimeScale", 0, "Animation" ] + +[sub_resource type="AnimationNodeAnimation" id=123] +animation = "stop-walking" + +[sub_resource type="AnimationNodeTimeScale" id=124] + +[sub_resource type="AnimationNodeBlendTree" id=116] +nodes/Animation/node = SubResource( 123 ) +nodes/Animation/position = Vector2( 275, 334 ) +nodes/TimeScale/node = SubResource( 124 ) +nodes/TimeScale/position = Vector2( 587, 359 ) +nodes/output/position = Vector2( 860, 340 ) +node_connections = [ "output", 0, "TimeScale", "TimeScale", 0, "Animation" ] + +[sub_resource type="AnimationNodeAnimation" id=131] +animation = "turn-left" + +[sub_resource type="AnimationNodeTimeScale" id=132] + +[sub_resource type="AnimationNodeBlendTree" id=125] +nodes/Animation/node = SubResource( 131 ) +nodes/Animation/position = Vector2( 200, 240 ) +nodes/TimeScale/node = SubResource( 132 ) +nodes/TimeScale/position = Vector2( 445, 231 ) +nodes/output/position = Vector2( 680, 240 ) +node_connections = [ "output", 0, "TimeScale", "TimeScale", 0, "Animation" ] + +[sub_resource type="AnimationNodeAnimation" id=133] +animation = "turn-right" + +[sub_resource type="AnimationNodeTimeScale" id=134] + +[sub_resource type="AnimationNodeBlendTree" id=126] +nodes/Animation/node = SubResource( 133 ) +nodes/Animation/position = Vector2( 213, 136 ) +nodes/TimeScale/node = SubResource( 134 ) +nodes/TimeScale/position = Vector2( 480, 140 ) +nodes/output/position = Vector2( 780, 160 ) +node_connections = [ "output", 0, "TimeScale", "TimeScale", 0, "Animation" ] + +[sub_resource type="AnimationNodeAnimation" id=113] +animation = "default" + +[sub_resource type="AnimationNodeTimeScale" id=114] + +[sub_resource type="AnimationNodeBlendTree" id=85] +nodes/Animation/node = SubResource( 113 ) +nodes/Animation/position = Vector2( 139, 122 ) +nodes/TimeScale/node = SubResource( 114 ) +nodes/TimeScale/position = Vector2( 461, 131 ) +nodes/output/position = Vector2( 860, 140 ) +node_connections = [ "output", 0, "TimeScale", "TimeScale", 0, "Animation" ] + +[sub_resource type="AnimationNodeStateMachineTransition" id=86] + +[sub_resource type="AnimationNodeStateMachineTransition" id=87] + +[sub_resource type="AnimationNodeStateMachineTransition" id=88] + +[sub_resource type="AnimationNodeStateMachineTransition" id=89] + +[sub_resource type="AnimationNodeStateMachineTransition" id=90] + +[sub_resource type="AnimationNodeStateMachineTransition" id=91] + +[sub_resource type="AnimationNodeStateMachineTransition" id=92] + +[sub_resource type="AnimationNodeStateMachineTransition" id=93] +switch_mode = 2 +auto_advance = true + +[sub_resource type="AnimationNodeStateMachineTransition" id=94] + +[sub_resource type="AnimationNodeStateMachineTransition" id=95] +switch_mode = 2 + +[sub_resource type="AnimationNodeStateMachineTransition" id=96] + +[sub_resource type="AnimationNodeStateMachineTransition" id=97] + +[sub_resource type="AnimationNodeStateMachineTransition" id=98] +switch_mode = 2 +auto_advance = true +xfade_time = 0.1 + +[sub_resource type="AnimationNodeStateMachineTransition" id=99] + +[sub_resource type="AnimationNodeStateMachineTransition" id=100] +switch_mode = 2 + +[sub_resource type="AnimationNodeStateMachineTransition" id=101] +switch_mode = 2 + +[sub_resource type="AnimationNodeStateMachineTransition" id=102] + +[sub_resource type="AnimationNodeStateMachineTransition" id=103] + +[sub_resource type="AnimationNodeStateMachineTransition" id=104] + +[sub_resource type="AnimationNodeStateMachineTransition" id=105] +switch_mode = 2 +auto_advance = true + +[sub_resource type="AnimationNodeStateMachineTransition" id=106] + +[sub_resource type="AnimationNodeStateMachineTransition" id=107] +switch_mode = 2 +auto_advance = true + +[sub_resource type="AnimationNodeStateMachineTransition" id=108] +switch_mode = 2 +auto_advance = true + +[sub_resource type="AnimationNodeStateMachineTransition" id=109] + +[sub_resource type="AnimationNodeStateMachineTransition" id=117] + +[sub_resource type="AnimationNodeStateMachineTransition" id=118] +switch_mode = 2 +auto_advance = true + +[sub_resource type="AnimationNodeStateMachineTransition" id=119] + +[sub_resource type="AnimationNodeStateMachineTransition" id=120] +switch_mode = 2 +auto_advance = true + +[sub_resource type="AnimationNodeStateMachineTransition" id=127] + +[sub_resource type="AnimationNodeStateMachineTransition" id=128] +switch_mode = 2 + +[sub_resource type="AnimationNodeStateMachineTransition" id=129] + +[sub_resource type="AnimationNodeStateMachineTransition" id=130] +switch_mode = 2 + +[sub_resource type="AnimationNodeStateMachine" id=110] +states/climb1/node = SubResource( 11 ) +states/climb1/position = Vector2( 804, 503.193 ) +states/climb1a/node = SubResource( 14 ) +states/climb1a/position = Vector2( 947, 503.193 ) +states/drive/node = SubResource( 15 ) +states/drive/position = Vector2( 868, 316.193 ) +states/grabbed/node = SubResource( 18 ) +states/grabbed/position = Vector2( 1277, 182.193 ) +states/kneel/node = SubResource( 21 ) +states/kneel/position = Vector2( 522, 84 ) +states/locomotion/node = SubResource( 53 ) +states/locomotion/position = Vector2( 822, 111 ) +states/passenger/node = SubResource( 54 ) +states/passenger/position = Vector2( 574, 327 ) +states/pray/node = SubResource( 66 ) +states/pray/position = Vector2( 381, 222 ) +states/pray-startled/node = SubResource( 63 ) +states/pray-startled/position = Vector2( 294, 316.193 ) +states/pray-startled-walk/node = SubResource( 60 ) +states/pray-startled-walk/position = Vector2( 294, 514.193 ) +states/sacrifice/node = SubResource( 75 ) +states/sacrifice/position = Vector2( 1023, 135 ) +states/sacrificed/node = SubResource( 78 ) +states/sacrificed/position = Vector2( 1125, 283 ) +states/sleeping/node = SubResource( 81 ) +states/sleeping/position = Vector2( 1078, 411.193 ) +states/stand-startled/node = SubResource( 84 ) +states/stand-startled/position = Vector2( 717, 411.193 ) +states/start_walking/node = SubResource( 115 ) +states/start_walking/position = Vector2( 522, 597.193 ) +states/stop_walking/node = SubResource( 116 ) +states/stop_walking/position = Vector2( 663, 697.193 ) +states/tun_left/node = SubResource( 125 ) +states/tun_left/position = Vector2( 868, 633.193 ) +states/turn_right/node = SubResource( 126 ) +states/turn_right/position = Vector2( 1059, 620.193 ) +states/use_tap/node = SubResource( 85 ) +states/use_tap/position = Vector2( 283, 143.193 ) +transitions = [ "locomotion", "passenger", SubResource( 86 ), "passenger", "locomotion", SubResource( 87 ), "passenger", "drive", SubResource( 88 ), "drive", "passenger", SubResource( 89 ), "drive", "locomotion", SubResource( 90 ), "locomotion", "drive", SubResource( 91 ), "sacrifice", "sacrificed", SubResource( 92 ), "sacrificed", "sacrifice", SubResource( 93 ), "locomotion", "kneel", SubResource( 94 ), "kneel", "pray", SubResource( 95 ), "pray", "locomotion", SubResource( 96 ), "pray", "pray-startled", SubResource( 97 ), "pray-startled", "pray-startled-walk", SubResource( 98 ), "sleeping", "locomotion", SubResource( 99 ), "pray-startled-walk", "stand-startled", SubResource( 100 ), "stand-startled", "locomotion", SubResource( 101 ), "locomotion", "grabbed", SubResource( 102 ), "grabbed", "locomotion", SubResource( 103 ), "locomotion", "climb1", SubResource( 104 ), "climb1", "locomotion", SubResource( 105 ), "locomotion", "climb1a", SubResource( 106 ), "climb1a", "locomotion", SubResource( 107 ), "use_tap", "locomotion", SubResource( 108 ), "locomotion", "use_tap", SubResource( 109 ), "locomotion", "start_walking", SubResource( 117 ), "start_walking", "locomotion", SubResource( 118 ), "locomotion", "stop_walking", SubResource( 119 ), "stop_walking", "locomotion", SubResource( 120 ), "locomotion", "tun_left", SubResource( 127 ), "tun_left", "locomotion", SubResource( 128 ), "locomotion", "turn_right", SubResource( 129 ), "turn_right", "locomotion", SubResource( 130 ) ] +start_node = "locomotion" +graph_offset = Vector2( -232, 15.1925 ) + +[sub_resource type="AnimationNodeBlendTree" id=111] +graph_offset = Vector2( 0, -221 ) +nodes/Animation/node = SubResource( 5 ) +nodes/Animation/position = Vector2( 540, 280 ) +"nodes/Animation 2/node" = SubResource( 4 ) +"nodes/Animation 2/position" = Vector2( 920, 280 ) +nodes/all_scale/node = SubResource( 6 ) +nodes/all_scale/position = Vector2( 840, -20 ) +nodes/blade_left/node = SubResource( 7 ) +nodes/blade_left/position = Vector2( 1040, 0 ) +nodes/blade_right/node = SubResource( 8 ) +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" ] + +[sub_resource type="AnimationNodeStateMachinePlayback" id=112] + +[node name="vroid1-female" instance=ExtResource( 1 )] + +[node name="Skeleton" parent="skeleton" index="0"] +bones/1/bound_children = [ NodePath("hips") ] +bones/25/bound_children = [ NodePath("chest") ] +bones/80/bound_children = [ NodePath("head") ] +bones/99/bound_children = [ NodePath("wrist_l") ] +bones/101/bound_children = [ NodePath("wrist_r") ] + +[node name="body" parent="skeleton/Skeleton" index="0"] +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.695045, 0.34614, -0.630227, -0.0867818, 0.910422, 0.404298, 0.713771, -0.226324, 0.66284, -0.0445963, 1.35245, -0.0152731 ) +bone_name = "Head" + +[node name="marker_talk" type="Spatial" parent="skeleton/Skeleton/head" index="0"] +transform = Transform( 0.938982, -0.1833, 0.290986, 0.0970959, 0.953036, 0.286975, -0.3299, -0.241222, 0.912684, -0.00304712, 0.094561, -0.232747 ) + +[node name="marker_hips_action" type="Spatial" parent="skeleton/Skeleton/head" index="1"] +transform = Transform( 0.845972, -0.248965, 0.471515, 0.270435, 0.962465, 0.0230151, -0.459582, 0.108024, 0.88155, 0.0862694, -0.150184, 0.25561 ) + +[node name="head_hurt" type="Area" parent="skeleton/Skeleton/head" index="2"] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0.02 ) + +[node name="CollisionShape" type="CollisionShape" parent="skeleton/Skeleton/head/head_hurt" index="0"] +shape = SubResource( 1 ) + +[node name="hair" type="Spatial" parent="skeleton/Skeleton/head" index="3"] +transform = Transform( 1, 0, 0, 0, 0.984808, -0.173648, 0, 0.173648, 0.984808, 0, 0, 0 ) + +[node name="female-hair1" parent="skeleton/Skeleton/head/hair" index="0" instance=ExtResource( 2 )] +transform = Transform( 1, -3.21306e-08, 5.58794e-08, 1.86265e-08, 1, 1.49012e-08, 3.35276e-08, -7.45058e-09, 1, 0, 0, 0 ) + +[node name="face" type="Spatial" parent="skeleton/Skeleton/head" index="4"] +transform = Transform( 1, -1.24197e-11, 0, 1.06852e-11, 1, -5.82077e-11, 0, 0, 1, -0.005, -0.002, 0.006 ) + +[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.932837, 0.0669982, 0.354143, 0.0474986, -0.99678, 0.0635026, 0.357293, -0.0424105, -0.933064, 0.000203875, 0.898321, -0.00645695 ) +bone_name = "Hips" + +[node name="marker_dagger_sacrifice" type="Spatial" parent="skeleton/Skeleton/hips" index="0"] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.2, 0.2 ) + +[node name="hips_hurt" type="Area" parent="skeleton/Skeleton/hips" index="1"] + +[node name="CollisionShape" type="CollisionShape" parent="skeleton/Skeleton/hips/hips_hurt" index="0"] +shape = SubResource( 2 ) + +[node name="wrist_r" type="BoneAttachment" parent="skeleton/Skeleton" index="4"] +transform = Transform( -0.287977, 0.919611, -0.267176, 0.942778, 0.321208, 0.0894101, 0.168042, -0.22614, -0.95949, 0.217922, 0.840792, 0.0647382 ) +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.0744099, -0.85538, 0.512627, -0.989629, 0.126679, 0.0677309, -0.122875, -0.50227, -0.855936, -0.175723, 0.838131, -0.0414757 ) +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.941419, -0.0483243, -0.333891, 0.0575738, 0.998111, 0.0178291, 0.332436, -0.0360186, 0.942465, -0.00328054, 1.05887, -0.018731 ) +bone_name = "Chest" + +[node name="chest_hurt" type="Area" parent="skeleton/Skeleton/chest" index="0"] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.05, 0 ) + +[node name="CollisionShape" type="CollisionShape" parent="skeleton/Skeleton/chest/chest_hurt" index="0"] +shape = SubResource( 3 ) + +[node name="MeshInstance" type="MeshInstance" parent="skeleton/Skeleton" index="7"] + +[node name="AnimationTree" type="AnimationTree" parent="." index="2"] +tree_root = SubResource( 111 ) +anim_player = NodePath("../AnimationPlayer") +active = true +root_motion_track = NodePath("skeleton/Skeleton:root") +parameters/all_scale/scale = 1.0 +parameters/blade_left/blend_amount = 0.0 +parameters/blade_right/blend_amount = 0.0 +parameters/state/playback = SubResource( 112 ) +parameters/state/climb1/TimeScale/scale = 2.0 +parameters/state/climb1a/TimeScale/scale = 2.0 +parameters/state/grabbed/TimeScale/scale = 1.0 +parameters/state/kneel/TimeScale/scale = 1.0 +parameters/state/locomotion/loc/blend_position = Vector2( -0.00127554, 0.00220752 ) +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 = 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 = 0 +parameters/state/locomotion/loc/2/TimeScale/scale = 1.0 +parameters/state/locomotion/loc/3/TimeScale/scale = 1.0 +parameters/state/locomotion/loc/4/TimeScale/scale = 3.5 +"parameters/state/locomotion/loc/4/TimeScale 2/scale" = 3.5 +parameters/state/locomotion/loc/4/Transition/current = 0 +parameters/state/locomotion/loc/5/TimeScale/scale = 1.5 +"parameters/state/locomotion/loc/5/TimeScale 2/scale" = 1.5 +parameters/state/locomotion/loc/5/Transition/current = 0 +parameters/state/pray/TimeScale/scale = 1.0 +parameters/state/pray-startled/TimeScale/scale = 1.8 +parameters/state/pray-startled-walk/TimeScale/scale = 1.3 +"parameters/state/pray-startled-walk/TimeScale 2/scale" = 1.6 +parameters/state/pray-startled-walk/Transition/current = 1 +parameters/state/sacrifice/TimeScale/scale = 1.0 +"parameters/state/sacrifice/TimeScale 2/scale" = 1.0 +parameters/state/sacrifice/attack1/active = false +parameters/state/sacrifice/attack2/active = false +parameters/state/sacrifice/speed/scale = 1.0 +parameters/state/sacrificed/TimeScale/scale = 1.0 +parameters/state/sleeping/TimeScale/scale = 1.0 +parameters/state/stand-startled/TimeScale/scale = 0.7 +parameters/state/start_walking/TimeScale/scale = 1.0 +parameters/state/stop_walking/TimeScale/scale = 1.0 +parameters/state/tun_left/TimeScale/scale = 1.0 +parameters/state/turn_right/TimeScale/scale = 1.0 +parameters/state/use_tap/TimeScale/scale = 1.0 diff --git a/characters/vroid1-man-animate.bin b/characters/vroid1-man-animate.bin new file mode 100644 index 0000000000000000000000000000000000000000..cef462bfc7bf42e0919ca03fde302d77228ba715 GIT binary patch literal 8618888 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