TowerDefense/Towers/TowerManager.gd

180 lines
5.2 KiB
GDScript

extends Node3D
class_name TowerManager
@onready var cam : Camera3D = $"../Camera3D"
@onready var selection_icon : Sprite3D = $Sprite3DSelection
var usedLocations : Dictionary
var selectedTile : Vector3
var selected_tower : Tower
var buildedTower : int = 0
var is_on_gui : bool = false
func _ready() -> void:
EventBus.tower_selected.connect(onTowerSelect)
#$AnimationPlayer.play("arrow_bobbing")
EventBus.mouse_entered_gui.connect(onMouseEnteredGui)
EventBus.mouse_exited_gui.connect(onMouseExitedGui)
Game.allowed_tower_has_change.connect(connectTowerSignals)
func _process(_delta: float) -> void:
var collider : CollisionObject3D = handle_player_controls()
var tower : Tower
if collider is GameTile:
tower = usedLocations.get(collider.global_position.round())
if Input.is_action_just_pressed("build"):
if not collider is GameTile || tower == selected_tower:
return
if isTileFree(collider):
placeTower()
elif tower:
selectTower(tower.type)
if Input.is_action_just_pressed("rest"):
if tower:
moveTower(tower, Vector3.INF)
else:
EventBus.tower_selected.emit(Tower.TYPE.NONE)
if Input.is_action_just_pressed("test"):
if tower:
tower.disable(3)
func _input(event: InputEvent) -> void:
if event is InputEventKey:
handleTowerShortCuts(event)
func handle_player_controls() -> Node3D:
#If the player has the mouse on the GUI, player can't place tower
if is_on_gui:
return
var space_state : PhysicsDirectSpaceState3D = get_world_3d().direct_space_state
var mouse_pos : Vector2 = get_viewport().get_mouse_position()
var origin : Vector3 = cam.project_ray_origin(mouse_pos)
var end : Vector3 = origin + cam.project_ray_normal(mouse_pos) * 100
var ray : PhysicsRayQueryParameters3D = PhysicsRayQueryParameters3D.create(origin, end)
ray.collide_with_bodies = true
var ray_result : Dictionary = space_state.intersect_ray(ray)
if ray_result.is_empty():
visible = false
return null
var collider : Node3D = ray_result.get("collider")
visible = true
selection_icon.visible = true
global_position = collider.global_position + Vector3(0.0, 0.21, 0.0)
if selected_tower && selected_tower.state == Tower.STATE.BLUEPRINT:
selected_tower.sprite.modulate = "ff4545c8" # If the tower can't be placed he is red
selection_icon.visible = false # If we are placing a tower, hide the selector model
if collider is GameTile && isTileFree(collider):
selected_tower.sprite.modulate = "61ff45c8" # If the tower can be placed he is green
return collider
func placeTower() -> void:
if not selected_tower:
return
if selected_tower.state == Tower.STATE.BLUEPRINT:
if not selected_tower.build():
return
buildedTower += 1
EventBus.tower_count_changed.emit(buildedTower)
remove_child(selected_tower)
$"../Towers".add_child(selected_tower)
moveTower(selected_tower, global_position)
func isTileFree(tile: GameTile) -> bool:
return not usedLocations.has(tile.global_position.round()) \
&& tile.type == GameTile.TYPE.TOWER
## Set [param toPosition] with [Vector3.INF] to make the tower rest
func moveTower(tower: Tower, toPosition: Vector3) -> void:
usedLocations.erase(tower.global_position.round())
if toPosition == Vector3.INF:
tower.changeState(Tower.STATE.REST)
else:
usedLocations.set(toPosition.round(), tower)
tower.global_position = toPosition
tower.changeState(Tower.STATE.ACTION)
var inAction : int = usedLocations.size()
EventBus.team_in_action_changed.emit(inAction)
EventBus.team_in_rest_changed.emit(buildedTower - inAction)
func onTowerSelect(towerType: Tower.TYPE):
# Hide current not builded tower
if selected_tower && selected_tower.state == Tower.STATE.BLUEPRINT:
selected_tower.visible = false
if selected_tower && selected_tower.type == towerType || towerType == Tower.TYPE.NONE:
if selected_tower && selected_tower.state == Tower.STATE.BLUEPRINT:
remove_child(selected_tower)
selected_tower = null
else:
selected_tower = Game.towers.get(towerType)
if selected_tower.state == Tower.STATE.BLUEPRINT:
selected_tower.visible = true
add_child(selected_tower)
func selectTower(towerType: Tower.TYPE, force : bool = false) -> void:
if towerType && (force || not selected_tower || selected_tower.state):
EventBus.tower_selected.emit(towerType)
func handleTowerShortCuts(event: InputEventKey) -> void:
if event.pressed:
return
var towerType : Tower.TYPE = Tower.TYPE.NONE
match event.physical_keycode:
KEY_Q: towerType = Tower.TYPE.PIERRE
KEY_W: towerType = Tower.TYPE.ALINE
KEY_E: towerType = Tower.TYPE.MAXENCE
KEY_R: towerType = Tower.TYPE.VICTORIA
KEY_A: towerType = Tower.TYPE.EVAN
KEY_S: towerType = Tower.TYPE.ALEX
KEY_D: towerType = Tower.TYPE.GERALDINE
#KEY_F: towerType = Tower.TYPE
if Game.towers.has(towerType):
selectTower(towerType, true)
func onMouseEnteredGui() -> void:
is_on_gui = true
func onMouseExitedGui() -> void:
is_on_gui = false
func connectTowerSignals() -> void:
for tower : Tower in Game.towers.values():
tower.state_changed.connect(onTowerStateChange.bind(tower))
func onTowerStateChange(tower : Tower) -> void:
if tower.state == Tower.STATE.DISABLED && tower == selected_tower:
EventBus.tower_selected.emit(Tower.TYPE.NONE)
moveTower(tower, Vector3.INF)