432 lines
13 KiB
GDScript
432 lines
13 KiB
GDScript
extends Node
|
|
|
|
signal character_ready
|
|
|
|
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
|
|
|
|
var side_wall: PackedScene = preload("res://objects/wall-side.scn")
|
|
var bottom_side: PackedScene = preload("res://objects/bottom-side.scn")
|
|
var bottom: PackedScene = preload("res://objects/bottom.scn")
|
|
var bottom_wheels: PackedScene = preload("res://objects/bottom-wheels.scn")
|
|
var entry: PackedScene = preload("res://objects/entry.scn")
|
|
var roof_floor: PackedScene = preload("res://objects/roof-floor.scn")
|
|
var roof_floor_range: PackedScene = preload("res://objects/roof-floor-range.scn")
|
|
var wall_internal: PackedScene = preload("res://objects/wall-internal.scn")
|
|
var window_narrow: PackedScene = preload("res://objects/window-narrow.scn")
|
|
var window_wide: PackedScene = preload("res://objects/window-wide.scn")
|
|
var wall_solid: PackedScene = preload("res://objects/wall-solid.scn")
|
|
|
|
var courtyard_tile: PackedScene = preload("res://objects/courtyard-tile.scn")
|
|
var foundation_tile: PackedScene = preload("res://objects/foundation.scn")
|
|
var room_tile: PackedScene = preload("res://objects/block-room-corridoor.scn")
|
|
var tower_walls_tile: PackedScene = preload("res://objects/tower-walls.scn")
|
|
var tower_floor_tile: PackedScene = preload("res://objects/tower_floor.scn")
|
|
var stairs_tile: PackedScene = preload("res://objects/stairs.scn")
|
|
var gate_bottom_tile: PackedScene = preload("res://objects/gate_bottom.scn")
|
|
var gate_top_tile: PackedScene = preload("res://objects/gate-top.scn")
|
|
var entry_tile: PackedScene = preload("res://objects/block-room-entry.scn")
|
|
var roof_tile: PackedScene = preload("res://objects/roof.scn")
|
|
var tower_roof_tile: PackedScene = preload("res://objects/tower-roof.scn")
|
|
var courtroom: PackedScene = preload("res://objects/courtroom.tscn")
|
|
var bandit_camp: PackedScene = preload("res://bandit_camp.tscn")
|
|
var hostile_dwelling: PackedScene = preload("res://hostile_dwelling.tscn")
|
|
|
|
onready var palace_map_data = {
|
|
"courtyard_tile": courtyard_tile,
|
|
"foundation_tile": foundation_tile,
|
|
"room_tile": room_tile,
|
|
"tower_walls_tile": tower_walls_tile,
|
|
"tower_floor_tile": tower_floor_tile,
|
|
"stairs_tile": stairs_tile,
|
|
"gate_bottom_tile": gate_bottom_tile,
|
|
"gate_top_tile": gate_top_tile,
|
|
"entry_tile": entry_tile,
|
|
"roof_tile": roof_tile,
|
|
"tower_roof_tile": tower_roof_tile,
|
|
"courtroom": courtroom,
|
|
}
|
|
|
|
onready var buildings = {
|
|
"trailer_house": preload("res://buildings/trailer-house.gd").new(),
|
|
}
|
|
|
|
func spawn_building(bname: String, xform: Transform) -> void:
|
|
if !buildings.has(bname):
|
|
return
|
|
var objects = buildings[bname].build_house(xform)
|
|
spawn_house_objects(xform, objects)
|
|
|
|
|
|
var traffic_rnd: RandomNumberGenerator
|
|
var traffic_astar: AStar
|
|
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 = RoadsData.get_site_border(site, 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
|
|
var infl = RoadsData.get_influence_cached(center.x, center.y, 256)
|
|
center.y = infl.y
|
|
var radial_points = RoadsData.get_site_radial_points(site, 32.0, 64.0)
|
|
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 miff = RoadsData.get_influence_cached(ep.x, ep.z, 256.0)
|
|
ep.y = center.y
|
|
var d = (center - ep).normalized()
|
|
assert(d.length_squared() > 0)
|
|
var dst = ep.distance_to(center)
|
|
print(dst)
|
|
if dst < 64.0 + 12 + 8 + 4:
|
|
continue
|
|
var step = 32.0
|
|
var pstart = ep + d * 32.0
|
|
dst -= 32.0
|
|
while dst > 0.0:
|
|
var ok = true
|
|
miff = RoadsData.get_influence_cached(pstart.x, pstart.z, 256.0)
|
|
if miff.x > 0.0:
|
|
ok = false
|
|
if ok:
|
|
pstart.y = miff.y
|
|
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)
|
|
spawn_building("trailer_house", xform)
|
|
var aabb = AABB(pstart, Vector3())
|
|
aabb = aabb.grow(32)
|
|
aabbs.push_back(aabb)
|
|
print("placed to: ", pstart)
|
|
pstart = pstart + d * step
|
|
dst -= step
|
|
towns += 1
|
|
|
|
func setup_first_town(site):
|
|
assert(!done)
|
|
var poly = RoadsData.get_site_polygon_3d(site)
|
|
var height = RoadsData.get_site_avg_height(site)
|
|
var border = RoadsData.get_site_border(site, 32)
|
|
var border1a = RoadsData.get_site_border(site, 42)
|
|
var border2 = RoadsData.get_site_border(site, 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
|
|
var infl = RoadsData.get_influence_cached(center.x, center.z, 256)
|
|
center.y = infl.y
|
|
print("first town center: ", center)
|
|
var radial_points = RoadsData.get_site_radial_points(site, 32.0, 64.0)
|
|
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 miff = RoadsData.get_influence_cached(ep.x, ep.z, 256.0)
|
|
ep.y = center.y
|
|
var d = (center - ep).normalized()
|
|
assert(d.length_squared() > 0)
|
|
var dst = ep.distance_to(center)
|
|
print(dst)
|
|
if dst < 64.0 + 12 + 8 + 4:
|
|
continue
|
|
var step = 32.0
|
|
var pstart = ep + d * 32.0
|
|
dst -= 32.0
|
|
while dst > 0.0:
|
|
var ok = true
|
|
miff = RoadsData.get_influence_cached(pstart.x, pstart.z, 256.0)
|
|
if miff.x > 0.0:
|
|
ok = false
|
|
if ok:
|
|
pstart.y = miff.y
|
|
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)
|
|
spawn_building("trailer_house", xform)
|
|
var aabb = AABB(pstart, Vector3())
|
|
aabb = aabb.grow(32)
|
|
aabbs.push_back(aabb)
|
|
print("placed to: ", pstart)
|
|
pstart = pstart + d * step
|
|
dst -= step
|
|
towns += 1
|
|
done = true
|
|
|
|
func setup_traffic(site):
|
|
var poly = RoadsData.get_site_polygon_3d(site)
|
|
var lp = get_tree().root
|
|
for p in range(poly.size()):
|
|
var p1 = poly[p]
|
|
var p2 = poly[(p + 1) % poly.size()]
|
|
var n = (p2 - p1).cross(Vector3.UP).normalized()
|
|
var t = (p2 - p1).normalized()
|
|
var l = p1.distance_to(p2)
|
|
assert(l > 0)
|
|
assert(t.length_squared() > 0)
|
|
var xpos = p1 + t * 8.0
|
|
var xe = 128.0
|
|
if l < xe + 16.0:
|
|
xpos = p1.linear_interpolate(p2, 0.5)
|
|
var x = xpos
|
|
var xform = Transform(Basis(), x).looking_at(x - t * 3.0, Vector3.UP)
|
|
var c = Spatial.new()
|
|
lp.add_child(c)
|
|
c.transform = xform
|
|
c.add_to_group("spawn")
|
|
c.add_to_group("keep")
|
|
c.add_to_group("traffic_spawn")
|
|
else:
|
|
while l > xe + 16.0:
|
|
var x = xpos
|
|
var xform = Transform(Basis(), x).looking_at(x - t * 3.0, Vector3.UP)
|
|
var c = Spatial.new()
|
|
lp.add_child(c)
|
|
c.transform = xform
|
|
c.add_to_group("spawn")
|
|
c.add_to_group("keep")
|
|
c.add_to_group("traffic_spawn")
|
|
xpos += t * xe
|
|
l -= xe
|
|
func _ready():
|
|
traffic_rnd = RandomNumberGenerator.new()
|
|
traffic_rnd.randomize()
|
|
traffic_astar = AStar.new()
|
|
for k in obj_names.keys():
|
|
Spawner.add_scene(k, obj_names[k])
|
|
for k in palace_map_data.keys():
|
|
Spawner.add_scene(k, palace_map_data[k])
|
|
var parts = {
|
|
"side_wall": side_wall,
|
|
"bottom_side": bottom_side,
|
|
"bottom": bottom,
|
|
"bottom_wheels": bottom_wheels,
|
|
"entry": entry,
|
|
"roof_floor": roof_floor,
|
|
"roof_floor_range": roof_floor_range,
|
|
"wall_internal": wall_internal,
|
|
"window_narrow": window_narrow,
|
|
"window_wide": window_wide,
|
|
"wall_solid": wall_solid
|
|
}
|
|
for k in parts.keys():
|
|
Spawner.add_scene(k, parts[k])
|
|
# Traffic.set_min_spawn_distance(50.0)
|
|
# Traffic.set_deny_physics()
|
|
# Traffic.set_physics_distance(Vector3(30, -10, 40))
|
|
# Traffic.set_debug(true)
|
|
Traffic.set_spawn_cooldown(10, 15)
|
|
Traffic.set_default_speed(8.5)
|
|
Traffic.add_traffic_vehicle(car)
|
|
var water_mat = load("res://water/Water.material")
|
|
Water.set_material(water_mat)
|
|
connect("character_ready", self, "char_ready")
|
|
|
|
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, 200)
|
|
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
|
|
# building parts
|
|
# call_deferred("real_spawn_child")
|
|
|
|
func stream_obj(obj: String, xform: Transform):
|
|
Spawner.place_scene(obj, xform)
|
|
var can_spawn = false
|
|
func char_ready():
|
|
can_spawn = true
|
|
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
|
|
if can_spawn:
|
|
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
|
|
ok = true
|
|
if ok || n.is_in_group("keep"):
|
|
var base = ["cmdq", "marker", "hurtboxes"]
|
|
var g = ""
|
|
if n.is_in_group("male"):
|
|
g = "male"
|
|
elif n.is_in_group("female"):
|
|
g = "female"
|
|
if n.is_in_group("mystress"):
|
|
base.push_back("mystress")
|
|
if n.is_in_group("student"):
|
|
base.push_back("student")
|
|
elif n.is_in_group("bandit"):
|
|
base.push_back("bandit")
|
|
if g.length() > 0:
|
|
print(g, " ", base)
|
|
CharacterSystemWorld.create_character_in_pool(g, base, n.global_transform)
|
|
n.queue_free()
|
|
elif n.is_in_group("car"):
|
|
var p1 = cam.global_transform.origin
|
|
var p2 = n.global_transform.origin
|
|
if p1.distance_squared_to(p2) < 5000.0:
|
|
var c = car.instance()
|
|
c.add_to_group("saved_vehicle")
|
|
var p = get_tree().root
|
|
p.add_child(c)
|
|
c.global_transform = n.global_transform
|
|
n.queue_free()
|
|
|
|
# buildings
|
|
|
|
#var spawn = []
|
|
onready var spawn_lock: Mutex = Mutex.new()
|
|
|
|
func spawn_child(n: String, xform: Transform) -> void:
|
|
spawn_lock.lock()
|
|
Spawner.queue_place_scene(n, xform)
|
|
spawn_lock.unlock()
|
|
|
|
func update_node_position(n):
|
|
var space_state = get_viewport().get_world().direct_space_state
|
|
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"):
|
|
return
|
|
else:
|
|
n.global_transform.origin = result.position
|
|
|
|
func spawn_house_objects(place: Transform, objects) -> void:
|
|
for obj in objects:
|
|
var x = obj.xform
|
|
for w in obj.data:
|
|
if w.ends_with("_rotated"):
|
|
x.basis = x.basis.rotated(Vector3(0, 1, 0), PI)
|
|
var n = w.replace("_rotated", "")
|
|
spawn_child(n, place * x)
|
|
else:
|
|
spawn_child(w, place * x)
|
|
|
|
static func get_place_rnd(xform: Transform):
|
|
var rnd = RandomNumberGenerator.new()
|
|
var s = int(xform.origin.x + 100 * xform.origin.z * 2) % 0x1ffffff
|
|
rnd.seed = s
|
|
return rnd
|
|
|
|
func setup_bandit_camp(site):
|
|
var poly = RoadsData.get_site_polygon_3d(site)
|
|
var height = RoadsData.get_site_avg_height(site)
|
|
var center = Vector3()
|
|
for p in poly:
|
|
center += p
|
|
center /= poly.size()
|
|
center.y = height
|
|
var xform = Transform(Basis(), center)
|
|
var camp = bandit_camp.instance()
|
|
get_tree().root.add_child(camp)
|
|
camp.global_transform = xform
|
|
return camp
|
|
func setup_bandit_camp_outskirts(site):
|
|
var b = RoadsData.get_site_border(site, 96.0)
|
|
for e in range(min(4, b.size())):
|
|
if scenario.camp_dwellings.has(e):
|
|
if scenario.camp_dwellings[e].health <= 0:
|
|
continue
|
|
var h_xform = Transform(Basis(), b[e])
|
|
var dwg = hostile_dwelling.instance()
|
|
get_tree().root.add_child(dwg)
|
|
dwg.global_transform = h_xform
|
|
if !scenario.camp_dwellings.has(e):
|
|
scenario.camp_dwellings[e] = {}
|
|
scenario.camp_dwellings[e].health = 100.0
|