diff --git a/Towers/Scenes/pierre.tscn b/Towers/Scenes/pierre.tscn index e471c21..88961e7 100644 --- a/Towers/Scenes/pierre.tscn +++ b/Towers/Scenes/pierre.tscn @@ -85,6 +85,7 @@ viewport_path = NodePath("EnergyBar3D/SubViewport") tower_name = "Pierre" type = 1 icone = ExtResource("2_lcjqw") +price = 100 projectileRessource = SubResource("Resource_r52mr") towerRange = SubResource("SphereShape3D_c55ds") action_cooldown = 1.0 diff --git a/Towers/Tower.gd b/Towers/Tower.gd index 5c5d7f2..aa40414 100644 --- a/Towers/Tower.gd +++ b/Towers/Tower.gd @@ -3,6 +3,10 @@ extends StaticBody3D class_name Tower +enum STATE { BLUEPRINT, REST, ACTION, EXHAUSTED, DISABLED } + + +signal state_changed signal energy_changed signal changed @@ -17,26 +21,25 @@ var projectileScene : PackedScene = preload("res://Towers/Projectiles/projectile @export_group("Base data") @export var icone : Texture2D @export var bio : String -@export var price : int = 100 +@export var price : int @export_group("Attack") @export var projectileRessource : ProjectileResource @export var towerRange : Shape3D -@export var action_cooldown : float = 1.5: +@export var action_cooldown : float = 0.3 : set(value): action_cooldown = clamp(value, 0.3, 999) @export_group("Energy") -@export var max_energy : float = 100.0 : +@export var max_energy : float : set(value): - var diff : int = value - max_energy + var diff : float = value - max_energy max_energy = value if not Engine.is_editor_hint() && is_node_ready(): energy += diff energyBar.max_value = max_energy - changed.emit() -@export var energy_regen : float = 10.0 -@export var energy_cost : float = 50.0 +@export var energy_regen : float +@export var energy_cost : float @export_group("Button") @export var buttonTooltip : String @@ -47,18 +50,22 @@ var projectileScene : PackedScene = preload("res://Towers/Projectiles/projectile @onready var energyRecoveryCooldown : Timer = $EnergyRecoveryCooldown +var state : STATE = STATE.BLUEPRINT : + set(value): + state = value + state_changed.emit() var energy : float : set(value): - energyBar.value = value - energy = clampf(value, 0.0, max_energy) - is_exhausted = energy < energy_cost + energy = clampf(value, 0, max_energy) + energyBar.value = energy energy_changed.emit() + if not energy: + state = STATE.EXHAUSTED var availableTargets : Array[Enemy] -var is_exhausted : bool = false -var is_rest : bool : - get(): return not energyRecoveryCooldown.is_stopped() -var builded : bool = false +var selectable : bool : + get(): + return state != STATE.DISABLED && (state != STATE.BLUEPRINT || Game.money >= price) @export_category("Upgrades") @@ -68,9 +75,9 @@ var builded : bool = false func _ready() -> void: - energy = max_energy # WARNING : Prevent .tscn file to be modified by the load of the scene in editor if not Engine.is_editor_hint(): + energy = max_energy energyRecoveryCooldown.timeout.connect(func(): energy += energy_regen + Game.energy_boost) collision_layer = 0 collision_mask = 0 @@ -79,10 +86,24 @@ func _ready() -> void: func _process(_delta: float) -> void: - if visible && $AttackCooldown.is_stopped() && builded: + if state == STATE.ACTION && $AttackCooldown.is_stopped(): shoot() +func changeState(newState : STATE) -> void: + if [STATE.BLUEPRINT, STATE.DISABLED].has(state): + return + + match newState: + STATE.ACTION when state == STATE.REST: in_action() + STATE.ACTION when not energy: newState = STATE.EXHAUSTED + STATE.ACTION: pass + STATE.REST: resting() + _: return # NOTE Prevent changing of state + + state = newState + + func shoot() -> void: var target : Enemy = choose_target() if not target: @@ -99,20 +120,16 @@ func resting() -> void: visible = false collision_layer = 0 collision_mask = 0 - - if builded: - toggleConnection(false) - energyRecoveryCooldown.start() + toggleConnection(false) + energyRecoveryCooldown.start() func in_action() -> void: visible = true - - if builded: - toggleConnection(true) - collision_layer = 0b100 - collision_mask = 0b100 - energyRecoveryCooldown.stop() + collision_layer = 0b100 + collision_mask = 0b100 + toggleConnection(true) + energyRecoveryCooldown.stop() func choose_target() -> Enemy: @@ -125,13 +142,14 @@ func choose_target() -> Enemy: func build() -> bool: - if builded || not Game.spendMoney(price): + if state != STATE.BLUEPRINT || not Game.spendMoney(price): return false sprite.modulate = "ffffffff" $EnergyBar3D.visible = true - builded = true $PriceTag.visible = false + state = STATE.ACTION + in_action() changed.emit() return true @@ -155,3 +173,10 @@ func toggleConnection(activate : bool) -> void: $Range.body_entered.disconnect(onBodyEntered) $Range.body_exited.disconnect(onBodyExited) availableTargets.clear() + + +func disable(duration : float) -> void: + state = STATE.DISABLED + resting() + await get_tree().create_timer(duration).timeout + state = STATE.REST diff --git a/Towers/TowerManager.gd b/Towers/TowerManager.gd index 3f32608..a060cb4 100644 --- a/Towers/TowerManager.gd +++ b/Towers/TowerManager.gd @@ -18,6 +18,7 @@ func _ready() -> void: #$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: @@ -42,6 +43,10 @@ func _process(_delta: float) -> void: 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: @@ -71,7 +76,7 @@ func handle_player_controls() -> Node3D: selection_icon.visible = true global_position = collider.global_position + Vector3(0.0, 0.21, 0.0) - if selected_tower && not selected_tower.builded: + 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): @@ -84,7 +89,7 @@ func placeTower() -> void: if not selected_tower: return - if not selected_tower.builded: + if selected_tower.state == Tower.STATE.BLUEPRINT: if not selected_tower.build(): return buildedTower += 1 @@ -105,11 +110,11 @@ func moveTower(tower: Tower, toPosition: Vector3) -> void: usedLocations.erase(tower.global_position.round()) if toPosition == Vector3.INF: - tower.resting() + tower.changeState(Tower.STATE.REST) else: usedLocations.set(toPosition.round(), tower) tower.global_position = toPosition - tower.in_action() + tower.changeState(Tower.STATE.ACTION) var inAction : int = usedLocations.size() EventBus.team_in_action_changed.emit(inAction) @@ -118,22 +123,22 @@ func moveTower(tower: Tower, toPosition: Vector3) -> void: func onTowerSelect(towerType: Tower.TYPE): # Hide current not builded tower - if selected_tower && not selected_tower.builded: + 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 && not selected_tower.builded: + if selected_tower && selected_tower.state == Tower.STATE.BLUEPRINT: remove_child(selected_tower) selected_tower = null else: selected_tower = Game.towers.get(towerType) - if not selected_tower.builded: + 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.builded): + if towerType && (force || not selected_tower || selected_tower.state): EventBus.tower_selected.emit(towerType) @@ -162,3 +167,14 @@ func onMouseEnteredGui() -> void: 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) diff --git a/Towers/tower.tscn b/Towers/tower.tscn index 2e42eb5..9619c8d 100644 --- a/Towers/tower.tscn +++ b/Towers/tower.tscn @@ -86,7 +86,3 @@ metadata/_custom_type_script = "uid://blnmjxmusrsa7" [node name="PriceTag" type="Label3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) billboard = 2 - -[connection signal="body_entered" from="Range" to="." method="_on_range_body_entered"] -[connection signal="body_exited" from="Range" to="." method="_on_range_body_exited"] -[connection signal="timeout" from="AttackCooldown" to="." method="_on_cooldown_timeout"] diff --git a/UI/InfoPanel.gd b/UI/InfoPanel.gd index 4a046ee..ccd8ded 100644 --- a/UI/InfoPanel.gd +++ b/UI/InfoPanel.gd @@ -12,7 +12,7 @@ func _ready() -> void: func onCubeSelected() -> void: visible = true - $PanelContainer2.visible = false + $InfoContainer.visible = false createTowerUpgradeButtons(Game.upgrades) @@ -26,7 +26,7 @@ func onTowerSelected(towerType : Tower.TYPE) -> void: visible = false return - $PanelContainer2.visible = true + $InfoContainer.visible = true tower = Game.towers.get(towerType) tower.energy_changed.connect(onEnergyChange) tower.changed.connect(onTowerChange) @@ -48,12 +48,11 @@ func onTowerChange() -> void: # TODO Check for better UI to display it #%TowerBio.text = tower.bio - if tower.builded && not %UpgradeContainer.visible: - createTowerUpgradeButtons(tower.upgrades) + createTowerUpgradeButtons(tower.upgrades) func createTowerUpgradeButtons(upgrades : Array) -> void: - if tower && not tower.builded: + if tower && tower.state == Tower.STATE.BLUEPRINT: %UpgradeContainer.visible = false return diff --git a/UI/gui.tscn b/UI/gui.tscn index c1d4edc..e141402 100644 --- a/UI/gui.tscn +++ b/UI/gui.tscn @@ -185,30 +185,30 @@ grow_vertical = 0 theme_override_constants/separation = 0 script = ExtResource("9_3lugd") -[node name="PanelContainer2" type="PanelContainer" parent="InfoPanel"] +[node name="InfoContainer" type="PanelContainer" parent="InfoPanel"] custom_minimum_size = Vector2(200, 0) layout_mode = 2 mouse_filter = 1 theme_override_styles/panel = SubResource("StyleBoxFlat_h4fn5") -[node name="MarginContainer" type="MarginContainer" parent="InfoPanel/PanelContainer2"] +[node name="MarginContainer" type="MarginContainer" parent="InfoPanel/InfoContainer"] layout_mode = 2 theme_override_constants/margin_left = 10 theme_override_constants/margin_top = 10 theme_override_constants/margin_right = 10 theme_override_constants/margin_bottom = 10 -[node name="VBoxContainer" type="VBoxContainer" parent="InfoPanel/PanelContainer2/MarginContainer"] +[node name="VBoxContainer" type="VBoxContainer" parent="InfoPanel/InfoContainer/MarginContainer"] layout_mode = 2 -[node name="HBoxContainer" type="HBoxContainer" parent="InfoPanel/PanelContainer2/MarginContainer/VBoxContainer"] +[node name="HBoxContainer" type="HBoxContainer" parent="InfoPanel/InfoContainer/MarginContainer/VBoxContainer"] layout_mode = 2 theme_override_constants/separation = 20 -[node name="VBoxContainer" type="VBoxContainer" parent="InfoPanel/PanelContainer2/MarginContainer/VBoxContainer/HBoxContainer"] +[node name="VBoxContainer" type="VBoxContainer" parent="InfoPanel/InfoContainer/MarginContainer/VBoxContainer/HBoxContainer"] layout_mode = 2 -[node name="TowerName" type="Label" parent="InfoPanel/PanelContainer2/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer"] +[node name="TowerName" type="Label" parent="InfoPanel/InfoContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer"] unique_name_in_owner = true layout_mode = 2 size_flags_vertical = 1 @@ -219,7 +219,7 @@ text = "Name" horizontal_alignment = 2 vertical_alignment = 2 -[node name="TowerEnergy" type="Label" parent="InfoPanel/PanelContainer2/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer"] +[node name="TowerEnergy" type="Label" parent="InfoPanel/InfoContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer"] unique_name_in_owner = true layout_mode = 2 tooltip_text = "Le nombre de héros en action sur le terrain !" @@ -228,14 +228,14 @@ theme_override_colors/font_color = Color(0.2, 0.2, 0.2, 1) text = "0/0" horizontal_alignment = 2 -[node name="TowerIcon" type="TextureRect" parent="InfoPanel/PanelContainer2/MarginContainer/VBoxContainer/HBoxContainer"] +[node name="TowerIcon" type="TextureRect" parent="InfoPanel/InfoContainer/MarginContainer/VBoxContainer/HBoxContainer"] unique_name_in_owner = true layout_mode = 2 theme = ExtResource("5_wpcnu") texture = ExtResource("10_parkk") expand_mode = 3 -[node name="TowerDamage" type="Label" parent="InfoPanel/PanelContainer2/MarginContainer/VBoxContainer"] +[node name="TowerDamage" type="Label" parent="InfoPanel/InfoContainer/MarginContainer/VBoxContainer"] unique_name_in_owner = true layout_mode = 2 tooltip_text = "Le nombre de héros disponible dans le cube !" @@ -244,7 +244,7 @@ theme_override_colors/font_color = Color(0.2, 0.2, 0.2, 1) text = "0" horizontal_alignment = 2 -[node name="TowerCooldown" type="Label" parent="InfoPanel/PanelContainer2/MarginContainer/VBoxContainer"] +[node name="TowerCooldown" type="Label" parent="InfoPanel/InfoContainer/MarginContainer/VBoxContainer"] unique_name_in_owner = true layout_mode = 2 tooltip_text = "Le nombre de héros en action sur le terrain !" @@ -253,7 +253,7 @@ theme_override_colors/font_color = Color(0.2, 0.2, 0.2, 1) text = "0" horizontal_alignment = 2 -[node name="TowerBio" type="Label" parent="InfoPanel/PanelContainer2/MarginContainer/VBoxContainer"] +[node name="TowerBio" type="Label" parent="InfoPanel/InfoContainer/MarginContainer/VBoxContainer"] unique_name_in_owner = true visible = false layout_mode = 2 diff --git a/UI/gui_button.gd b/UI/gui_button.gd index f1419e6..d60278f 100644 --- a/UI/gui_button.gd +++ b/UI/gui_button.gd @@ -20,7 +20,8 @@ func towerLinked(value) -> void: add_theme_stylebox_override("pressed", GameStyleBoxFlat.createWithColor(GameColor.COLOR.SELECTED)) tower.changed.connect(onTowerChanged) tower.energy_changed.connect(func(): $EnergyBar.value = tower.energy) - Game.money_changed.connect(onMoneyChanged) + tower.state_changed.connect(updateDisabled) + Game.money_changed.connect(updateDisabled) EventBus.tower_selected.connect(func(_type): set_pressed_no_signal(_type == tower.type)) toggled.connect(func(state): EventBus.tower_selected.emit(tower.type if state else Tower.TYPE.NONE)) tooltip_text = tower.name @@ -29,11 +30,11 @@ func towerLinked(value) -> void: func onTowerChanged() -> void : - disabled = not tower.builded && Game.money < tower.price + disabled = not tower.selectable $EnergyBar.max_value = tower.max_energy - $EnergyBar.visible = tower.builded - $LeFond.visible = not tower.builded + $EnergyBar.visible = tower.selectable + $LeFond.visible = tower.state == Tower.STATE.BLUEPRINT -func onMoneyChanged() -> void: - disabled = not tower.builded && Game.money < tower.price +func updateDisabled() -> void: + disabled = not tower.selectable diff --git a/project.godot b/project.godot index f9997bb..c435e83 100644 --- a/project.godot +++ b/project.godot @@ -101,6 +101,11 @@ pause_game={ "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":80,"key_label":0,"unicode":112,"location":0,"echo":false,"script":null) ] } +test={ +"deadzone": 0.2, +"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":3,"canceled":false,"pressed":false,"double_click":false,"script":null) +] +} [layer_names]