This commit is contained in:
Segey Lapin
2021-10-26 21:51:45 +03:00
commit d6c8a24f5a
58 changed files with 271059 additions and 0 deletions

604
autoload/characters.gd Normal file
View File

@@ -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)

192
autoload/controls.gd Normal file
View File

@@ -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)

72
autoload/doors.gd Normal file
View File

@@ -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)

131
autoload/freezer.gd Normal file
View File

@@ -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

89
autoload/inventory.gd Normal file
View File

@@ -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)

52
autoload/map.gd Normal file
View File

@@ -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")

16
autoload/map.tscn Normal file
View File

@@ -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 )

213
autoload/marker.gd Normal file
View File

@@ -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)

17
autoload/scenario.gd Normal file
View File

@@ -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

296
autoload/streaming.gd Normal file
View File

@@ -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()

12
autoload/streaming.tscn Normal file
View File

@@ -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 )