From 579fc26423d17f022bfe40d7ed2e21afc395ba66 Mon Sep 17 00:00:00 2001 From: Varylios Date: Tue, 16 Sep 2025 22:14:22 +0200 Subject: [PATCH 1/4] upgrade: godot 4.5 --- Enemies/enemy.gd | 7 ++++--- Globals/Game.gd | 2 +- Globals/Helper.gd | 4 ++-- Globals/transition.gd | 4 ++-- Projectiles/Draft/projectile_pierre.gd | 2 +- UI/InfoPanel.gd | 4 ++-- UI/gui.gd | 4 ++-- Upgrades/Upgrade.gd | 11 +++++------ VFX/paint_brush_particles.gd | 2 +- VFX/pixel_rain.gd | 4 ++-- addons/LevelEditor/LevelEditor.gd | 2 +- addons/LevelEditor/WaveMaker.gd | 2 +- project.godot | 2 +- 13 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Enemies/enemy.gd b/Enemies/enemy.gd index d5d0073..0859d94 100644 --- a/Enemies/enemy.gd +++ b/Enemies/enemy.gd @@ -5,8 +5,9 @@ class_name Enemy signal died -@onready var death_vfx_packed : PackedScene = preload("res://VFX/death_particles.tscn") -@onready var sad_vfx_packed : PackedScene = preload("res://VFX/sad_particles.tscn") +const DEATH_PARTICLE : PackedScene = preload("uid://ddm57pv5ox171") +const SAD_PARTICLE : PackedScene = preload("uid://m0vj2ac5oesx") + @export var speed : float = 1 @export var base_attack_damage : int = 1 @@ -62,7 +63,7 @@ func death() -> void: died.emit() Game.money += money $Sprite3D.visible = false - var death_vfx : CPUParticles3D = death_vfx_packed.instantiate() + var death_vfx : CPUParticles3D = DEATH_PARTICLE.instantiate() get_tree().current_scene.add_child(death_vfx) death_vfx.global_position = global_position path.queue_free() diff --git a/Globals/Game.gd b/Globals/Game.gd index d82f1a2..b0051d1 100644 --- a/Globals/Game.gd +++ b/Globals/Game.gd @@ -9,7 +9,7 @@ signal lose signal allowed_tower_has_change -var upgrades : Array[CubeUpgrade] = load("res://Upgrades/cube_upgrades.tres").upgrades +var upgrades : Array[CubeUpgrade] = load("uid://py454tq2ghgx").upgrades var towerPackedScenes : Dictionary var enmies : Dictionary var towers : Dictionary diff --git a/Globals/Helper.gd b/Globals/Helper.gd index d9f48ef..bdacbe7 100644 --- a/Globals/Helper.gd +++ b/Globals/Helper.gd @@ -2,7 +2,7 @@ class_name Helper -const confirmPopupScene : PackedScene = preload("res://UI/confirm_popup.tscn") +const CONFIRM_POPUP : PackedScene = preload("uid://cxn3x8dq8vawa") const SCENE_DIR_PATTERN : String = "res://\\w+/(Scenes|Map \\d+)/$" @@ -75,7 +75,7 @@ static func showConfirmPopup( confirmCallback : Callable, cancelCallback : Callable = func(): null ) -> void: - var confirmPopup : ConfirmPopup = confirmPopupScene.instantiate() + var confirmPopup : ConfirmPopup = CONFIRM_POPUP.instantiate() nodeToAppend.add_child(confirmPopup) confirmPopup.label.text = text confirmPopup.confirmed.connect(confirmCallback) diff --git a/Globals/transition.gd b/Globals/transition.gd index 408535d..df59fa5 100644 --- a/Globals/transition.gd +++ b/Globals/transition.gd @@ -2,7 +2,7 @@ extends ColorRect enum LOAD_STATE { NO_LOAD, BASIC_LOAD, MAP_LOAD, MAP_LOADED } -const worldManager = preload("res://Levels/world_manager.tscn") +const WORLD_MANAGER = preload("uid://bph5gpic1arod") @export var opaque := 0.0 @export var transparent := 11.0 @@ -78,7 +78,7 @@ func _process(_delta: float) -> void: var scene = ResourceLoader.load_threaded_get(target_scene_path) if loadState == LOAD_STATE.MAP_LOAD: mapScene = scene - get_tree().change_scene_to_packed(worldManager) + get_tree().change_scene_to_packed(WORLD_MANAGER) loadState = LOAD_STATE.MAP_LOADED if loadState == LOAD_STATE.BASIC_LOAD: get_tree().change_scene_to_packed(scene) diff --git a/Projectiles/Draft/projectile_pierre.gd b/Projectiles/Draft/projectile_pierre.gd index 986cb4b..aed4ca1 100644 --- a/Projectiles/Draft/projectile_pierre.gd +++ b/Projectiles/Draft/projectile_pierre.gd @@ -1,6 +1,6 @@ extends Sprite3D -var impact : GPUParticles3D = preload("res://Projectiles/Draft/ImpactPierre.tscn").instantiate() +var impact : GPUParticles3D = preload("uid://c5rx5scnkh3fb").instantiate() func _ready() -> void: $SFXCreate.play() diff --git a/UI/InfoPanel.gd b/UI/InfoPanel.gd index 4305cfb..fccf979 100644 --- a/UI/InfoPanel.gd +++ b/UI/InfoPanel.gd @@ -1,7 +1,7 @@ extends HBoxContainer -const upgradeBtnScene : PackedScene = preload("res://UI/upgrade_button.tscn") +const UPGRADE_BTN : PackedScene = preload("uid://dfp5q5gek4ve7") var tower : Tower @@ -59,7 +59,7 @@ func createTowerUpgradeButtons(upgrades : Array) -> void: %UpgradeContainer.visible = true %UpgradeContainer.get_children().map(func(btn): btn.queue_free()) for upgrade in upgrades: - var btn : UpgradeButton = upgradeBtnScene.instantiate() + var btn : UpgradeButton = UPGRADE_BTN.instantiate() %UpgradeContainer.add_child(btn) btn.setUpgrade(upgrade) if tower: diff --git a/UI/gui.gd b/UI/gui.gd index 533cc9d..962cc8a 100644 --- a/UI/gui.gd +++ b/UI/gui.gd @@ -3,7 +3,7 @@ extends Control const BUTTON_QTY = 4 -const guiButton : PackedScene = preload("res://UI/gui_button.tscn") +const GUI_BUTTON : PackedScene = preload("uid://dqb5o8w7u50hc") @onready var buttonContainer : GridContainer = %ButtonContainer @onready var cubeIntegrity : ProgressBar = %CubeIntegrity @@ -77,7 +77,7 @@ func addTowerButtonNodes() -> void: func createTowerButton(towerType : Tower.TYPE) -> void: - var btn : GuiButton = guiButton.instantiate() + var btn : GuiButton = GUI_BUTTON.instantiate() btn.set_meta("dynamicButton", true) if towerType: diff --git a/Upgrades/Upgrade.gd b/Upgrades/Upgrade.gd index a3270e1..eabbf34 100644 --- a/Upgrades/Upgrade.gd +++ b/Upgrades/Upgrade.gd @@ -1,12 +1,12 @@ -extends Resource -class_name Upgrade +@abstract +class_name Upgrade extends Resource enum SCALE_TYPE { LINEAR, EXP, LOG } enum UPGRADE_DIRECTION { INCREASE = 1, DECREASE = -1 } -@export var icon : Texture2D = preload("res://Assets/Icones/medal2.png") +@export var icon : Texture2D = preload("uid://dqvou7t7o1t5d") @export var text : String @export var baseCost : int : set(value): @@ -32,9 +32,8 @@ var level : int = 0 func isLevelMax() -> bool : return not tierLock.is_empty() && level == tierLock[Game.tier] - -func upgrade(_subject = null) -> bool: - return false +@abstract +func upgrade(_subject = null) -> bool func upgradeProperty(subject: Variant, property: String) -> void: diff --git a/VFX/paint_brush_particles.gd b/VFX/paint_brush_particles.gd index fe7d229..e2fada2 100644 --- a/VFX/paint_brush_particles.gd +++ b/VFX/paint_brush_particles.gd @@ -1,6 +1,6 @@ extends Path3D -var particle_np := preload("res://VFX/paint_brush_particle.tscn") +var particle_np := preload("uid://drnc0eus8n2oy") @export var duration : float = 6.0 @export var spawn_timer : float = 0.1 diff --git a/VFX/pixel_rain.gd b/VFX/pixel_rain.gd index 498c2ea..b65cc3b 100644 --- a/VFX/pixel_rain.gd +++ b/VFX/pixel_rain.gd @@ -10,7 +10,7 @@ extends Node2D var time := 0.0 -var rain_drop_packed := preload("res://VFX/pixel_drop.tscn") +const RAIN_DROP : PackedScene = preload("uid://cqn4xrehqnuso") func _physics_process(delta: float) -> void: @@ -21,7 +21,7 @@ func _physics_process(delta: float) -> void: func make_it_rain() -> void: - var rain_drop : RainDrop = rain_drop_packed.instantiate() + var rain_drop : RainDrop = RAIN_DROP.instantiate() var screen_width = get_viewport().get_camera_2d().position.x + get_viewport().size.x/2 var screen_height = get_viewport().get_camera_2d().position.y - get_viewport().size.y/2 - 100 #Offset rain_drop.speed = speed diff --git a/addons/LevelEditor/LevelEditor.gd b/addons/LevelEditor/LevelEditor.gd index e5e1911..89f920f 100644 --- a/addons/LevelEditor/LevelEditor.gd +++ b/addons/LevelEditor/LevelEditor.gd @@ -3,7 +3,7 @@ extends EditorPlugin # Replace this value with a PascalCase autoload name, as per the GDScript style guide. #const AUTOLOAD_NAME = "LevelEditorAutoload" -const ui = preload("res://addons/LevelEditor/wave_maker.tscn") +const ui = preload("uid://dh24t8804isms") var main_panel_instance diff --git a/addons/LevelEditor/WaveMaker.gd b/addons/LevelEditor/WaveMaker.gd index 84f2d4f..8791e6f 100644 --- a/addons/LevelEditor/WaveMaker.gd +++ b/addons/LevelEditor/WaveMaker.gd @@ -6,7 +6,7 @@ class_name WaveMaker signal spawnQtyChanged(newQty : int) -const TROOP_SCENE = preload("res://addons/LevelEditor/UI/Troop/Troop.tscn") +const TROOP_SCENE = preload("uid://djrbvm8gmhly3") var level : Level diff --git a/project.godot b/project.godot index 26ef7df..ac7f125 100644 --- a/project.godot +++ b/project.godot @@ -25,7 +25,7 @@ resources_spreadsheet_view/freeze_first_column=true config/name="Pole Pixel Defense Force" run/main_scene="uid://2xw1yn1tmlcy" -config/features=PackedStringArray("4.4") +config/features=PackedStringArray("4.5") config/icon="res://icon.svg" [audio] -- 2.45.3 From 868810ca828c33127fbb570484eb4093136d5b35 Mon Sep 17 00:00:00 2001 From: Varylios Date: Sat, 20 Sep 2025 19:58:50 +0200 Subject: [PATCH 2/4] refactor: projectiles logic - add hitscan - add camera arrow key move --- Globals/EventBus.gd | 2 +- Levels/Scripts/Camera.gd | 26 ++- Levels/Scripts/WorldManager.gd | 4 +- Projectiles/Projectile.gd | 170 +++++++++----------- Projectiles/Scenes/projectile-Aline.tscn | 12 +- Projectiles/Scenes/projectile-James.tscn | 3 +- Projectiles/Scenes/projectile-Pierre.tscn | 1 - Projectiles/Scenes/projectile-Victoria.tscn | 13 +- Projectiles/Scenes/projectile-maxence.tscn | 19 +++ Projectiles/projectile.tscn | 7 +- Towers/Scenes/maxence.tscn | 4 +- 11 files changed, 137 insertions(+), 124 deletions(-) create mode 100644 Projectiles/Scenes/projectile-maxence.tscn diff --git a/Globals/EventBus.gd b/Globals/EventBus.gd index 9b81764..b03b7b8 100644 --- a/Globals/EventBus.gd +++ b/Globals/EventBus.gd @@ -29,7 +29,7 @@ signal team_in_rest_changed(count : int) ## [b]Emitter[/b] : [Projectile][br] ## [b]Subscriber[/b] : [code]null[/code] -signal projectile_shooted(projectile: Projectile, startPosition: Vector3) +signal projectile_shooted(projectile: Projectile, transform: Transform3D) ## [b]Emitter[/b] : [WorldManager][br] diff --git a/Levels/Scripts/Camera.gd b/Levels/Scripts/Camera.gd index e2ad8af..2a32ad1 100644 --- a/Levels/Scripts/Camera.gd +++ b/Levels/Scripts/Camera.gd @@ -22,12 +22,12 @@ func _process(_delta: float) -> void: var mousePosition : Vector2 = get_viewport().get_mouse_position() if mousePosition.x < SCREEN_MARGIN: - position.x += -SCREEN_MOVEMENT_SPEED - if mousePosition.y < SCREEN_MARGIN: - position.z += -SCREEN_MOVEMENT_SPEED - if mousePosition.x > windowSize.x - SCREEN_MARGIN: + position.x -= SCREEN_MOVEMENT_SPEED + elif mousePosition.x > windowSize.x - SCREEN_MARGIN: position.x += SCREEN_MOVEMENT_SPEED - if mousePosition.y > windowSize.y - SCREEN_MARGIN: + if mousePosition.y < SCREEN_MARGIN: + position.z -= SCREEN_MOVEMENT_SPEED + elif mousePosition.y > windowSize.y - SCREEN_MARGIN: position.z += SCREEN_MOVEMENT_SPEED @@ -38,9 +38,13 @@ func _notification(what: int) -> void: func _input(event: InputEvent) -> void: - if not event is InputEventMouseButton: - return + if event is InputEventMouseButton: + onEventMouseButton(event) + elif event is InputEventKey: + onEventKey(event) + +func onEventMouseButton(event: InputEventMouseButton) -> void: var newPosition : float = position.y match event.button_index: MOUSE_BUTTON_WHEEL_UP: newPosition -= .2 @@ -50,3 +54,11 @@ func _input(event: InputEvent) -> void: rotation.x = deg_to_rad(curve.sample(newPosition)) position.y = newPosition + + +func onEventKey(event: InputEventKey) -> void: + match event.keycode: + KEY_LEFT: position.x -= SCREEN_MOVEMENT_SPEED * 4 + KEY_RIGHT: position.x += SCREEN_MOVEMENT_SPEED * 4 + KEY_UP: position.z -= SCREEN_MOVEMENT_SPEED * 4 + KEY_DOWN: position.z += SCREEN_MOVEMENT_SPEED * 4 diff --git a/Levels/Scripts/WorldManager.gd b/Levels/Scripts/WorldManager.gd index 2167566..34cf397 100644 --- a/Levels/Scripts/WorldManager.gd +++ b/Levels/Scripts/WorldManager.gd @@ -118,6 +118,6 @@ func addMap(mapScene : PackedScene) -> void: state = STATE.SPAWN if level.auto_start else STATE.IDLE -func onProjectileShooted(projectile: Projectile, startPosition: Vector3) -> void: +func onProjectileShooted(projectile: Projectile, _transform: Transform3D) -> void: add_child(projectile) - projectile.global_position = startPosition + projectile.transform = _transform diff --git a/Projectiles/Projectile.gd b/Projectiles/Projectile.gd index 3d88299..35f3c0b 100644 --- a/Projectiles/Projectile.gd +++ b/Projectiles/Projectile.gd @@ -2,27 +2,35 @@ extends CharacterBody3D class_name Projectile -enum MODE { - FOLLOW, ## Follow Entity - LOCATION, ## Go to entity location - HITSCAN, ## DANGER NOT implemented yet +enum Mode { + FOLLOW, ## Follow target + LOCATION, ## Go to target location + SPAWN_ON_TARGET, ## Spawn on target location + HITSCAN, ## Spawn on target location } -enum TYPE { ## Types of projectiles - BASIC, ## One target - AOE, ## Multiple targets[br]work with [member damageArea] - PIERCING, ## Piercing through enemies[br]work with [member maxTarets] and [member damageArea] - BOUNCING, ## Bouncing over enemies[br]work with [member maxTarets] and [member damageArea] - DISABLING, ## Disable ally tower for [member damage] duration [br]Usable on [Boss] projectiles +enum Duration { + ONE_HIT, ## Make damage on hit + DAMAGE_OVER_TIME, ## Make damage every tick for specified duration[br]work with [member maxTargets] for number of tick +} + +enum Type { ## Types of projectiles + BASIC, ## One defined target + AOE, ## Multiple targets + BOUNCING, ## Bouncing over enemies[br]work with [member maxTargets] + DISABLING, ## Disable ally tower for [member amount] duration [br]Usable on [Boss] projectiles } -@export var type : TYPE = TYPE.BASIC -@export var mode : MODE = MODE.FOLLOW +@export var mode : Mode = Mode.FOLLOW +@export var duration : Duration = Duration.ONE_HIT +@export var type : Type = Type.BASIC @export var speed : int +## Usefull when [enum Type] is not [constant BASIC][br] +## [code]-1[/code] for no maximum +## Used as time when [enum Duration] is [constant HITSCAN] @export var maxTargets : int = 1 - var amount : float var target : PhysicsBody3D var vectorTarget : Vector3 @@ -31,93 +39,75 @@ var collidingBodies : Array[Node3D] var affectedTarget : Array[Node3D] +func _ready() -> void: + $HitBox.body_entered.connect(collidingBodies.append) + #$HitBox.body_entered.connect(test) + $HitBox.body_exited.connect(collidingBodies.erase) + $EffectArea.body_entered.connect(bodiesInRange.append) + $EffectArea.body_exited.connect(bodiesInRange.erase) + + +func test(body): + print(body) + +var firstTick : bool = true func _physics_process(_delta: float) -> void: - if mode == MODE.LOCATION && vectorTarget.distance_squared_to(global_position) < .4: - resolveContact() - maxTargets = 0 # Ensure queue free in next if + if firstTick: + firstTick = false + return + + resolveContact() if shouldQueueFree(): - return queue_free() + queue_free.call_deferred() + return - if not collidingBodies.is_empty() && collidingBodies.has(target): - return onBodyCollideWithProjectile(target) - - var globalPos : Vector3 = vectorTarget if vectorTarget else target.global_position - if target: + if mode == Mode.FOLLOW: + var globalPos : Vector3 = target.global_position globalPos.y += Helper.getHitBoxLocation(target, Helper.POSITION.CENTER) - look_at(globalPos) - velocity = global_position.direction_to(globalPos) * speed + look_at(globalPos) + velocity = global_position.direction_to(globalPos) * speed + move_and_slide() func shouldQueueFree() -> bool: - if maxTargets < 1: + if maxTargets == 0 || !is_instance_valid(target) && mode == Mode.FOLLOW: return true - - if !is_instance_valid(target): - return mode == MODE.FOLLOW + elif mode != Mode.FOLLOW: + return isOnTarget() elif target is Tower: return not target.visible return false -func onBodyEnteredDamageArea(body: Node3D) -> void: - if type != TYPE.BASIC && targetable(body): - addBodyInRange(body) - if type == TYPE.PIERCING: - resolveContact() - - -func onBodyCollideWithProjectile(body: Node3D) -> void: - if not collidingBodies.has(body): - collidingBodies.push_back(body) - - if mode != MODE.LOCATION && (body == target || type == TYPE.PIERCING) && targetable(body): - addBodyInRange(body, true) - resolveContact() - - -func addBodyInRange(body: Node3D, pushFront: bool = false) -> void: - var idx : int = bodiesInRange.find(body) - - if idx == -1: - if pushFront: - bodiesInRange.push_front(body) - else: - bodiesInRange.push_back(body) - elif pushFront && idx != 0: - bodiesInRange.remove_at(idx) - bodiesInRange.push_front(body) - - -func targetable(body: Node3D) -> bool: - return not affectedTarget.has(body) +func isOnTarget() -> bool: + match mode: + Mode.LOCATION, Mode.SPAWN_ON_TARGET: return vectorTarget.distance_squared_to(global_position) < .4 + Mode.FOLLOW: return collidingBodies.has(target) + Mode.HITSCAN: return true + _: return false func resolveContact() -> void: - if bodiesInRange.is_empty(): + if collidingBodies.is_empty() || not isOnTarget(): return - resolveEffect(bodiesInRange[0]) - match type: - TYPE.AOE: - for bodyInRange in bodiesInRange: - if is_instance_valid(bodyInRange): - resolveEffect(bodyInRange, false) - - TYPE.BOUNCING: - target = null if bodiesInRange.is_empty() else bodiesInRange[0] + Type.AOE: + collidingBodies.map(resolveEffect) + _ when collidingBodies.has(target): + resolveEffect(target) + if type == Type.BOUNCING: + target = null if bodiesInRange.is_empty() else bodiesInRange[0] -func resolveEffect(body : Node3D, erase : bool = true) -> void: - if erase: - bodiesInRange.erase(body) - if affectedTarget.has(body) || body is GameTile: +func resolveEffect(body : Node3D) -> void: + if affectedTarget.has(body) || body is GameTile || maxTargets == 0: return - if type == TYPE.DISABLING && body.has_method("disable"): + if type == Type.DISABLING && body.has_method("disable"): body.disable(amount) elif body.has_method("take_damage"): body.take_damage(amount) @@ -126,23 +116,23 @@ func resolveEffect(body : Node3D, erase : bool = true) -> void: maxTargets -= 1 -func removeTarget(body: Node3D) -> void: - bodiesInRange.erase(body) - - -func removeCollidingBody(body: Node3D) -> void: - collidingBodies.erase(body) - - func shoot(_target: Node3D, globalPos: Vector3) -> void: target = _target - match mode: - Projectile.MODE.HITSCAN: - globalPos = target.global_position - globalPos.y += Helper.getHitBoxLocation(target, Helper.POSITION.CENTER) - Projectile.MODE.LOCATION: - vectorTarget = target.global_position - vectorTarget.y += Helper.getHitBoxLocation(target, Helper.POSITION.CENTER) + var transform3D : Transform3D = Transform3D() + transform3D.origin = globalPos - EventBus.projectile_shooted.emit(self, globalPos) + var targetPosition : Vector3 = target.global_position + targetPosition.y += Helper.getHitBoxLocation(target, Helper.POSITION.CENTER) + transform3D = transform3D.looking_at(targetPosition) + match mode: + Mode.SPAWN_ON_TARGET: + transform3D.origin = targetPosition + transform3D = transform3D.looking_at(globalPos) + vectorTarget = targetPosition + Mode.LOCATION: + vectorTarget = targetPosition + velocity = transform3D.origin.direction_to(vectorTarget) * speed + + print(transform3D) + EventBus.projectile_shooted.emit(self, transform3D) diff --git a/Projectiles/Scenes/projectile-Aline.tscn b/Projectiles/Scenes/projectile-Aline.tscn index d68c3ab..79ac8fb 100644 --- a/Projectiles/Scenes/projectile-Aline.tscn +++ b/Projectiles/Scenes/projectile-Aline.tscn @@ -2,20 +2,20 @@ [ext_resource type="PackedScene" uid="uid://oykrff3g74eo" path="res://Projectiles/projectile.tscn" id="1_4tmpc"] -[sub_resource type="SphereShape3D" id="SphereShape3D_k24mn"] +[sub_resource type="SphereShape3D" id="SphereShape3D_2ioqj"] radius = 0.3 [node name="Projectile" instance=ExtResource("1_4tmpc")] -type = 1 mode = 1 +type = 1 speed = 3 -damage = 6 +maxTargets = -1 [node name="HitBox" parent="." index="2"] collision_mask = 2 +[node name="ProjectileSize" parent="HitBox" index="0"] +shape = SubResource("SphereShape3D_2ioqj") + [node name="DamageArea" parent="." index="3"] collision_mask = 2 - -[node name="Node" type="CollisionShape3D" parent="DamageArea" index="0"] -shape = SubResource("SphereShape3D_k24mn") diff --git a/Projectiles/Scenes/projectile-James.tscn b/Projectiles/Scenes/projectile-James.tscn index 06e8c6e..2508618 100644 --- a/Projectiles/Scenes/projectile-James.tscn +++ b/Projectiles/Scenes/projectile-James.tscn @@ -4,9 +4,8 @@ [ext_resource type="Texture2D" uid="uid://b7jiyk3w5tl02" path="res://Assets/Icones/Spritesheet_Cakes_WITH_OUTLINE.png" id="2_ckawd"] [node name="Projectile" instance=ExtResource("1_do0ca")] -type = 4 +type = 3 speed = 2 -damage = 3 [node name="Sprite3D" parent="." index="1"] transform = Transform3D(1.3, 0, 0, 0, 1.3, 0, 0, 0, 1.3, 0, 0, 0) diff --git a/Projectiles/Scenes/projectile-Pierre.tscn b/Projectiles/Scenes/projectile-Pierre.tscn index d9c0126..26b91e3 100644 --- a/Projectiles/Scenes/projectile-Pierre.tscn +++ b/Projectiles/Scenes/projectile-Pierre.tscn @@ -4,7 +4,6 @@ [node name="Projectile" instance=ExtResource("1_d01p1")] speed = 15 -damage = 2 [node name="HitBox" parent="." index="2"] collision_mask = 2 diff --git a/Projectiles/Scenes/projectile-Victoria.tscn b/Projectiles/Scenes/projectile-Victoria.tscn index 78bf3d2..46791c6 100644 --- a/Projectiles/Scenes/projectile-Victoria.tscn +++ b/Projectiles/Scenes/projectile-Victoria.tscn @@ -6,15 +6,12 @@ radius = 1.5 [node name="Projectile" instance=ExtResource("1_suva6")] -type = 3 +type = 2 speed = 5 maxTargets = 3 -[node name="HitBox" parent="." index="2"] -collision_mask = 2 - -[node name="DamageArea" parent="." index="3"] -collision_mask = 2 - -[node name="BoucingRange" type="CollisionShape3D" parent="DamageArea" index="0"] +[node name="DamageArea#BoucingRange" type="CollisionShape3D" parent="." index="0"] shape = SubResource("SphereShape3D_k24mn") + +[node name="HitBox" parent="." index="3"] +collision_mask = 2 diff --git a/Projectiles/Scenes/projectile-maxence.tscn b/Projectiles/Scenes/projectile-maxence.tscn new file mode 100644 index 0000000..d6141d2 --- /dev/null +++ b/Projectiles/Scenes/projectile-maxence.tscn @@ -0,0 +1,19 @@ +[gd_scene load_steps=3 format=3 uid="uid://baixm8pfsdo3t"] + +[ext_resource type="PackedScene" uid="uid://oykrff3g74eo" path="res://Projectiles/projectile.tscn" id="1_a1h27"] + +[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_a1h27"] +radius = 0.1 +height = 10.0 + +[node name="Projectile" instance=ExtResource("1_a1h27")] +mode = 3 +type = 1 +maxTargets = 5 + +[node name="HitBox" parent="." index="2"] +collision_mask = 2 + +[node name="ProjectileSize" parent="HitBox" index="0"] +transform = Transform3D(1, 0, 0, 0, -4.371139e-08, -1, 0, 1, -4.371139e-08, 0, 0, -5) +shape = SubResource("CapsuleShape3D_a1h27") diff --git a/Projectiles/projectile.tscn b/Projectiles/projectile.tscn index 3d0bee3..89f3037 100644 --- a/Projectiles/projectile.tscn +++ b/Projectiles/projectile.tscn @@ -30,11 +30,6 @@ collision_mask = 0 shape = SubResource("SphereShape3D_dsts2") debug_color = Color(0.926858, 0.237749, 0.335021, 0.42) -[node name="DamageArea" type="Area3D" parent="."] +[node name="EffectArea" type="Area3D" parent="."] collision_layer = 0 collision_mask = 0 - -[connection signal="body_entered" from="HitBox" to="." method="onBodyCollideWithProjectile" flags=3] -[connection signal="body_exited" from="HitBox" to="." method="removeCollidingBody"] -[connection signal="body_entered" from="DamageArea" to="." method="onBodyEnteredDamageArea"] -[connection signal="body_exited" from="DamageArea" to="." method="removeTarget"] diff --git a/Towers/Scenes/maxence.tscn b/Towers/Scenes/maxence.tscn index 2edd650..da57ed9 100644 --- a/Towers/Scenes/maxence.tscn +++ b/Towers/Scenes/maxence.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=5 format=3 uid="uid://b1pg1hgysx3am"] +[gd_scene load_steps=6 format=3 uid="uid://b1pg1hgysx3am"] [ext_resource type="PackedScene" uid="uid://trg7ag3dqr2l" path="res://Towers/tower.tscn" id="1_laam8"] [ext_resource type="Texture2D" uid="uid://boxdrq4nrq7hv" path="res://Assets/Icones/flamingo.svg" id="2_sciv6"] +[ext_resource type="PackedScene" uid="uid://baixm8pfsdo3t" path="res://Projectiles/Scenes/projectile-maxence.tscn" id="3_7fox5"] [sub_resource type="SphereShape3D" id="SphereShape3D_pw4mj"] radius = 10.0 @@ -16,6 +17,7 @@ icone = ExtResource("2_sciv6") bio = "" price = 200 damage = 10 +projectileScene = ExtResource("3_7fox5") towerRange = SubResource("SphereShape3D_pw4mj") action_cooldown = 3.0 max_energy = 50.0 -- 2.45.3 From ee46149287ea6c3543151a4d841a4811f36631e5 Mon Sep 17 00:00:00 2001 From: Varylios Date: Sun, 21 Sep 2025 00:32:13 +0200 Subject: [PATCH 3/4] feat: add projectile effects + states --- Globals/Helper.gd | 7 +- Projectiles/Projectile.gd | 107 ++++++++++++++------ Projectiles/Scenes/projectile-Evan.tscn | 41 ++++++++ Projectiles/Scenes/projectile-Victoria.tscn | 14 +-- Towers/Scenes/evan.tscn | 10 +- 5 files changed, 140 insertions(+), 39 deletions(-) create mode 100644 Projectiles/Scenes/projectile-Evan.tscn diff --git a/Globals/Helper.gd b/Globals/Helper.gd index bdacbe7..73d684d 100644 --- a/Globals/Helper.gd +++ b/Globals/Helper.gd @@ -73,13 +73,14 @@ static func showConfirmPopup( text : String, nodeToAppend : Node, confirmCallback : Callable, - cancelCallback : Callable = func(): null + cancelCallback : Callable = func(): pass ) -> void: var confirmPopup : ConfirmPopup = CONFIRM_POPUP.instantiate() nodeToAppend.add_child(confirmPopup) + nodeToAppend.get_tree().paused = true confirmPopup.label.text = text - confirmPopup.confirmed.connect(confirmCallback) - confirmPopup.canceled.connect(cancelCallback) + confirmPopup.confirmed.connect(func(): confirmCallback.call(); nodeToAppend.get_tree().paused = false) + confirmPopup.canceled.connect(func(): cancelCallback.call(); nodeToAppend.get_tree().paused = false) enum POSITION { TOP, CENTER, DOWN } static func getHitBoxLocation(body : CollisionObject3D, position : POSITION) -> float: diff --git a/Projectiles/Projectile.gd b/Projectiles/Projectile.gd index 35f3c0b..6776d15 100644 --- a/Projectiles/Projectile.gd +++ b/Projectiles/Projectile.gd @@ -2,6 +2,9 @@ extends CharacterBody3D class_name Projectile +enum State { INIT, TRAVEL, EFFECT, DESPAWN } + + enum Mode { FOLLOW, ## Follow target LOCATION, ## Go to target location @@ -9,9 +12,15 @@ enum Mode { HITSCAN, ## Spawn on target location } -enum Duration { + +enum Effect { ONE_HIT, ## Make damage on hit - DAMAGE_OVER_TIME, ## Make damage every tick for specified duration[br]work with [member maxTargets] for number of tick + ## Make damage every tick for specified duration[br] + ## work with [member dotTicks] for number of tick + DAMAGE_OVER_TIME, + ## Make damage over time on hitted target for the specified duration[br] + ## work with [member dotTicks] for number of tick + POISON, } enum Type { ## Types of projectiles @@ -23,14 +32,17 @@ enum Type { ## Types of projectiles @export var mode : Mode = Mode.FOLLOW -@export var duration : Duration = Duration.ONE_HIT +@export var effect : Effect = Effect.ONE_HIT @export var type : Type = Type.BASIC @export var speed : int -## Usefull when [enum Type] is not [constant BASIC][br] -## [code]-1[/code] for no maximum -## Used as time when [enum Duration] is [constant HITSCAN] +## Usefull when [enum Type] is not [constant BASIC][br][code]-1[/code] for no maximum @export var maxTargets : int = 1 +## The amount of ticks +## Used as time when [enum Effect] is [constant DAMAGE_OVER_TIME] or [constant POISON] +@export var dotTicks : int +@export var tickInterval : float ## +var state : State = State.INIT var amount : float var target : PhysicsBody3D var vectorTarget : Vector3 @@ -41,25 +53,30 @@ var affectedTarget : Array[Node3D] func _ready() -> void: $HitBox.body_entered.connect(collidingBodies.append) - #$HitBox.body_entered.connect(test) $HitBox.body_exited.connect(collidingBodies.erase) $EffectArea.body_entered.connect(bodiesInRange.append) $EffectArea.body_exited.connect(bodiesInRange.erase) -func test(body): - print(body) - -var firstTick : bool = true func _physics_process(_delta: float) -> void: - if firstTick: - firstTick = false + if state == State.INIT: + state = State.TRAVEL return - resolveContact() + match state: + State.TRAVEL when isOnTarget(): + state = State.EFFECT + applyEffects() + return + State.EFFECT: return + State.DESPAWN: + queue_free.call_deferred() + return if shouldQueueFree(): - queue_free.call_deferred() + state = State.DESPAWN + + if state != State.TRAVEL: return if mode == Mode.FOLLOW: @@ -72,39 +89,63 @@ func _physics_process(_delta: float) -> void: func shouldQueueFree() -> bool: - if maxTargets == 0 || !is_instance_valid(target) && mode == Mode.FOLLOW: - return true - elif mode != Mode.FOLLOW: - return isOnTarget() + if !is_instance_valid(target): + return mode == Mode.FOLLOW || maxTargets == 0 elif target is Tower: return not target.visible - return false + return maxTargets == 0 func isOnTarget() -> bool: match mode: - Mode.LOCATION, Mode.SPAWN_ON_TARGET: return vectorTarget.distance_squared_to(global_position) < .4 + Mode.LOCATION: return vectorTarget.distance_squared_to(global_position) < .4 Mode.FOLLOW: return collidingBodies.has(target) - Mode.HITSCAN: return true + Mode.HITSCAN, Mode.SPAWN_ON_TARGET: return true _: return false -func resolveContact() -> void: - if collidingBodies.is_empty() || not isOnTarget(): - return +func applyEffects() -> void: + if not collidingBodies.is_empty() && isOnTarget(): + resolveContacts() + if effect == Effect.DAMAGE_OVER_TIME: + dotTicks -= 1 + state = State.DESPAWN + if dotTicks > 0: + state = State.EFFECT + await get_tree().create_timer(tickInterval).timeout + applyEffects.call_deferred() + + +func resolveContacts() -> void: match type: Type.AOE: + if maxTargets > 0: # No need to sort if we want to hit all targets + collidingBodies.sort_custom(sortTargets) collidingBodies.map(resolveEffect) _ when collidingBodies.has(target): resolveEffect(target) if type == Type.BOUNCING: - target = null if bodiesInRange.is_empty() else bodiesInRange[0] + target = chooseNextTarget() + state = State.TRAVEL + return + + +func sortTargets(body1: Node3D, body2: Node3D) -> bool: + return vectorTarget.distance_to(body1.global_position) < vectorTarget.distance_to(body2.global_position) + + +func chooseNextTarget() -> Node3D: + var bodies = bodiesInRange.filter(func(body): return not affectedTarget.has(body)) + if bodies.is_empty(): + return null + bodies.sort_custom(sortTargets) + return bodies[0] func resolveEffect(body : Node3D) -> void: - if affectedTarget.has(body) || body is GameTile || maxTargets == 0: + if body is GameTile || maxTargets == 0: return if type == Type.DISABLING && body.has_method("disable"): @@ -112,12 +153,21 @@ func resolveEffect(body : Node3D) -> void: elif body.has_method("take_damage"): body.take_damage(amount) + if effect == Effect.POISON: + dotTicks -= 1 + while dotTicks > 0 && is_instance_valid(body): + dotTicks -= 1 + await get_tree().create_timer(tickInterval).timeout + body.take_damage(amount) + affectedTarget.append(body) maxTargets -= 1 + state = State.DESPAWN func shoot(_target: Node3D, globalPos: Vector3) -> void: target = _target + vectorTarget = globalPos var transform3D : Transform3D = Transform3D() transform3D.origin = globalPos @@ -127,12 +177,11 @@ func shoot(_target: Node3D, globalPos: Vector3) -> void: transform3D = transform3D.looking_at(targetPosition) match mode: Mode.SPAWN_ON_TARGET: + vectorTarget = targetPosition transform3D.origin = targetPosition transform3D = transform3D.looking_at(globalPos) - vectorTarget = targetPosition Mode.LOCATION: vectorTarget = targetPosition velocity = transform3D.origin.direction_to(vectorTarget) * speed - print(transform3D) EventBus.projectile_shooted.emit(self, transform3D) diff --git a/Projectiles/Scenes/projectile-Evan.tscn b/Projectiles/Scenes/projectile-Evan.tscn new file mode 100644 index 0000000..d9d659a --- /dev/null +++ b/Projectiles/Scenes/projectile-Evan.tscn @@ -0,0 +1,41 @@ +[gd_scene load_steps=7 format=3 uid="uid://dp8tg6cpu3ftd"] + +[ext_resource type="PackedScene" uid="uid://oykrff3g74eo" path="res://Projectiles/projectile.tscn" id="1_yw5ty"] + +[sub_resource type="SphereShape3D" id="SphereShape3D_xshf4"] + +[sub_resource type="Gradient" id="Gradient_yw5ty"] +offsets = PackedFloat32Array(0, 0.5, 1) +colors = PackedColorArray(1, 0.007843138, 0, 1, 1, 0.54901963, 0, 1, 1, 0, 0, 1) +metadata/_snap_enabled = true + +[sub_resource type="GradientTexture1D" id="GradientTexture1D_xshf4"] +gradient = SubResource("Gradient_yw5ty") + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_yw5ty"] +transparency = 4 +albedo_color = Color(1, 1, 1, 0.43137255) +albedo_texture = SubResource("GradientTexture1D_xshf4") + +[sub_resource type="SphereMesh" id="SphereMesh_q317a"] +material = SubResource("StandardMaterial3D_yw5ty") + +[node name="Projectile" instance=ExtResource("1_yw5ty")] +mode = 2 +effect = 1 +type = 1 +maxTargets = -1 +dotTicks = 6 +tickInterval = 0.5 + +[node name="Sprite3D" parent="." index="1"] +visible = false + +[node name="HitBox" parent="." index="2"] +collision_mask = 2 + +[node name="ProjectileSize" parent="HitBox" index="0"] +shape = SubResource("SphereShape3D_xshf4") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="." index="4"] +mesh = SubResource("SphereMesh_q317a") diff --git a/Projectiles/Scenes/projectile-Victoria.tscn b/Projectiles/Scenes/projectile-Victoria.tscn index 46791c6..ae5e8bc 100644 --- a/Projectiles/Scenes/projectile-Victoria.tscn +++ b/Projectiles/Scenes/projectile-Victoria.tscn @@ -2,16 +2,18 @@ [ext_resource type="PackedScene" uid="uid://oykrff3g74eo" path="res://Projectiles/projectile.tscn" id="1_suva6"] -[sub_resource type="SphereShape3D" id="SphereShape3D_k24mn"] -radius = 1.5 +[sub_resource type="SphereShape3D" id="SphereShape3D_878kj"] [node name="Projectile" instance=ExtResource("1_suva6")] type = 2 speed = 5 maxTargets = 3 -[node name="DamageArea#BoucingRange" type="CollisionShape3D" parent="." index="0"] -shape = SubResource("SphereShape3D_k24mn") - -[node name="HitBox" parent="." index="3"] +[node name="HitBox" parent="." index="2"] collision_mask = 2 + +[node name="EffectArea" parent="." index="3"] +collision_mask = 2 + +[node name="CollisionShape3D" type="CollisionShape3D" parent="EffectArea" index="0"] +shape = SubResource("SphereShape3D_878kj") diff --git a/Towers/Scenes/evan.tscn b/Towers/Scenes/evan.tscn index 23c8b88..b15309e 100644 --- a/Towers/Scenes/evan.tscn +++ b/Towers/Scenes/evan.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=5 format=3 uid="uid://c4ta0aynybpis"] +[gd_scene load_steps=6 format=3 uid="uid://c4ta0aynybpis"] [ext_resource type="PackedScene" uid="uid://trg7ag3dqr2l" path="res://Towers/tower.tscn" id="1_yctfx"] [ext_resource type="Texture2D" uid="uid://dwwgho6f8f4kj" path="res://Assets/Icones/penguin.svg" id="2_5uh04"] +[ext_resource type="PackedScene" uid="uid://dp8tg6cpu3ftd" path="res://Projectiles/Scenes/projectile-Evan.tscn" id="3_5uh04"] [sub_resource type="SphereShape3D" id="SphereShape3D_y05yr"] radius = 4.0 @@ -14,7 +15,14 @@ tower_name = "Evan" type = 5 icone = ExtResource("2_5uh04") bio = "" +price = 300 +damage = 1 +projectileScene = ExtResource("3_5uh04") towerRange = SubResource("SphereShape3D_y05yr") +action_cooldown = 3.0 +max_energy = 30.0 +energy_regen = 5.0 +energy_cost = 10.0 [node name="EnergyBar3D" parent="." index="6"] texture = SubResource("ViewportTexture_fegyx") -- 2.45.3 From f8d904c87e69203ca321b232ec49c8dfcfcf4d92 Mon Sep 17 00:00:00 2001 From: Varylios Date: Sun, 21 Sep 2025 13:08:20 +0200 Subject: [PATCH 4/4] feat: add projectile Animmantion & SFX handling --- Assets/Audio/SFX/Test/BadHitSound_coin.ogg | Bin 0 -> 7760 bytes .../SFX/Test/BadHitSound_coin.ogg.import | 19 ++++++ Assets/Audio/SFX/Test/BadHitSound_ktoung.ogg | Bin 0 -> 11023 bytes .../SFX/Test/BadHitSound_ktoung.ogg.import | 19 ++++++ Globals/AudioManager.gd | 11 ++++ Levels/Map 1/level_1.tres | 33 ---------- Projectiles/Draft/ImpactPierre.tscn | 9 +-- Projectiles/Draft/ProjectilePierre.tscn | 58 ----------------- Projectiles/Draft/impact_pierre.gd | 7 -- Projectiles/Draft/impact_pierre.gd.uid | 1 - Projectiles/Draft/projectile_pierre.gd | 10 --- Projectiles/Draft/projectile_pierre.gd.uid | 1 - Projectiles/Projectile.gd | 61 +++++++++++------- Projectiles/Scenes/projectile-Aline.tscn | 11 ++-- Projectiles/Scenes/projectile-James.tscn | 9 +-- Projectiles/Scenes/projectile-Pierre.tscn | 61 +++++++++++++++++- Projectiles/Scenes/projectile-Victoria.tscn | 12 +++- Projectiles/Scenes/projectile-maxence.tscn | 10 ++- Projectiles/projectile.tscn | 8 +-- UI/confirm_popup.tscn | 1 + 20 files changed, 178 insertions(+), 163 deletions(-) create mode 100644 Assets/Audio/SFX/Test/BadHitSound_coin.ogg create mode 100644 Assets/Audio/SFX/Test/BadHitSound_coin.ogg.import create mode 100644 Assets/Audio/SFX/Test/BadHitSound_ktoung.ogg create mode 100644 Assets/Audio/SFX/Test/BadHitSound_ktoung.ogg.import delete mode 100644 Projectiles/Draft/ProjectilePierre.tscn delete mode 100644 Projectiles/Draft/impact_pierre.gd delete mode 100644 Projectiles/Draft/impact_pierre.gd.uid delete mode 100644 Projectiles/Draft/projectile_pierre.gd delete mode 100644 Projectiles/Draft/projectile_pierre.gd.uid diff --git a/Assets/Audio/SFX/Test/BadHitSound_coin.ogg b/Assets/Audio/SFX/Test/BadHitSound_coin.ogg new file mode 100644 index 0000000000000000000000000000000000000000..07bcf8113efc7c40dfcf064e2c4835139d0beae4 GIT binary patch literal 7760 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 literal 0 HcmV?d00001 diff --git a/Assets/Audio/SFX/Test/BadHitSound_ktoung.ogg.import b/Assets/Audio/SFX/Test/BadHitSound_ktoung.ogg.import new file mode 100644 index 0000000..5ad0873 --- /dev/null +++ b/Assets/Audio/SFX/Test/BadHitSound_ktoung.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://bf50ah0ktnriu" +path="res://.godot/imported/BadHitSound_ktoung.ogg-d80938d9e44d3d634fa88c3cc16891ef.oggvorbisstr" + +[deps] + +source_file="res://Assets/Audio/SFX/Test/BadHitSound_ktoung.ogg" +dest_files=["res://.godot/imported/BadHitSound_ktoung.ogg-d80938d9e44d3d634fa88c3cc16891ef.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/Globals/AudioManager.gd b/Globals/AudioManager.gd index 61510e1..1c8678b 100644 --- a/Globals/AudioManager.gd +++ b/Globals/AudioManager.gd @@ -1 +1,12 @@ extends Node + + +func playSFX3D(stream: AudioStream, position: Vector3) -> void: + var sfx : AudioStreamPlayer3D = AudioStreamPlayer3D.new() + sfx.stream = stream + sfx.bus = "SFX" + add_child(sfx) + sfx.global_position = position + sfx.play() + await sfx.finished + sfx.queue_free() diff --git a/Levels/Map 1/level_1.tres b/Levels/Map 1/level_1.tres index fb2a2f5..f2eed94 100644 --- a/Levels/Map 1/level_1.tres +++ b/Levels/Map 1/level_1.tres @@ -7,10 +7,7 @@ [sub_resource type="Resource" id="Resource_87wss"] script = ExtResource("3_ub8wd") enemy = "res://Enemies/Scenes/enemy-a.tscn" -number_to_spawn = 1 -lane_to_spawn = 0 spawn_delay = 2.0 -pack_delay = 0.15 metadata/_custom_type_script = "uid://blxx3vs2wnfet" [sub_resource type="Resource" id="Resource_457yt"] @@ -22,23 +19,17 @@ metadata/_custom_type_script = "uid://chu8s12rtdeqx" script = ExtResource("3_ub8wd") enemy = "uid://1kwye5yjf40d" number_to_spawn = 2 -lane_to_spawn = 0 -spawn_delay = 1.0 -pack_delay = 0.15 [sub_resource type="Resource" id="Resource_ftl6b"] script = ExtResource("3_ub8wd") enemy = "uid://1kwye5yjf40d" number_to_spawn = 2 -lane_to_spawn = 0 spawn_delay = 2.0 -pack_delay = 0.15 [sub_resource type="Resource" id="Resource_e6yyc"] script = ExtResource("3_ub8wd") enemy = "uid://1kwye5yjf40d" number_to_spawn = 5 -lane_to_spawn = 0 spawn_delay = 10.0 pack_delay = 0.5 @@ -49,10 +40,6 @@ troops = Array[ExtResource("3_ub8wd")]([SubResource("Resource_qfjse"), SubResour [sub_resource type="Resource" id="Resource_fhv1k"] script = ExtResource("3_ub8wd") enemy = "uid://r6tj7jprdqib" -number_to_spawn = 1 -lane_to_spawn = 0 -spawn_delay = 1.0 -pack_delay = 0.15 [sub_resource type="Resource" id="Resource_46oi2"] script = ExtResource("2_457yt") @@ -61,16 +48,11 @@ troops = Array[ExtResource("3_ub8wd")]([SubResource("Resource_fhv1k"), SubResour [sub_resource type="Resource" id="Resource_7vcps"] script = ExtResource("3_ub8wd") enemy = "uid://koikfh03qv7" -number_to_spawn = 1 -lane_to_spawn = 0 -spawn_delay = 1.0 -pack_delay = 0.15 [sub_resource type="Resource" id="Resource_3kmde"] script = ExtResource("3_ub8wd") enemy = "uid://koikfh03qv7" number_to_spawn = 3 -lane_to_spawn = 0 spawn_delay = 5.0 pack_delay = 0.3 @@ -78,7 +60,6 @@ pack_delay = 0.3 script = ExtResource("3_ub8wd") enemy = "uid://1kwye5yjf40d" number_to_spawn = 5 -lane_to_spawn = 0 spawn_delay = 10.0 pack_delay = 0.4 @@ -86,15 +67,11 @@ pack_delay = 0.4 script = ExtResource("3_ub8wd") enemy = "uid://r6tj7jprdqib" number_to_spawn = 3 -lane_to_spawn = 0 -spawn_delay = 1.0 -pack_delay = 0.15 [sub_resource type="Resource" id="Resource_q3d8d"] script = ExtResource("3_ub8wd") enemy = "uid://1kwye5yjf40d" number_to_spawn = 10 -lane_to_spawn = 0 spawn_delay = 2.0 pack_delay = 0.3 @@ -102,8 +79,6 @@ pack_delay = 0.3 script = ExtResource("3_ub8wd") enemy = "uid://koikfh03qv7" number_to_spawn = 4 -lane_to_spawn = 0 -spawn_delay = 1.0 pack_delay = 0.5 [sub_resource type="Resource" id="Resource_p2jl5"] @@ -113,10 +88,6 @@ troops = Array[ExtResource("3_ub8wd")]([SubResource("Resource_7vcps"), SubResour [sub_resource type="Resource" id="Resource_1nx3f"] script = ExtResource("3_ub8wd") enemy = "uid://dyl4wiga2goi" -number_to_spawn = 1 -lane_to_spawn = 0 -spawn_delay = 1.0 -pack_delay = 0.15 [sub_resource type="Resource" id="Resource_0nx55"] script = ExtResource("2_457yt") @@ -124,11 +95,7 @@ troops = Array[ExtResource("3_ub8wd")]([SubResource("Resource_1nx3f")]) [resource] script = ExtResource("1_ftl6b") -auto_start = false -auto_launch_wave = false -tier_max = 1 allowedTowers = Array[int]([1, 2, 3]) -laneCount = 1 startingMoney = 110 waves = Array[ExtResource("2_457yt")]([SubResource("Resource_457yt"), SubResource("Resource_qeljc"), SubResource("Resource_46oi2"), SubResource("Resource_p2jl5"), SubResource("Resource_0nx55")]) metadata/_custom_type_script = "uid://cuhq6u67cbbqm" diff --git a/Projectiles/Draft/ImpactPierre.tscn b/Projectiles/Draft/ImpactPierre.tscn index 75a9404..03d710f 100644 --- a/Projectiles/Draft/ImpactPierre.tscn +++ b/Projectiles/Draft/ImpactPierre.tscn @@ -1,7 +1,6 @@ -[gd_scene load_steps=10 format=3 uid="uid://c5rx5scnkh3fb"] +[gd_scene load_steps=9 format=3 uid="uid://c5rx5scnkh3fb"] [ext_resource type="Texture2D" uid="uid://dqyhhvxpwtpsy" path="res://Assets/Emotes/emote_star.png" id="1_3pqxv"] -[ext_resource type="Script" uid="uid://6xiqssgmiurt" path="res://Projectiles/Draft/impact_pierre.gd" id="2_ymm3v"] [sub_resource type="Curve" id="Curve_ymm3v"] _data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(0.499044, 1), 0.0, 0.0, 0, 0, Vector2(0.745698, 0.50142), -0.0206361, -0.0206361, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0] @@ -43,9 +42,3 @@ one_shot = true explosiveness = 1.0 process_material = SubResource("ParticleProcessMaterial_jk26u") draw_pass_1 = SubResource("QuadMesh_qw7ty") -script = ExtResource("2_ymm3v") - -[node name="SFXImpact" type="AudioStreamPlayer3D" parent="."] -bus = &"SFX" - -[connection signal="finished" from="." to="." method="_on_finished"] diff --git a/Projectiles/Draft/ProjectilePierre.tscn b/Projectiles/Draft/ProjectilePierre.tscn deleted file mode 100644 index 2233c95..0000000 --- a/Projectiles/Draft/ProjectilePierre.tscn +++ /dev/null @@ -1,58 +0,0 @@ -[gd_scene load_steps=8 format=3 uid="uid://dsv2untvmg8q"] - -[ext_resource type="Texture2D" uid="uid://dqyhhvxpwtpsy" path="res://Assets/Emotes/emote_star.png" id="1_lcll5"] -[ext_resource type="Script" uid="uid://bpy86kcsjgx0e" path="res://Projectiles/Draft/projectile_pierre.gd" id="2_i2vf7"] - -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_qaid5"] -transparency = 1 -shading_mode = 0 -vertex_color_use_as_albedo = true -albedo_texture = ExtResource("1_lcll5") -billboard_mode = 3 -particles_anim_h_frames = 1 -particles_anim_v_frames = 1 -particles_anim_loop = false - -[sub_resource type="QuadMesh" id="QuadMesh_nkvug"] -material = SubResource("StandardMaterial3D_qaid5") -size = Vector2(0.2, 0.2) - -[sub_resource type="Curve" id="Curve_lcll5"] -_data = [Vector2(0, 0), 0.0, 0.0, 0, 0, Vector2(0.509769, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0] -point_count = 3 - -[sub_resource type="Gradient" id="Gradient_i2vf7"] -offsets = PackedFloat32Array(0, 0.379888, 1) -colors = PackedColorArray(0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0) - -[sub_resource type="Gradient" id="Gradient_nlum7"] -colors = PackedColorArray(1, 1, 1, 1, 1, 1, 1, 1) - -[node name="ProjectilePierre" type="Sprite3D"] -billboard = 2 -texture = ExtResource("1_lcll5") -script = ExtResource("2_i2vf7") - -[node name="CPUParticles3D" type="CPUParticles3D" parent="."] -amount = 16 -lifetime = 0.5 -explosiveness = 0.2 -mesh = SubResource("QuadMesh_nkvug") -emission_shape = 6 -emission_ring_axis = Vector3(0, 0, 1) -emission_ring_height = 0.0 -emission_ring_radius = 0.3 -emission_ring_inner_radius = 0.0 -emission_ring_cone_angle = 90.0 -direction = Vector3(0, 0, 0) -spread = 0.0 -gravity = Vector3(0, 0, 0) -angular_velocity_min = 180.0 -angular_velocity_max = 360.0 -scale_amount_min = 0.0 -scale_amount_curve = SubResource("Curve_lcll5") -color_ramp = SubResource("Gradient_i2vf7") -color_initial_ramp = SubResource("Gradient_nlum7") - -[node name="SFXCreate" type="AudioStreamPlayer3D" parent="."] -bus = &"SFX" diff --git a/Projectiles/Draft/impact_pierre.gd b/Projectiles/Draft/impact_pierre.gd deleted file mode 100644 index 66a9747..0000000 --- a/Projectiles/Draft/impact_pierre.gd +++ /dev/null @@ -1,7 +0,0 @@ -extends GPUParticles3D - -func _ready() -> void: - $SFXImpact.play() - -func _on_finished() -> void: - queue_free() diff --git a/Projectiles/Draft/impact_pierre.gd.uid b/Projectiles/Draft/impact_pierre.gd.uid deleted file mode 100644 index 9bcb9e0..0000000 --- a/Projectiles/Draft/impact_pierre.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://6xiqssgmiurt diff --git a/Projectiles/Draft/projectile_pierre.gd b/Projectiles/Draft/projectile_pierre.gd deleted file mode 100644 index aed4ca1..0000000 --- a/Projectiles/Draft/projectile_pierre.gd +++ /dev/null @@ -1,10 +0,0 @@ -extends Sprite3D - -var impact : GPUParticles3D = preload("uid://c5rx5scnkh3fb").instantiate() - -func _ready() -> void: - $SFXCreate.play() - -func on_impact() -> void: - get_tree().root.add_child(impact) - queue_free() diff --git a/Projectiles/Draft/projectile_pierre.gd.uid b/Projectiles/Draft/projectile_pierre.gd.uid deleted file mode 100644 index 3533719..0000000 --- a/Projectiles/Draft/projectile_pierre.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://bpy86kcsjgx0e diff --git a/Projectiles/Projectile.gd b/Projectiles/Projectile.gd index 6776d15..5cb4278 100644 --- a/Projectiles/Projectile.gd +++ b/Projectiles/Projectile.gd @@ -2,8 +2,7 @@ extends CharacterBody3D class_name Projectile -enum State { INIT, TRAVEL, EFFECT, DESPAWN } - +enum State { INIT, TRAVEL, IMPACT, EFFECT, DESPAWN } enum Mode { FOLLOW, ## Follow target @@ -12,7 +11,6 @@ enum Mode { HITSCAN, ## Spawn on target location } - enum Effect { ONE_HIT, ## Make damage on hit ## Make damage every tick for specified duration[br] @@ -42,6 +40,11 @@ enum Type { ## Types of projectiles @export var dotTicks : int @export var tickInterval : float ## +@export_group("Sounds - Animations") +@export var impactScene : PackedScene +@export var shootSFX : AudioStream +@export var impactSFX : AudioStream + var state : State = State.INIT var amount : float var target : PhysicsBody3D @@ -60,33 +63,33 @@ func _ready() -> void: func _physics_process(_delta: float) -> void: if state == State.INIT: + if shootSFX: + AudioManager.playSFX3D(shootSFX, global_position) state = State.TRAVEL return match state: State.TRAVEL when isOnTarget(): - state = State.EFFECT - applyEffects() + state = State.IMPACT return + State.TRAVEL: + if mode == Mode.FOLLOW: + var globalPos : Vector3 = target.global_position + globalPos.y += Helper.getHitBoxLocation(target, Helper.POSITION.CENTER) + look_at(globalPos) + velocity = global_position.direction_to(globalPos) * speed + move_and_slide() + State.IMPACT: + state = State.EFFECT + impactAnimations() + applyEffects() State.EFFECT: return State.DESPAWN: queue_free.call_deferred() - return if shouldQueueFree(): state = State.DESPAWN - if state != State.TRAVEL: - return - - if mode == Mode.FOLLOW: - var globalPos : Vector3 = target.global_position - globalPos.y += Helper.getHitBoxLocation(target, Helper.POSITION.CENTER) - look_at(globalPos) - velocity = global_position.direction_to(globalPos) * speed - - move_and_slide() - func shouldQueueFree() -> bool: if !is_instance_valid(target): @@ -97,6 +100,18 @@ func shouldQueueFree() -> bool: return maxTargets == 0 +func impactAnimations() -> void: + if impactSFX: + AudioManager.playSFX3D(impactSFX, global_position) + if impactScene: + var impact : GPUParticles3D = impactScene.instantiate() + impact.finished.connect(impact.queue_free) + get_tree().root.add_child(impact) + impact.emitting = false + impact.one_shot = true + impact.emitting = true + + func isOnTarget() -> bool: match mode: Mode.LOCATION: return vectorTarget.distance_squared_to(global_position) < .4 @@ -109,9 +124,10 @@ func applyEffects() -> void: if not collidingBodies.is_empty() && isOnTarget(): resolveContacts() + if state != State.TRAVEL: + state = State.DESPAWN if effect == Effect.DAMAGE_OVER_TIME: dotTicks -= 1 - state = State.DESPAWN if dotTicks > 0: state = State.EFFECT await get_tree().create_timer(tickInterval).timeout @@ -144,7 +160,7 @@ func chooseNextTarget() -> Node3D: return bodies[0] -func resolveEffect(body : Node3D) -> void: +func resolveEffect(body: Node3D) -> void: if body is GameTile || maxTargets == 0: return @@ -154,15 +170,14 @@ func resolveEffect(body : Node3D) -> void: body.take_damage(amount) if effect == Effect.POISON: - dotTicks -= 1 - while dotTicks > 0 && is_instance_valid(body): - dotTicks -= 1 + var poisonTicks : int = dotTicks - 1 + while poisonTicks > 0 && is_instance_valid(body): + poisonTicks -= 1 await get_tree().create_timer(tickInterval).timeout body.take_damage(amount) affectedTarget.append(body) maxTargets -= 1 - state = State.DESPAWN func shoot(_target: Node3D, globalPos: Vector3) -> void: diff --git a/Projectiles/Scenes/projectile-Aline.tscn b/Projectiles/Scenes/projectile-Aline.tscn index 79ac8fb..8fbd3c5 100644 --- a/Projectiles/Scenes/projectile-Aline.tscn +++ b/Projectiles/Scenes/projectile-Aline.tscn @@ -1,6 +1,7 @@ -[gd_scene load_steps=3 format=3 uid="uid://dcnm6rjht0rew"] +[gd_scene load_steps=4 format=3 uid="uid://dcnm6rjht0rew"] [ext_resource type="PackedScene" uid="uid://oykrff3g74eo" path="res://Projectiles/projectile.tscn" id="1_4tmpc"] +[ext_resource type="Texture2D" uid="uid://dqyhhvxpwtpsy" path="res://Assets/Emotes/emote_star.png" id="2_dl8a6"] [sub_resource type="SphereShape3D" id="SphereShape3D_2ioqj"] radius = 0.3 @@ -11,11 +12,13 @@ type = 1 speed = 3 maxTargets = -1 -[node name="HitBox" parent="." index="2"] +[node name="HitBox" parent="." index="1"] collision_mask = 2 [node name="ProjectileSize" parent="HitBox" index="0"] shape = SubResource("SphereShape3D_2ioqj") -[node name="DamageArea" parent="." index="3"] -collision_mask = 2 +[node name="Sprite3D" type="Sprite3D" parent="." index="3"] +transform = Transform3D(2.5, 0, 0, 0, 2.5, 0, 0, 0, 2.5, 0, 0, 0) +billboard = 2 +texture = ExtResource("2_dl8a6") diff --git a/Projectiles/Scenes/projectile-James.tscn b/Projectiles/Scenes/projectile-James.tscn index 2508618..f1262c5 100644 --- a/Projectiles/Scenes/projectile-James.tscn +++ b/Projectiles/Scenes/projectile-James.tscn @@ -7,12 +7,13 @@ type = 3 speed = 2 -[node name="Sprite3D" parent="." index="1"] +[node name="HitBox" parent="." index="1"] +collision_mask = 4 + +[node name="Sprite3D" type="Sprite3D" parent="." index="3"] transform = Transform3D(1.3, 0, 0, 0, 1.3, 0, 0, 0, 1.3, 0, 0, 0) +billboard = 2 texture = ExtResource("2_ckawd") hframes = 6 vframes = 2 frame = 11 - -[node name="HitBox" parent="." index="2"] -collision_mask = 4 diff --git a/Projectiles/Scenes/projectile-Pierre.tscn b/Projectiles/Scenes/projectile-Pierre.tscn index 26b91e3..38865ea 100644 --- a/Projectiles/Scenes/projectile-Pierre.tscn +++ b/Projectiles/Scenes/projectile-Pierre.tscn @@ -1,9 +1,66 @@ -[gd_scene load_steps=2 format=3 uid="uid://dy755v20lqu7q"] +[gd_scene load_steps=11 format=3 uid="uid://dy755v20lqu7q"] [ext_resource type="PackedScene" uid="uid://oykrff3g74eo" path="res://Projectiles/projectile.tscn" id="1_d01p1"] +[ext_resource type="Texture2D" uid="uid://dqyhhvxpwtpsy" path="res://Assets/Emotes/emote_star.png" id="2_5lxlg"] +[ext_resource type="PackedScene" uid="uid://c5rx5scnkh3fb" path="res://Projectiles/Draft/ImpactPierre.tscn" id="2_s3rfh"] +[ext_resource type="AudioStream" uid="uid://c0qfynrgoynwr" path="res://Assets/Audio/SFX/Test/BadHitSound_coin.ogg" id="4_r8d72"] +[ext_resource type="AudioStream" uid="uid://bf50ah0ktnriu" path="res://Assets/Audio/SFX/Test/BadHitSound_ktoung.ogg" id="4_s3rfh"] + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_qaid5"] +transparency = 1 +shading_mode = 0 +vertex_color_use_as_albedo = true +albedo_texture = ExtResource("2_5lxlg") +billboard_mode = 3 +particles_anim_h_frames = 1 +particles_anim_v_frames = 1 +particles_anim_loop = false + +[sub_resource type="QuadMesh" id="QuadMesh_nkvug"] +material = SubResource("StandardMaterial3D_qaid5") +size = Vector2(0.2, 0.2) + +[sub_resource type="Curve" id="Curve_lcll5"] +_data = [Vector2(0, 0), 0.0, 0.0, 0, 0, Vector2(0.509769, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0] +point_count = 3 + +[sub_resource type="Gradient" id="Gradient_i2vf7"] +offsets = PackedFloat32Array(0, 0.379888, 1) +colors = PackedColorArray(0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0) + +[sub_resource type="Gradient" id="Gradient_nlum7"] +colors = PackedColorArray(1, 1, 1, 1, 1, 1, 1, 1) [node name="Projectile" instance=ExtResource("1_d01p1")] speed = 15 +impactScene = ExtResource("2_s3rfh") +shootSFX = ExtResource("4_r8d72") +impactSFX = ExtResource("4_s3rfh") -[node name="HitBox" parent="." index="2"] +[node name="HitBox" parent="." index="1"] collision_mask = 2 + +[node name="ProjectilePierre" type="Sprite3D" parent="." index="3"] +billboard = 2 +texture = ExtResource("2_5lxlg") + +[node name="CPUParticles3D" type="CPUParticles3D" parent="ProjectilePierre" index="0"] +amount = 16 +lifetime = 0.5 +explosiveness = 0.2 +mesh = SubResource("QuadMesh_nkvug") +emission_shape = 6 +emission_ring_axis = Vector3(0, 0, 1) +emission_ring_height = 0.0 +emission_ring_radius = 0.3 +emission_ring_inner_radius = 0.0 +emission_ring_cone_angle = 90.0 +direction = Vector3(0, 0, 0) +spread = 0.0 +gravity = Vector3(0, 0, 0) +angular_velocity_min = 180.0 +angular_velocity_max = 360.0 +scale_amount_min = 0.0 +scale_amount_curve = SubResource("Curve_lcll5") +color_ramp = SubResource("Gradient_i2vf7") +color_initial_ramp = SubResource("Gradient_nlum7") diff --git a/Projectiles/Scenes/projectile-Victoria.tscn b/Projectiles/Scenes/projectile-Victoria.tscn index ae5e8bc..640511e 100644 --- a/Projectiles/Scenes/projectile-Victoria.tscn +++ b/Projectiles/Scenes/projectile-Victoria.tscn @@ -1,6 +1,7 @@ -[gd_scene load_steps=3 format=3 uid="uid://df8u7dogl4wi0"] +[gd_scene load_steps=4 format=3 uid="uid://df8u7dogl4wi0"] [ext_resource type="PackedScene" uid="uid://oykrff3g74eo" path="res://Projectiles/projectile.tscn" id="1_suva6"] +[ext_resource type="Texture2D" uid="uid://dqyhhvxpwtpsy" path="res://Assets/Emotes/emote_star.png" id="2_4juxc"] [sub_resource type="SphereShape3D" id="SphereShape3D_878kj"] @@ -9,11 +10,16 @@ type = 2 speed = 5 maxTargets = 3 -[node name="HitBox" parent="." index="2"] +[node name="HitBox" parent="." index="1"] collision_mask = 2 -[node name="EffectArea" parent="." index="3"] +[node name="EffectArea" parent="." index="2"] collision_mask = 2 [node name="CollisionShape3D" type="CollisionShape3D" parent="EffectArea" index="0"] shape = SubResource("SphereShape3D_878kj") + +[node name="Sprite3D" type="Sprite3D" parent="." index="3"] +transform = Transform3D(2.5, 0, 0, 0, 2.5, 0, 0, 0, 2.5, 0, 0, 0) +billboard = 2 +texture = ExtResource("2_4juxc") diff --git a/Projectiles/Scenes/projectile-maxence.tscn b/Projectiles/Scenes/projectile-maxence.tscn index d6141d2..7ffc9b5 100644 --- a/Projectiles/Scenes/projectile-maxence.tscn +++ b/Projectiles/Scenes/projectile-maxence.tscn @@ -1,6 +1,7 @@ -[gd_scene load_steps=3 format=3 uid="uid://baixm8pfsdo3t"] +[gd_scene load_steps=4 format=3 uid="uid://baixm8pfsdo3t"] [ext_resource type="PackedScene" uid="uid://oykrff3g74eo" path="res://Projectiles/projectile.tscn" id="1_a1h27"] +[ext_resource type="Texture2D" uid="uid://dqyhhvxpwtpsy" path="res://Assets/Emotes/emote_star.png" id="2_lwnvl"] [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_a1h27"] radius = 0.1 @@ -11,9 +12,14 @@ mode = 3 type = 1 maxTargets = 5 -[node name="HitBox" parent="." index="2"] +[node name="HitBox" parent="." index="1"] collision_mask = 2 [node name="ProjectileSize" parent="HitBox" index="0"] transform = Transform3D(1, 0, 0, 0, -4.371139e-08, -1, 0, 1, -4.371139e-08, 0, 0, -5) shape = SubResource("CapsuleShape3D_a1h27") + +[node name="Sprite3D" type="Sprite3D" parent="." index="3"] +transform = Transform3D(2.5, 0, 0, 0, 2.5, 0, 0, 0, 2.5, 0, 0, 0) +billboard = 2 +texture = ExtResource("2_lwnvl") diff --git a/Projectiles/projectile.tscn b/Projectiles/projectile.tscn index 89f3037..9cb5090 100644 --- a/Projectiles/projectile.tscn +++ b/Projectiles/projectile.tscn @@ -1,7 +1,6 @@ -[gd_scene load_steps=5 format=3 uid="uid://oykrff3g74eo"] +[gd_scene load_steps=4 format=3 uid="uid://oykrff3g74eo"] [ext_resource type="Script" uid="uid://b788twwo1o6l2" path="res://Projectiles/Projectile.gd" id="1_ggq0q"] -[ext_resource type="Texture2D" uid="uid://dqyhhvxpwtpsy" path="res://Assets/Emotes/emote_star.png" id="2_08w86"] [sub_resource type="SphereShape3D" id="SphereShape3D_r5o86"] radius = 0.1 @@ -17,11 +16,6 @@ script = ExtResource("1_ggq0q") [node name="CollisionShape3D" type="CollisionShape3D" parent="."] shape = SubResource("SphereShape3D_r5o86") -[node name="Sprite3D" type="Sprite3D" parent="."] -transform = Transform3D(2.5, 0, 0, 0, 2.5, 0, 0, 0, 2.5, 0, 0, 0) -billboard = 2 -texture = ExtResource("2_08w86") - [node name="HitBox" type="Area3D" parent="."] collision_layer = 0 collision_mask = 0 diff --git a/UI/confirm_popup.tscn b/UI/confirm_popup.tscn index 9d66c21..8c956e7 100644 --- a/UI/confirm_popup.tscn +++ b/UI/confirm_popup.tscn @@ -4,6 +4,7 @@ [ext_resource type="Theme" uid="uid://bbp4qcbwkeg7x" path="res://default_theme.tres" id="1_x7bkm"] [node name="Panel" type="PanelContainer"] +process_mode = 3 anchors_preset = 8 anchor_left = 0.5 anchor_top = 0.5 -- 2.45.3