## BattleContext is the central hub for NBattle. ## It manages all objects, dispatches events, handles ticks, and provides factory methods. ## ## Usage: ## var ctx: BattleContext = BattleContext.new() ## var hp: StatDef = ctx.new_stat_def("hp", 0, 99) ## var str: StatDef = ctx.new_stat_def("str", 0, 99) ## var c1: Combatant = ctx.new_combatant() ## var c2: Combatant = ctx.new_combatant() ## ctx.tick() class_name BattleContext extends RefCounted var _id_counter: int = 0 var _tick: int = 0 var _stat_defs: Dictionary var _effect_defs: Dictionary var _trigger_defs: Dictionary var _combatants: Array var _flags: Dictionary var _flag_counter: int = 1 var _effect_stack: Array var _event_hooks: Array # Array of Callables func _init() -> void: _id_counter = 0 _tick = 0 _stat_defs = {} _effect_defs = {} _trigger_defs = {} _combatants = [] _flags = {} _flag_counter = 1 _effect_stack = [] _event_hooks = [] ## Creates a new stat definition. func new_stat_def(name: String, min_val: int, max_val: int) -> StatDef: var def: StatDef = StatDef.new(self, name, min_val, max_val) _stat_defs[def.get_id()] = def return def ## Creates a new effect definition. Factory should return a new EffectBase instance. func new_effect_def(name: String, factory: Callable) -> EffectDef: var def: EffectDef = EffectDef.new(self, name, factory) _effect_defs[def.get_id()] = def return def ## Creates a new trigger definition. func new_trigger_def(name: String) -> TriggerDef: var def: TriggerDef = TriggerDef.new(self, name) _trigger_defs[def.get_id()] = def return def ## Creates a new combatant (automatically activated). func new_combatant() -> Combatant: var combatant: Combatant = Combatant.new(self) _combatants.append(combatant) return combatant ## Creates a new named flag and returns its bitmask value. func new_flag(name: String) -> int: var flag: int = _flag_counter _flags[name] = flag _flag_counter <<= 1 return flag ## Gets the current tick count. func get_tick() -> int: return _tick ## Advances the tick counter and emits a Tick event. func tick() -> int: _tick += 1 _emit_event(TickEvent.new(_tick)) return _tick ## Emits an event to all hooks and active combatant effects. func emit_event(evt: NBattleEvent) -> void: _emit_event(evt) ## Adds an event hook (Callable that takes an NBattleEvent). func hook_events(hook: Callable) -> void: _event_hooks.append(hook) ## Gets all stat definitions. func get_stat_defs() -> Array: return _stat_defs.values() ## Gets a stat definition by ID. func get_stat_def_by_id(id: int) -> StatDef: return _stat_defs.get(id, null) ## Gets a stat definition by name. func get_stat_def_by_name(name: String) -> StatDef: for def in _stat_defs.values(): if def.get_name() == name: return def return null ## Gets all effect definitions. func get_effect_defs() -> Array: return _effect_defs.values() ## Gets an effect definition by ID. func get_effect_def_by_id(id: int) -> EffectDef: return _effect_defs.get(id, null) ## Gets an effect definition by name. func get_effect_def_by_name(name: String) -> EffectDef: for def in _effect_defs.values(): if def.get_name() == name: return def return null ## Gets all trigger definitions. func get_trigger_defs() -> Array: return _trigger_defs.values() ## Gets a trigger definition by ID. func get_trigger_def_by_id(id: int) -> TriggerDef: return _trigger_defs.get(id, null) ## Gets a trigger definition by name. func get_trigger_def_by_name(name: String) -> TriggerDef: for def in _trigger_defs.values(): if def.get_name() == name: return def return null ## Gets all combatants. func get_combatants() -> Array: return _combatants ## Gets a combatant by ID. func get_combatant_by_id(id: int) -> Combatant: for combatant in _combatants: if combatant.get_id() == id: return combatant return null ## Gets a flag by name. func get_flag_by_name(name: String) -> int: return _flags.get(name, 0) ## Gets all flags. func get_flags() -> Dictionary: return _flags.duplicate() ## Removes a combatant from this context. func remove_combatant(combatant: Combatant) -> void: for i in range(_combatants.size()): if _combatants[i].get_id() == combatant.get_id(): _combatants.remove_at(i) return ## Resolves a variant to an NBattleObject. func get_object(obj: Variant) -> NBattleObject: if obj == null: return null if obj is NBattleObject: return obj if obj is int: return get_object_by_id(obj) if obj is String: return get_object_by_name(obj) push_error("NBattle: Invalid object type in get_object") return null ## Gets any object by ID. func get_object_by_id(id: int) -> NBattleObject: if _stat_defs.has(id): return _stat_defs[id] if _effect_defs.has(id): return _effect_defs[id] if _trigger_defs.has(id): return _trigger_defs[id] for combatant in _combatants: if combatant.get_id() == id: return combatant return null ## Gets any object by name (searches stat_defs, effect_defs, trigger_defs). func get_object_by_name(name: String) -> NBattleObject: var result: NBattleObject = get_stat_def_by_name(name) if result: return result result = get_effect_def_by_name(name) if result: return result result = get_trigger_def_by_name(name) if result: return result return null ## Internal: find the combatant that owns a given stat instance. func _get_combatant_with_stat(stat: Stat) -> Combatant: for combatant in _combatants: for c_stat in combatant.get_stats(): if c_stat == stat: return combatant return null ## Internal: emit event to hooks and combatant effects. func _emit_event(evt: NBattleEvent) -> void: for hook in _event_hooks: hook.call(evt) for combatant in _combatants: combatant.handle_effect_event(evt) ## Internal: push effect onto the stack (prevents recursive calls). func _push_effect_stack(effect: EffectBase) -> void: _effect_stack.append(effect) ## Internal: pop effect from the stack. func _pop_effect_stack(effect: EffectBase) -> void: if _effect_stack.size() > 0 and _effect_stack[-1] == effect: _effect_stack.remove_at(_effect_stack.size() - 1) ## Internal: check if effect is currently on the stack. func _is_effect_in_stack(effect: EffectBase) -> bool: return effect in _effect_stack ## Internal: generate the next unique object ID. func _next_id() -> int: _id_counter += 1 return _id_counter