Better status effects
This commit is contained in:
@@ -3,8 +3,8 @@ extends Node
|
||||
|
||||
@export var damage: float = 0.25
|
||||
@export var area2d: Area2D
|
||||
@export var is_fire_brick: bool = false
|
||||
@export var is_ice_brick: bool = false
|
||||
@export var status_effect_data: StatusEffectDataResource
|
||||
signal effect_inflicted(target: Node2D, effect: StatusEffectDataResource)
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
@@ -23,18 +23,12 @@ func on_area2d_body_entered(body: Node2D) -> void:
|
||||
if body.has_node("HealthComponent"):
|
||||
var health_component: HealthComponent = body.get_node("HealthComponent")
|
||||
var invulnerability_component: InvulnerabilityComponent = body.get_node_or_null("InvulnerabilityComponent")
|
||||
var fire_effect_component: FireEffectComponent = body.get_node_or_null("FireEffectComponent")
|
||||
var ice_effect_component: IceEffectComponent = body.get_node_or_null("IceEffectComponent")
|
||||
|
||||
if invulnerability_component and invulnerability_component.is_invulnerable():
|
||||
return
|
||||
|
||||
if fire_effect_component and is_fire_brick:
|
||||
fire_effect_component.activate()
|
||||
return
|
||||
|
||||
if ice_effect_component and is_ice_brick:
|
||||
ice_effect_component.activate()
|
||||
if status_effect_data.effect_type != StatusEffectComponent.EffectType.NONE:
|
||||
effect_inflicted.emit(body, status_effect_data)
|
||||
return
|
||||
|
||||
deal_damage(health_component)
|
22
scripts/components/effect_inflictor_component.gd
Normal file
22
scripts/components/effect_inflictor_component.gd
Normal file
@@ -0,0 +1,22 @@
|
||||
class_name EffectInflictorComponent
|
||||
extends Node
|
||||
|
||||
@export var damage: DamageComponent
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
if not damage:
|
||||
printerr("No damage component assigned!")
|
||||
return
|
||||
|
||||
damage.effect_inflicted.connect(on_effect_inflicted)
|
||||
|
||||
|
||||
func on_effect_inflicted(target: Node2D, effect: StatusEffectDataResource) -> void:
|
||||
var status_effect_component: StatusEffectComponent = target.get_node_or_null("StatusEffectComponent")
|
||||
if not status_effect_component:
|
||||
return
|
||||
|
||||
status_effect_component.apply_effect(effect)
|
||||
|
||||
|
@@ -1,56 +1,49 @@
|
||||
class_name FireEffectComponent
|
||||
extends Node
|
||||
|
||||
@export var duration: float = 1.0
|
||||
@export var damage_per_second: float = 1.0
|
||||
@export var health_component: HealthComponent
|
||||
@export var status_effect_component: StatusEffectComponent
|
||||
@export var root: Node2D
|
||||
|
||||
var timer: Timer
|
||||
var should_deal_damage: bool = false
|
||||
var time_elapsed: float = 0.0
|
||||
var data: StatusEffectDataResource = null
|
||||
var should_deal_damage: bool = false
|
||||
var time_elapsed: float = 0.0
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
if not health_component:
|
||||
health_component = root.get_node("HealthComponent")
|
||||
if not status_effect_component:
|
||||
status_effect_component = root.get_node("StatusEffectComponent")
|
||||
|
||||
if not health_component:
|
||||
printerr("No HealthComponent assigned!")
|
||||
return
|
||||
if not status_effect_component:
|
||||
printerr("No StatusEffectComponent assigned!")
|
||||
return
|
||||
|
||||
timer = Timer.new()
|
||||
timer.timeout.connect(on_timer_timeout)
|
||||
prepare_timer()
|
||||
add_child(timer)
|
||||
status_effect_component.effect_applied.connect(on_effect_applied)
|
||||
status_effect_component.effect_removed.connect(on_effect_removed)
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if not should_deal_damage or not health_component:
|
||||
if not should_deal_damage or not health_component or not data:
|
||||
return
|
||||
|
||||
time_elapsed += delta
|
||||
if time_elapsed >= 1.0:
|
||||
health_component.decrease_health(damage_per_second)
|
||||
health_component.decrease_health(data.damage_per_second)
|
||||
time_elapsed = 0.0
|
||||
|
||||
|
||||
func on_timer_timeout() -> void:
|
||||
deactivate()
|
||||
func on_effect_applied(effect_data: StatusEffectDataResource) -> void:
|
||||
if effect_data.effect_type == StatusEffectComponent.EffectType.FIRE:
|
||||
data = effect_data
|
||||
should_deal_damage = true
|
||||
|
||||
|
||||
func activate() -> void:
|
||||
should_deal_damage = true
|
||||
timer.start()
|
||||
|
||||
|
||||
func deactivate() -> void:
|
||||
should_deal_damage = false
|
||||
timer.stop()
|
||||
|
||||
|
||||
func prepare_timer() -> void:
|
||||
timer.set_wait_time(duration)
|
||||
timer.set_one_shot(true)
|
||||
timer.stop()
|
||||
time_elapsed = 0.0
|
||||
func on_effect_removed(effect_type: StatusEffectComponent.EffectType) -> void:
|
||||
if effect_type == StatusEffectComponent.EffectType.FIRE:
|
||||
data = null
|
||||
should_deal_damage = false
|
||||
|
@@ -1,52 +1,49 @@
|
||||
class_name IceEffectComponent
|
||||
extends Node
|
||||
|
||||
@export var duration: float = 1.0
|
||||
@export var side_to_side_movement: SideToSideMovement
|
||||
@export var periodic_shooting: PeriodicShootingComponent
|
||||
@export var components_to_disable: Array = []
|
||||
@export var status_effect_component: StatusEffectComponent
|
||||
|
||||
var timer: Timer
|
||||
var is_frozen: bool = false
|
||||
var movement_speed: float = 0.0
|
||||
var data: StatusEffectDataResource = null
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
timer = Timer.new()
|
||||
timer.timeout.connect(on_timer_timeout)
|
||||
prepare_timer()
|
||||
add_child(timer)
|
||||
if not status_effect_component:
|
||||
status_effect_component = get_node("StatusEffectComponent")
|
||||
|
||||
if side_to_side_movement:
|
||||
movement_speed = side_to_side_movement.speed
|
||||
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
if not side_to_side_movement or not periodic_shooting:
|
||||
if not status_effect_component:
|
||||
printerr("No StatusEffectComponent assigned!")
|
||||
return
|
||||
|
||||
if is_frozen:
|
||||
side_to_side_movement.process_mode = PROCESS_MODE_DISABLED
|
||||
periodic_shooting.process_mode = PROCESS_MODE_DISABLED
|
||||
else:
|
||||
side_to_side_movement.process_mode = PROCESS_MODE_ALWAYS
|
||||
periodic_shooting.process_mode = PROCESS_MODE_ALWAYS
|
||||
status_effect_component.effect_applied.connect(on_effect_applied)
|
||||
status_effect_component.effect_removed.connect(on_effect_removed)
|
||||
|
||||
|
||||
func on_timer_timeout() -> void:
|
||||
deactivate()
|
||||
func on_effect_applied(effect_data: StatusEffectDataResource) -> void:
|
||||
if effect_data.effect_type == StatusEffectComponent.EffectType.ICE:
|
||||
data = effect_data
|
||||
apply_freeze()
|
||||
|
||||
|
||||
func activate() -> void:
|
||||
is_frozen = true
|
||||
timer.start()
|
||||
func on_effect_removed(effect_type: StatusEffectComponent.EffectType) -> void:
|
||||
if effect_type == StatusEffectComponent.EffectType.ICE:
|
||||
data = null
|
||||
remove_freeze()
|
||||
|
||||
|
||||
func deactivate() -> void:
|
||||
is_frozen = false
|
||||
timer.stop()
|
||||
func apply_freeze() -> void:
|
||||
for component_path in components_to_disable:
|
||||
var component: Node = get_node_or_null(component_path)
|
||||
if not component:
|
||||
continue
|
||||
|
||||
component.process_mode = PROCESS_MODE_DISABLED
|
||||
|
||||
|
||||
func prepare_timer() -> void:
|
||||
timer.set_wait_time(duration)
|
||||
timer.set_one_shot(true)
|
||||
timer.stop()
|
||||
func remove_freeze() -> void:
|
||||
for component_path in components_to_disable:
|
||||
var component: Node = get_node_or_null(component_path)
|
||||
if not component:
|
||||
continue
|
||||
|
||||
component.process_mode = PROCESS_MODE_ALWAYS
|
46
scripts/components/status_effect_component.gd
Normal file
46
scripts/components/status_effect_component.gd
Normal file
@@ -0,0 +1,46 @@
|
||||
class_name StatusEffectComponent
|
||||
extends Node
|
||||
|
||||
enum EffectType {
|
||||
NONE,
|
||||
FIRE,
|
||||
ICE
|
||||
}
|
||||
var active_effect: StatusEffectDataResource = null
|
||||
var timer: Timer
|
||||
var is_active: bool = false
|
||||
var time_elapsed: float = 0.0
|
||||
signal effect_applied(effect_data: StatusEffectDataResource)
|
||||
signal effect_removed(effect_type: EffectType)
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
timer = Timer.new()
|
||||
timer.timeout.connect(on_timer_timeout)
|
||||
add_child(timer)
|
||||
|
||||
|
||||
func apply_effect(effect_data: StatusEffectDataResource) -> void:
|
||||
if is_active:
|
||||
return
|
||||
|
||||
is_active = true
|
||||
active_effect = effect_data
|
||||
prepare_timer()
|
||||
effect_applied.emit(active_effect)
|
||||
timer.start()
|
||||
|
||||
|
||||
func remove_effect() -> void:
|
||||
is_active = false
|
||||
effect_removed.emit(active_effect.effect_type)
|
||||
|
||||
|
||||
func on_timer_timeout() -> void:
|
||||
remove_effect()
|
||||
|
||||
|
||||
func prepare_timer() -> void:
|
||||
timer.set_wait_time(active_effect.duration)
|
||||
timer.set_one_shot(true)
|
||||
timer.stop()
|
@@ -1,4 +1,4 @@
|
||||
class_name StompDamageComponent
|
||||
class_name StompDamageComponent
|
||||
extends Node
|
||||
|
||||
@export var damage: float = 0.25
|
||||
@@ -44,4 +44,4 @@ func on_area2d_body_entered(body: Node2D) -> void:
|
||||
damage_component.set_process(false)
|
||||
await get_tree().process_frame
|
||||
damage_component.set_process(true)
|
||||
|
||||
|
||||
|
6
scripts/resources/status_effect_data_resource.gd
Normal file
6
scripts/resources/status_effect_data_resource.gd
Normal file
@@ -0,0 +1,6 @@
|
||||
class_name StatusEffectDataResource
|
||||
extends Resource
|
||||
|
||||
@export var effect_type: StatusEffectComponent.EffectType = StatusEffectComponent.EffectType.NONE
|
||||
@export var duration: float = 1.0
|
||||
@export var damage_per_second: float = 0.25
|
Reference in New Issue
Block a user