84 lines
2 KiB
GDScript
84 lines
2 KiB
GDScript
extends Node3D
|
|
|
|
var boxes: Array[CSGBox3D]
|
|
var points: Array[Vector3]
|
|
|
|
const MAX_CACHED_POINTS := 100
|
|
var doomed_point_idx := 0
|
|
|
|
@export var enemy_scenes: Array[EnemyEntry]
|
|
var weights: Array[float]
|
|
var total_cost := 0.
|
|
var money := 5.
|
|
|
|
var rng := RandomNumberGenerator.new()
|
|
|
|
func _get_point() -> Vector3:
|
|
assert(not boxes.is_empty())
|
|
|
|
var box: CSGBox3D = boxes.pick_random()
|
|
var x_stride := box.size.x / 2
|
|
var y_stride := box.size.y / 2
|
|
|
|
var ret := box.global_position
|
|
ret.x += randf_range(-x_stride, x_stride)
|
|
ret.y += randf_range(-y_stride, y_stride)
|
|
|
|
return ret
|
|
|
|
func _ready() -> void:
|
|
for child in get_children():
|
|
if child is CSGBox3D:
|
|
boxes.push_back(child)
|
|
|
|
for entry in enemy_scenes:
|
|
total_cost += entry.cost
|
|
|
|
for entry in enemy_scenes:
|
|
weights.push_back(total_cost - entry.cost + 1.)
|
|
func _process(_delta: float) -> void:
|
|
var v := _get_point()
|
|
v.y = 50.
|
|
|
|
var col_mask := 16 # floor collision layer
|
|
var params := PhysicsRayQueryParameters3D.create(
|
|
v, v + Vector3.DOWN * 100., 1 # detect any level geometry
|
|
)
|
|
var raycast := get_world_3d().direct_space_state.intersect_ray(params)
|
|
|
|
# if the raycast hit and the hit was the floor...
|
|
if not raycast.is_empty() and raycast.collider.collision_layer & col_mask:
|
|
var hitpos: Vector3 = raycast.position
|
|
|
|
if points.size() < MAX_CACHED_POINTS:
|
|
points.push_back(hitpos)
|
|
else:
|
|
points[doomed_point_idx] = hitpos
|
|
doomed_point_idx += 1
|
|
doomed_point_idx = doomed_point_idx % MAX_CACHED_POINTS
|
|
|
|
func _on_timer_timeout() -> void:
|
|
if not Level.is_active(): return
|
|
|
|
money += 2.
|
|
if randf() > .1: return
|
|
|
|
if points.is_empty():
|
|
push_warning("tried to spawn enemy, but can't find a point!")
|
|
return
|
|
|
|
while money > 3.:
|
|
var entry: EnemyEntry = enemy_scenes.pick_random()
|
|
if entry.cost > money:
|
|
return
|
|
var scene := entry.scene
|
|
|
|
var pos: Vector3 = points.pick_random()
|
|
pos += Vector3.UP * 0.02
|
|
var car: Node3D = scene.instantiate()
|
|
car.position = pos
|
|
get_tree().current_scene.add_child(car)
|
|
|
|
money -= entry.cost
|
|
|
|
|