class_name EffectInstance extends RefCounted var definition: Resource var remaining := 0.0 var stacks := 1 var source: Variant = &"-" static func create(next_definition: Resource, next_source: Variant = &"-") -> RefCounted: var script: Script = load("res://resources/effects/effect_instance.gd") var instance: RefCounted = script.new() instance.definition = next_definition instance.remaining = float(next_definition.get("duration")) if StringName(str(next_definition.get("duration_type"))) == &"until_event": instance.remaining = 1.0 instance.source = next_source return instance func is_expired() -> bool: return remaining <= 0.0 and StringName(str(definition.get("duration_type"))) != &"infinite" func tick_time(delta: float) -> void: var duration_type := StringName(str(definition.get("duration_type"))) if duration_type == &"seconds": remaining -= delta func tick_beats(beats: float) -> void: var duration_type := StringName(str(definition.get("duration_type"))) if duration_type == &"beats": remaining -= beats func tick_event(event_name: StringName, context: Dictionary = {}) -> void: if not matches_event_context(context): return var duration_type := StringName(str(definition.get("duration_type"))) if duration_type == &"actions" and event_name == &"on_action_start": remaining -= 1.0 elif duration_type == &"hits" and event_name == &"on_hit": remaining -= 1.0 elif duration_type == &"hurts" and event_name == &"on_hurt": remaining -= 1.0 elif duration_type == &"measures" and event_name == &"on_measure_start": remaining -= 1.0 elif duration_type == &"until_event" and event_name == StringName(str(definition.get("until_event"))): remaining = 0.0 func matches_event_context(context: Dictionary = {}) -> bool: var action_tags := _event_action_tags(context) var required_tags := _string_name_array(definition.get("required_event_action_tags")) if not required_tags.is_empty() and not _has_any(action_tags, required_tags): return false var blocked_tags := _string_name_array(definition.get("blocked_event_action_tags")) if not blocked_tags.is_empty() and _has_any(action_tags, blocked_tags): return false return true func _event_action_tags(context: Dictionary) -> Array[StringName]: if context.has("action_tags"): return _string_name_array(context["action_tags"]) var action: Resource = context.get("action", null) as Resource if action != null: return _string_name_array(action.get("action_tags")) var result = context.get("result", {}) if result is Dictionary: if result.has("action_tags"): return _string_name_array(result["action_tags"]) var result_action: Resource = result.get("action", null) as Resource if result_action != null: return _string_name_array(result_action.get("action_tags")) return [] func _string_name_array(value: Variant) -> Array[StringName]: var result: Array[StringName] = [] if value is Array: for item: Variant in value: result.append(StringName(str(item))) return result func _has_any(values: Array[StringName], candidates: Array[StringName]) -> bool: for value: StringName in values: if candidates.has(value): return true return false