#* #* select_flanking_pos.gd #* ============================================================================= #* Copyright (c) 2023-present Serhii Snitsaruk and the LimboAI contributors. #* #* Use of this source code is governed by an MIT-style #* license that can be found in the LICENSE file or at #* https://opensource.org/licenses/MIT. #* ============================================================================= #* @tool extends BTAction ## Selects a position on the target's side and stores it on the ## blackboard, returning [code]SUCCESS[/code]. [br] ## Returns [code]FAILURE[/code] if the target is not valid. enum AgentSide { CLOSEST, FARTHEST, BACK, FRONT, } ## Blackboard variable that holds current target (should be a Node2D instance). @export var target_var: StringName = &"target" ## Which agent's side should we flank? @export var flank_side: AgentSide = AgentSide.CLOSEST ## Minimum range relative to the target. @export var range_min: int = 300 ## Maximum range relative to the target. @export var range_max: int = 400 ## Blackboard variable that will be used to store selected position. @export var position_var: StringName = &"pos" # Display a customized name (requires @tool). func _generate_name() -> String: return "SelectFlankingPos target: %s range: [%s, %s] side: %s ➜%s" % [ LimboUtility.decorate_var(target_var), range_min, range_max, AgentSide.keys()[flank_side], LimboUtility.decorate_var(position_var)] # Called each time this task is ticked (aka executed). func _tick(_delta: float) -> Status: var target := blackboard.get_var(target_var) as Node2D if not is_instance_valid(target): return FAILURE var dir: float # 1.0 is right, -1.0 is left (relative to target) match flank_side: AgentSide.FARTHEST: dir = signf(target.global_position.x - agent.global_position.x) AgentSide.CLOSEST : dir = -signf(target.global_position.x - agent.global_position.x) AgentSide.BACK: dir = -target.get_facing() AgentSide.FRONT: dir = target.get_facing() var flank_pos: Vector2 var offset := Vector2(dir * randf_range(range_min, range_max), 0.0) flank_pos = target.global_position + offset if not agent.is_good_position(flank_pos): # Choose the opposite side if the preferred side is not good (i.e., inside a collision shape). flank_pos = target.global_position - offset blackboard.set_var(position_var, flank_pos) return SUCCESS