oh man i fixed that status effect bug

This commit is contained in:
2025-06-07 09:11:13 +10:00
parent c44a730b59
commit 400415f8a5
40 changed files with 648 additions and 270 deletions

@ -4,10 +4,16 @@ class_name AreaAffector extends Affector
func apply_effect(effect: Effect, targets: Array[EnemyController]) -> void:
for i: int in shapecast.get_collision_count():
var enemy: EnemyController = shapecast.get_collider(i) as EnemyController
#print(shapecast.get_collider(i))
if targets.has(enemy):
if shapecast:
for i: int in shapecast.get_collision_count():
var enemy: EnemyController = shapecast.get_collider(i) as EnemyController
#print(shapecast.get_collider(i))
if targets.has(enemy):
enemy.apply_effect(effect)
if Data.preferences.display_tower_damage_indicators and effect.damage > 0:
spawn_damage_indicator(effect.damage, enemy.sprite.global_position)
else:
for enemy: EnemyController in targets:
enemy.apply_effect(effect)
if Data.preferences.display_tower_damage_indicators and effect.damage > 0:
spawn_damage_indicator(effect.damage, enemy.sprite.global_position)

48
Scripts/flow_node.gd Normal file

@ -0,0 +1,48 @@
class_name FlowNode extends StaticBody3D
var connections: Array[FlowNode]
var visualisers: Array[CSGBox3D]
var traversable: bool = true
var best_path: FlowNode :
get():
return best_path
set(value):
set_connector_color(best_path, Color.DARK_GRAY)
best_path = value
set_connector_color(best_path, Color.DARK_GREEN)
func _process(delta: float) -> void:
for i: int in connections.size():
var distance: float = global_position.distance_to(connections[i].global_position)
visualisers[i].size = Vector3(0.3, 0.3, 1.0 * (distance / 2.0))
visualisers[i].position = to_local(connections[i].global_position) / 4.0
if distance >= 0.05:
visualisers[i].look_at(connections[i].global_position)
func set_color(new_color: Color) -> void:
$CSGSphere3D.material.albedo_color = new_color
func set_connector_color(node: FlowNode, new_color: Color) -> void:
var i: int = connections.find(node)
visualisers[i].material.albedo_color = new_color
func add_connection(node: FlowNode) -> void:
if !connections.has(node):
var visual: CSGBox3D = CSGBox3D.new()
visual.material = StandardMaterial3D.new()
visual.material.resource_local_to_scene = true
visual.material.albedo_color = Color.DARK_GRAY
add_child(visual)
connections.append(node)
visualisers.append(visual)
func remove_connection(node: FlowNode) -> void:
if connections.has(node):
var i: int = connections.find(node)
visualisers.pop_at(i).queue_free()
connections.remove_at(i)

1
Scripts/flow_node.gd.uid Normal file

@ -0,0 +1 @@
uid://c86ygtor5tksd

@ -1,12 +1,12 @@
class_name StatusEffector extends Node3D
class_name StatusEffector extends Node
@export var hbox: HBoxContainer
@export var enemy: EnemyController
@export var sprite_container: Container ## Container that effect icons should be instantiated under
var enemy: EnemyController ## Enemy Controller that this node should affect
var icon_scene: PackedScene = preload("res://Scenes/status_icon.tscn")
var immune: Array[StatusEffect] = []
var effects: Dictionary = {}
var icons: Dictionary = {}
var immunities: Array[StatusEffect] = [] ## The set of status effects that this effector shouldn't apply
var effects: Dictionary[StatusEffect, int] = {}
var icons: Dictionary[StatusEffect, TextureRect] = {}
func _process(delta: float) -> void:
@ -20,7 +20,7 @@ func _process(delta: float) -> void:
effects[effect] -= 1
effect.on_removed(enemy, effects)
if effects[effect] == 0:
icons[effect].set_visible(false)
icons[effect].visible = false
if effect.time_since_proc >= effect.stats.proc_cd:
effect.proc(enemy, effects[effect], effects)
effect.time_since_proc -= effect.stats.proc_cd
@ -33,27 +33,25 @@ func force_proc(effect_to_proc: StatusEffect) -> void:
func add_effect(new_effect: StatusEffect) -> void:
for effect: StatusEffect in immune:
# Return early if this node immune to the new effect
for effect: StatusEffect in immunities:
if effect.stats == new_effect.stats:
return
var existing_effect: StatusEffect
var existing_effect: StatusEffect = null
for effect: StatusEffect in effects:
if effect.stats == new_effect.stats:
existing_effect = effect
if !existing_effect:
existing_effect = new_effect
effects[new_effect] = 0
existing_effect = new_effect.duplicate()
effects[existing_effect] = 0
var icon: TextureRect = icon_scene.instantiate()
icon.texture = new_effect.stats.icon
icon.set_visible(false)
icons[new_effect] = icon
hbox.add_child(icon)
icon.texture = existing_effect.stats.icon
icons[existing_effect] = icon
sprite_container.add_child(icon)
if existing_effect.stats.max_stacks == 0 or effects[existing_effect] < existing_effect.stats.max_stacks:
existing_effect.on_attached(enemy, effects)
icons[existing_effect].set_visible(true)
icons[existing_effect].visible = true
effects[existing_effect] += 1
existing_effect.time_existed = 0.0
if existing_effect.stats.max_stacks != 0 and effects[existing_effect] > existing_effect.stats.max_stacks:
effects[existing_effect] = existing_effect.stats.max_stacks

@ -1,14 +1,29 @@
extends Node
class_name WaveManager extends Object
## A collection of static functions related to enemy wave generation
##
## Contains the algorithm for generating a wave based on a given pool of enemies
## as well as the functions for determining how much powerful a given enemy wave
## should be based on the the number of players and what number wave it is.
##
## Also contains the function for determining how much money is earned after
## completing a wave
## Takes in wave number and number of players and returns a spawn power value
## intended for passing into the generate_wave method
static func calculate_spawn_power(wave_number: int, number_of_players: int) -> int:
return (20 * number_of_players) + (5 * wave_number)
## Takes in wave number and number of players and returns the amount of coins
## that should be divided between each player after completing the wave
static func calculate_pot(wave_number: int, number_of_players: int) -> int:
return ceili((2.5 * number_of_players) + (0.5 * wave_number))
## Uses a spawn power budget to "buy" cards of enemies at random selection from
## the given spawn pool, returns the resulting wave but also assigns the cards
## among the given set of enemy spawners
static func generate_wave(spawn_power: int, spawn_pool: Array[Enemy], spawners: Array[EnemySpawner]) -> Wave:
var wave: Wave = Wave.new()
@ -18,7 +33,7 @@ static func generate_wave(spawn_power: int, spawn_pool: Array[Enemy], spawners:
var new_card: EnemyCard = EnemyCard.new()
#First, choose an enemy at random
new_card.enemy = Data.enemies.pick_random()
new_card.enemy = spawn_pool.pick_random()
#Next, we have to figure out if we can actually buy that enemy
#and, if not, then we have to pick a different enemy, repeat until
@ -45,11 +60,11 @@ static func generate_wave(spawn_power: int, spawn_pool: Array[Enemy], spawners:
else:
#Even the common rarity was too expensive, so we have to choose
#a different enemy and try this process again
var enemy_id: int = Data.enemies.find(new_card.enemy)
var enemy_id: int = spawn_pool.find(new_card.enemy)
if enemy_id <= 0:
new_card.enemy = Data.enemies[Data.enemies.size() - 1]
new_card.enemy = spawn_pool[spawn_pool.size() - 1]
else:
new_card.enemy = Data.enemies[enemy_id - 1]
new_card.enemy = spawn_pool[enemy_id - 1]
#Now that we know which rarities we could afford, lets just choose a
#random one