2025-04-23 11:56:29 +01:00
|
|
|
extends Building
|
2025-04-26 16:02:13 +01:00
|
|
|
|
|
|
|
@export var ammo_cap: int = 10
|
|
|
|
@export var fire_cooldown_time: float = 0.2
|
|
|
|
@export var reload_time: float = 1.0
|
|
|
|
@export var bullet_scene: PackedScene = preload("res://objects/bullet.tscn")
|
|
|
|
@export var fire_position: Vector3 = Vector3(0,1,0)
|
|
|
|
@export var shot_impulse: float = 100
|
|
|
|
@export var lead_shot_factor: float = 0.01
|
|
|
|
|
|
|
|
@onready var consumer: Consumer = $Consumer
|
|
|
|
enum LoadState {UNLOADED, RELOADING, LOADED}
|
|
|
|
|
|
|
|
@onready var ammo: int = 0
|
|
|
|
var loaded: LoadState = LoadState.UNLOADED
|
|
|
|
var cooldown_timer: float = 0.0
|
|
|
|
var reload_timer: float = 0.0
|
|
|
|
var current_target: Enemy = null
|
|
|
|
|
|
|
|
func _on_consumer_item_added(item: Item) -> void:
|
|
|
|
pass
|
|
|
|
|
|
|
|
func _process(delta: float) -> void:
|
|
|
|
if loaded == LoadState.UNLOADED:
|
|
|
|
if consumer.take_any_item_from_storage():
|
|
|
|
#Engine.time_scale = 1.0
|
|
|
|
loaded = LoadState.RELOADING
|
|
|
|
if loaded == LoadState.RELOADING:
|
|
|
|
reload_timer += delta
|
|
|
|
if reload_timer >= reload_time:
|
|
|
|
loaded = LoadState.LOADED
|
|
|
|
ammo = ammo_cap
|
|
|
|
reload_timer = 0.0
|
|
|
|
if loaded == LoadState.LOADED:
|
|
|
|
cooldown_timer += delta
|
|
|
|
if cooldown_timer >= fire_cooldown_time:
|
|
|
|
cooldown_timer -= fire_cooldown_time
|
|
|
|
if current_target == null:
|
|
|
|
search_for_enemy()
|
|
|
|
if current_target != null:
|
|
|
|
fire_at_target()
|
|
|
|
|
|
|
|
func check_target_status() -> void:
|
|
|
|
if current_target.is_queued_for_deletion():
|
|
|
|
current_target = null
|
|
|
|
|
|
|
|
func search_for_enemy() -> void:
|
|
|
|
var enemies: Array[Node] = get_tree().get_nodes_in_group("Enemies")
|
|
|
|
var closest: float = 9999999999
|
|
|
|
for enemy in enemies:
|
|
|
|
if enemy is Enemy:
|
|
|
|
if !enemy.sighted:
|
|
|
|
continue
|
|
|
|
var distance_sqr = global_position.distance_squared_to(enemy.global_position)
|
|
|
|
if distance_sqr <= closest:
|
|
|
|
var params: PhysicsRayQueryParameters3D = PhysicsRayQueryParameters3D.new()
|
|
|
|
params.collision_mask = 0b00101
|
|
|
|
params.from = to_global(fire_position)
|
|
|
|
params.to = enemy.global_position
|
|
|
|
var result: Dictionary = get_world_3d().direct_space_state.intersect_ray(params)
|
|
|
|
#DebugDraw3D.draw_line_hit(params.from, params.to, result["position"] if result.has("position") else Vector3(), result.has("position"), 0.25, Color.YELLOW, Color.BLACK, 1.0)
|
|
|
|
if result.has("collider"):
|
|
|
|
if !result["collider"] is PhysicsBody3D:
|
|
|
|
continue
|
|
|
|
var body: PhysicsBody3D = result["collider"]
|
|
|
|
if body is Enemy:
|
|
|
|
current_target = body
|
|
|
|
closest = body.global_position.distance_squared_to(global_position)
|
|
|
|
|
|
|
|
func fire_at_target() -> void:
|
|
|
|
#Engine.time_scale = 0.1
|
|
|
|
var bullet: RigidBody3D = bullet_scene.instantiate()
|
|
|
|
add_child(bullet)
|
|
|
|
bullet.global_position = to_global(fire_position)
|
|
|
|
|
|
|
|
var aim_target: Vector3 = current_target.global_position
|
|
|
|
var range: float = global_position.distance_to(current_target.global_position)
|
|
|
|
aim_target += current_target.linear_velocity * lead_shot_factor * range
|
|
|
|
DebugDraw3D.draw_sphere(aim_target, 0.25, Color.RED, 0.1)
|
|
|
|
|
|
|
|
bullet.look_at(aim_target)
|
|
|
|
bullet.apply_impulse((aim_target - bullet.global_position).normalized()*shot_impulse)
|
2025-04-27 14:38:35 +01:00
|
|
|
bullet.angular_velocity = (bullet.global_basis * Vector3(0,0,-10))
|
2025-04-26 16:02:13 +01:00
|
|
|
current_target = null
|
|
|
|
ammo -= 1
|
|
|
|
if ammo <= 0:
|
|
|
|
loaded = LoadState.UNLOADED
|