class_name MonsterSpawnpoint extends Node3D @onready var monster_tscn = preload("res://entities/monster/monster.tscn") # a spawnpoint that can spawn monsters # monsters are only spawned, if the player is not looking # list that holds all spawnable monsters @export var spawnable_monsters: Array[MonsterData] # ignore spawning only if visible @export var ignore_visibility: bool = false # the maximum amount of spawned monsters # no monsters will spawn, when this number is reached @export var max_monsters: int = 5 # the maximum lifetime a monster can be in the world # a monster is then deleted if the following conditions are met: # the monster has exceeded its maximum lifetime and it is not on screen # TODO: figure out how to check for the exceeded lifetime and delete @export var max_lifetime: float = 60.0 # seconds # only spawn a monster every x seconds @export var spawn_cooldown: float = 3.0 # seconds @onready var spawn_timer: Timer = Timer.new() @onready var time: float = 16.0 @onready var frequency: float = 1.0 @onready var amplitude: float = 0.5 @onready var spawn_point: Vector3 = Vector3(0, 0, 0) @onready var label: Label3D = $Label3D # a spawnpoint should keep track of spawned entities var active_monsters: Array[Monster] = [] # Called when the node enters the scene tree for the first time. func _ready() -> void: spawn_timer.wait_time = spawn_cooldown spawn_timer.autostart = true spawn_timer.timeout.connect(spawn) add_child(spawn_timer) spawn_timer.start() spawn_point = position func spawn() -> void: if len(active_monsters) >= max_monsters: print("Spawnpoint reached maximum amount of monsters") return if ignore_visibility == false and $VisibleOnScreenNotifier3D.is_on_screen(): print("Spawnpoint is visible on screen. Not spawning a monster.") return # TODO: Add a check to not spawn enemies X units near the player # instantiate a monster .tscn scene var monster_to_spawn = monster_tscn.instantiate() monster_to_spawn.stats = spawnable_monsters[0] # keep track of the current monster active_monsters.append(monster_to_spawn) label.text = "%s / %s" % [len(active_monsters), max_monsters] # calculate the position of the monster and add the offset of the spawnpoint itself var monster_position = Vector3(position.x, position.y + 1, position.z) monster_to_spawn.position = monster_position var debug_level_node = get_parent_node_3d() debug_level_node.add_child(monster_to_spawn) print("Spawning Mob \"%s\"" % monster_to_spawn.stats.display_name) # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta: float) -> void: time += delta var diamond_rotation: float = sin(time * frequency) * amplitude var diamond_height: float = sin(time * frequency) * amplitude $Diamond.rotation.y = diamond_rotation $Diamond.position.y = 2.0 + diamond_height