NPCs can take quests!
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
[gd_scene load_steps=8 format=3 uid="uid://dfa6ep4o53s08"]
|
||||
[gd_scene load_steps=7 format=3 uid="uid://dfa6ep4o53s08"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://cci652umkym1f" path="res://test_scene.gd" id="1_8p2cu"]
|
||||
[ext_resource type="PackedScene" uid="uid://cd08dp16bixfv" path="res://guildhall.tscn" id="1_fcxuj"]
|
||||
@@ -14,10 +14,6 @@ cell_size = 50.0
|
||||
border_size = 250.0
|
||||
agent_radius = 35.0
|
||||
|
||||
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_d0hfk"]
|
||||
radius = 15.0
|
||||
height = 54.0
|
||||
|
||||
[node name="Active Scene" type="Node2D"]
|
||||
script = ExtResource("1_8p2cu")
|
||||
|
||||
@@ -33,21 +29,9 @@ position = Vector2(512, 82)
|
||||
[node name="Queue" parent="Guildhall/Sprites/Receptionist" index="3"]
|
||||
position = Vector2(-99, 189)
|
||||
|
||||
[node name="CollisionShape2D" parent="Guildhall/Sprites/CharacterBody2D" index="0"]
|
||||
shape = SubResource("CapsuleShape2D_d0hfk")
|
||||
|
||||
[node name="Sprite2D" parent="Guildhall/Sprites/CharacterBody2D" index="1"]
|
||||
position = Vector2(0, -43)
|
||||
|
||||
[node name="Quest Board" parent="Guildhall" index="3"]
|
||||
position = Vector2(927, 33)
|
||||
|
||||
[node name="CollisionShape2D" parent="Guildhall/Quest Board" index="1"]
|
||||
position = Vector2(0, -14)
|
||||
|
||||
[node name="Queue" parent="Guildhall/Quest Board" index="2"]
|
||||
position = Vector2(2, 44)
|
||||
|
||||
[node name="VisitorSpawner" type="Node2D" parent="Guildhall"]
|
||||
position = Vector2(505, 870)
|
||||
script = ExtResource("6_d0hfk")
|
||||
@@ -58,6 +42,7 @@ total_visitors = 3
|
||||
[node name="UI" type="CanvasLayer" parent="."]
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="UI"]
|
||||
anchors_preset = -1
|
||||
offset_left = 1567.0
|
||||
offset_top = 23.0
|
||||
offset_right = 1903.0
|
||||
|
||||
@@ -58,6 +58,8 @@ func set_movement_target(target : Vector2) -> void:
|
||||
func show_speech_bubble(bubble_type : String) -> void:
|
||||
bubble.try_show_speech(bubble_type)
|
||||
|
||||
|
||||
|
||||
func _on_nav_agent_finished() -> void:
|
||||
navigation_finished.emit()
|
||||
|
||||
|
||||
@@ -20,3 +20,6 @@ var quest : Quest
|
||||
func assign_quest(quest : Quest) -> void:
|
||||
self.quest = quest
|
||||
quest.initiate(self)
|
||||
|
||||
func full_name() -> String:
|
||||
return given_name + " " + surname
|
||||
|
||||
@@ -12,7 +12,7 @@ enum Phases {
|
||||
ARRIVE,
|
||||
QUEUE,
|
||||
WAIT,
|
||||
SERVICE,
|
||||
INTERACT,
|
||||
COMPLETE
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ func _generate_name() -> String:
|
||||
func _enter() -> void:
|
||||
var eq = Guild.hall.interactables.get(equipment_name)
|
||||
if !eq:
|
||||
printerr("Use Guild Equipment (%s) - %s, '%s' not found!", equipment_name, service_name, equipment_name)
|
||||
printerr("Use Guild Equipment (%s) - %s, '%s' not found!" % [equipment_name, service_name, equipment_name])
|
||||
return
|
||||
equipment = eq
|
||||
queue = equipment.queue
|
||||
@@ -61,11 +61,11 @@ func _tick(delta: float) -> Status:
|
||||
pass
|
||||
Phases.WAIT:
|
||||
pass
|
||||
Phases.SERVICE:
|
||||
Phases.INTERACT:
|
||||
if wait_time_remaining > 0:
|
||||
wait_time_remaining -= delta
|
||||
if wait_time_remaining <= 0:
|
||||
equipment.service_provided.connect(_on_service_complete)
|
||||
equipment.interaction_complete.connect(_on_interaction_complete)
|
||||
equipment.interact(agent, service_name)
|
||||
Phases.COMPLETE:
|
||||
return SUCCESS
|
||||
@@ -81,10 +81,11 @@ func _on_navigation_failed() -> void:
|
||||
wait_time_remaining = randf_range(.5, 2)
|
||||
agent.navigation_finished.disconnect(_on_navigation_complete)
|
||||
|
||||
func use_service():
|
||||
phase = Phases.SERVICE
|
||||
func interact():
|
||||
phase = Phases.INTERACT
|
||||
wait_time_remaining = randf_range(2,5)
|
||||
#TODO: Make them both do the talking emoji
|
||||
equipment.busy = true
|
||||
agent.show_speech_bubble("busy")
|
||||
|
||||
func wait():
|
||||
@@ -98,12 +99,14 @@ func _on_queue_advanced() -> void:
|
||||
if equipment.busy:
|
||||
wait()
|
||||
else:
|
||||
use_service()
|
||||
interact()
|
||||
pass
|
||||
|
||||
func _on_service_complete() -> void:
|
||||
equipment.service_provided.disconnect(_on_service_complete)
|
||||
func _on_interaction_complete() -> void:
|
||||
equipment.interaction_complete.disconnect(_on_interaction_complete)
|
||||
equipment.busy = false
|
||||
agent.show_speech_bubble("")
|
||||
queue.remove_member(agent)
|
||||
phase = Phases.COMPLETE
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
extends BTCondition
|
||||
var invert : bool
|
||||
@export var invert : bool
|
||||
func _tick(delta: float) -> Status:
|
||||
if agent.data and ((agent.data.quest == null) == invert):
|
||||
return SUCCESS
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[gd_resource type="BehaviorTree" load_steps=42 format=3 uid="uid://dght2flegv70i"]
|
||||
[gd_resource type="BehaviorTree" load_steps=43 format=3 uid="uid://dght2flegv70i"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://h113xg55h4r8" path="res://ai/tasks/actions/go_to.gd" id="1_s3kkm"]
|
||||
[ext_resource type="Script" uid="uid://bsq5dxul0uto" path="res://ai/tasks/actions/use_guild_service.gd" id="2_1441p"]
|
||||
@@ -6,6 +6,7 @@
|
||||
[ext_resource type="Script" uid="uid://b2vuw12mttm40" path="res://ai/tasks/decorators/busy.gd" id="2_mtixs"]
|
||||
[ext_resource type="Script" uid="uid://bcbfnm21rtkuo" path="res://ai/tasks/conditions/is_unregistered.gd" id="3_mtixs"]
|
||||
[ext_resource type="Script" uid="uid://xom38ohdwfms" path="res://ai/tasks/conditions/has_quest.gd" id="4_1441p"]
|
||||
[ext_resource type="Script" uid="uid://bhatmue8jr2ab" path="res://ai/tasks/actions/use_guild_equipment.gd" id="7_nqy1p"]
|
||||
|
||||
[sub_resource type="BlackboardPlan" id="BlackboardPlan_6h604"]
|
||||
var/pos/name = &"pos"
|
||||
@@ -77,18 +78,19 @@ activity = "Registering as an adventurer"
|
||||
|
||||
[sub_resource type="BTCondition" id="BTCondition_mtixs"]
|
||||
script = ExtResource("4_1441p")
|
||||
invert = true
|
||||
|
||||
[sub_resource type="BTAction" id="BTAction_fe6jf"]
|
||||
script = ExtResource("2_1441p")
|
||||
employee_name = "Questboard"
|
||||
service_name = "get_quest"
|
||||
[sub_resource type="BTAction" id="BTAction_8lwgx"]
|
||||
script = ExtResource("7_nqy1p")
|
||||
equipment_name = "Quest Board"
|
||||
service_name = "quest"
|
||||
|
||||
[sub_resource type="BTAction" id="BTAction_mwsop"]
|
||||
script = ExtResource("2_fe6jf")
|
||||
|
||||
[sub_resource type="BTSequence" id="BTSequence_nqy1p"]
|
||||
custom_name = "Get a Quest"
|
||||
children = [SubResource("BTCondition_mtixs"), SubResource("BTAction_fe6jf"), SubResource("BTAction_mwsop")]
|
||||
children = [SubResource("BTCondition_mtixs"), SubResource("BTAction_8lwgx"), SubResource("BTAction_mwsop")]
|
||||
|
||||
[sub_resource type="BTDecorator" id="BTDecorator_s18yy"]
|
||||
children = [SubResource("BTSequence_nqy1p")]
|
||||
@@ -120,12 +122,14 @@ custom_name = "Idle"
|
||||
|
||||
[sub_resource type="BTProbability" id="BTProbability_gc1l4"]
|
||||
children = [SubResource("BTWait_8lwgx")]
|
||||
_enabled = false
|
||||
|
||||
[sub_resource type="BTAction" id="BTAction_jq6fo"]
|
||||
script = ExtResource("2_fe6jf")
|
||||
|
||||
[sub_resource type="BTProbability" id="BTProbability_8lwgx"]
|
||||
children = [SubResource("BTAction_jq6fo")]
|
||||
_enabled = false
|
||||
|
||||
[sub_resource type="BTProbabilitySelector" id="BTProbabilitySelector_mtixs"]
|
||||
children = [SubResource("BTProbability_s3kkm"), SubResource("BTProbability_1441p"), SubResource("BTProbability_gc1l4"), SubResource("BTProbability_8lwgx")]
|
||||
|
||||
34
ai/trees/quest_board.tres
Normal file
34
ai/trees/quest_board.tres
Normal file
@@ -0,0 +1,34 @@
|
||||
[gd_resource type="BehaviorTree" load_steps=9 format=3 uid="uid://tr5enbq48w6x"]
|
||||
|
||||
[sub_resource type="BlackboardPlan" id="BlackboardPlan_7h63t"]
|
||||
|
||||
[sub_resource type="BBVariant" id="BBVariant_7h63t"]
|
||||
type = 1
|
||||
saved_value = false
|
||||
resource_name = "false"
|
||||
|
||||
[sub_resource type="BTCheckAgentProperty" id="BTCheckAgentProperty_un3nm"]
|
||||
property = &"busy"
|
||||
value = SubResource("BBVariant_7h63t")
|
||||
|
||||
[sub_resource type="BBNode" id="BBNode_3iu7m"]
|
||||
saved_value = NodePath("Queue")
|
||||
resource_name = "Queue"
|
||||
|
||||
[sub_resource type="BTCallMethod" id="BTCallMethod_8wdsa"]
|
||||
node = SubResource("BBNode_3iu7m")
|
||||
method = &"try_advance"
|
||||
|
||||
[sub_resource type="BTSequence" id="BTSequence_26pbt"]
|
||||
children = [SubResource("BTCheckAgentProperty_un3nm"), SubResource("BTCallMethod_8wdsa")]
|
||||
|
||||
[sub_resource type="BTCooldown" id="BTCooldown_3glab"]
|
||||
duration = 2.0
|
||||
children = [SubResource("BTSequence_26pbt")]
|
||||
|
||||
[sub_resource type="BTRepeat" id="BTRepeat_hcvsp"]
|
||||
children = [SubResource("BTCooldown_3glab")]
|
||||
|
||||
[resource]
|
||||
blackboard_plan = SubResource("BlackboardPlan_7h63t")
|
||||
root_task = SubResource("BTRepeat_hcvsp")
|
||||
@@ -10,7 +10,6 @@ func generate_quest() -> void:
|
||||
quest.location = "Nestor Woods"
|
||||
quest.difficulty = 1
|
||||
quest.rewards = {"exp":100,"gold":1}
|
||||
|
||||
|
||||
func update_quest_window() -> void:
|
||||
if quest:
|
||||
@@ -34,6 +33,9 @@ func _on_generate_button_pressed() -> void:
|
||||
|
||||
func _on_post_button_pressed() -> void:
|
||||
Guild.add_quest(quest)
|
||||
quest = null
|
||||
%GenerateQuest.show()
|
||||
%PostQuest.hide()
|
||||
hide()
|
||||
|
||||
func _on_post_back_button_pressed() -> void:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[gd_scene load_steps=14 format=4 uid="uid://cd08dp16bixfv"]
|
||||
[gd_scene load_steps=11 format=4 uid="uid://cd08dp16bixfv"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://ccorfvcfa84gf" path="res://guildhall.gd" id="1_lsinl"]
|
||||
[ext_resource type="TileSet" uid="uid://6im0g3eg6sr4" path="res://test_tiles.tres" id="1_qel1r"]
|
||||
@@ -6,9 +6,7 @@
|
||||
[ext_resource type="Texture2D" uid="uid://83ayd5rg7x8l" path="res://reception-table.png" id="3_13vc8"]
|
||||
[ext_resource type="Texture2D" uid="uid://cg6ptmynq0aq0" path="res://basic-sprite.png" id="4_l3mu1"]
|
||||
[ext_resource type="PackedScene" uid="uid://cf6nnjyp8kv78" path="res://receptionist.tscn" id="5_l3mu1"]
|
||||
[ext_resource type="Texture2D" uid="uid://bnt2dlv7kxw7s" path="res://questboard.png" id="6_2wofw"]
|
||||
[ext_resource type="Script" uid="uid://b0q2233msdtgo" path="res://guild_queue.gd" id="7_hph4e"]
|
||||
[ext_resource type="PackedScene" uid="uid://drrtypncppjps" path="res://quest_board_window.tscn" id="8_uo85v"]
|
||||
[ext_resource type="PackedScene" uid="uid://b3mksvn2jf7e0" path="res://quest_board.tscn" id="7_hph4e"]
|
||||
|
||||
[sub_resource type="NavigationPolygon" id="NavigationPolygon_w7eqs"]
|
||||
vertices = PackedVector2Array(591.3203, 170.54688, 591.3125, 170.53906, 614.1094, 159.47656, 694.9531, 80.92969, 694.9375, 80.921875, 702.6406, 67, 1053, 67, 1053, 605, 665.27344, 134.64063, 35, 605, 578.35156, 176.85938, 512.60156, 177.99219, 445.89844, 179.14063, 35, 35, 432.14063, 172.14844, 432.14063, 172.14063, 406.6172, 159.21875, 368.17188, 139.71875, 368.17188, 139.71094, 357.59375, 134.42969, 326.3125, 77.5625, 324.82813, 35, 325.8828, 65.21875)
|
||||
@@ -26,18 +24,6 @@ vertices = PackedVector2Array(117.96875, 286, 9.96875, 286, 9.03125, 0, 117.0312
|
||||
polygons = Array[PackedInt32Array]([PackedInt32Array(0, 1, 2, 3)])
|
||||
outlines = Array[PackedVector2Array]([PackedVector2Array(-1, -10, 127, -10, 128, 296, 0, 296)])
|
||||
|
||||
[sub_resource type="GDScript" id="GDScript_bog1h"]
|
||||
script/source = "class_name QuestBoard extends Interactable
|
||||
|
||||
signal service_provided()
|
||||
|
||||
func _ready() -> void:
|
||||
queue = $Queue
|
||||
|
||||
func interact(interactor, service : String):
|
||||
service_provided.emit()
|
||||
"
|
||||
|
||||
[node name="Guildhall" type="Node2D"]
|
||||
script = ExtResource("1_lsinl")
|
||||
|
||||
@@ -72,19 +58,19 @@ position = Vector2(512, 29)
|
||||
[node name="Queue" parent="Sprites/Receptionist" index="3"]
|
||||
position = Vector2(0, 220)
|
||||
|
||||
[node name="CharacterBody2D" type="CharacterBody2D" parent="Sprites"]
|
||||
[node name="Player" type="CharacterBody2D" parent="Sprites"]
|
||||
position = Vector2(202, 389)
|
||||
script = ExtResource("2_5n4iw")
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Sprites/CharacterBody2D"]
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Sprites/Player"]
|
||||
rotation = 1.5707964
|
||||
shape = SubResource("CapsuleShape2D_l3mu1")
|
||||
|
||||
[node name="Sprite2D" type="Sprite2D" parent="Sprites/CharacterBody2D"]
|
||||
[node name="Sprite2D" type="Sprite2D" parent="Sprites/Player"]
|
||||
position = Vector2(0, -64)
|
||||
texture = ExtResource("4_l3mu1")
|
||||
|
||||
[node name="NavigationAgent2D" type="NavigationAgent2D" parent="Sprites/CharacterBody2D"]
|
||||
[node name="NavigationAgent2D" type="NavigationAgent2D" parent="Sprites/Player"]
|
||||
path_desired_distance = 30.0
|
||||
avoidance_enabled = true
|
||||
|
||||
@@ -92,24 +78,7 @@ avoidance_enabled = true
|
||||
position = Vector2(448, 600)
|
||||
navigation_polygon = SubResource("NavigationPolygon_l3mu1")
|
||||
|
||||
[node name="Quest Board" type="StaticBody2D" parent="."]
|
||||
[node name="Quest Board" parent="." instance=ExtResource("7_hph4e")]
|
||||
position = Vector2(935, 32)
|
||||
script = SubResource("GDScript_bog1h")
|
||||
|
||||
[node name="QuestBoardWindow" parent="Quest Board" instance=ExtResource("8_uo85v")]
|
||||
|
||||
[node name="Sprite2D" type="Sprite2D" parent="Quest Board"]
|
||||
position = Vector2(0, -64)
|
||||
texture = ExtResource("6_2wofw")
|
||||
|
||||
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Quest Board"]
|
||||
position = Vector2(-1, 11)
|
||||
rotation = 1.5707964
|
||||
polygon = PackedVector2Array(-39.999996, 128, -26.999994, 139, -3.9999943, 139, 12.000006, 129, 13.999994, -127, -7.6293945e-06, -140, -30.000008, -140, -43.000008, -126)
|
||||
|
||||
[node name="Queue" type="Node2D" parent="Quest Board"]
|
||||
position = Vector2(-12, 44)
|
||||
script = ExtResource("7_hph4e")
|
||||
direction = Vector2(0, 1)
|
||||
|
||||
[editable path="Sprites/Receptionist"]
|
||||
|
||||
@@ -3,10 +3,10 @@ class_name Interactable extends StaticBody2D
|
||||
var busy : bool = false
|
||||
var queue : GuildQueue
|
||||
|
||||
signal service_provided()
|
||||
signal interaction_complete()
|
||||
|
||||
func _ready() -> void:
|
||||
queue = $Queue
|
||||
|
||||
func interact(interactor, service : String = ""):
|
||||
service_provided.emit()
|
||||
interaction_complete.emit()
|
||||
|
||||
@@ -54,6 +54,9 @@ func approach(pos : Vector2) -> void:
|
||||
set_movement_target(point)
|
||||
|
||||
func approach_and_interact(obj : Interactable) -> void:
|
||||
var t : Vector2 = obj.global_position
|
||||
if obj.has("queue") and obj.queue != null:
|
||||
t = obj.queue.global_position
|
||||
set_movement_target(obj.global_position)
|
||||
nav_agent.target_desired_distance = interaction_range - 5
|
||||
interaction_target = obj
|
||||
|
||||
7
quest.gd
7
quest.gd
@@ -28,11 +28,18 @@ var taken : bool = false
|
||||
var questor : AdventurerData = null
|
||||
signal status_changed(status : Status)
|
||||
|
||||
func _init() -> void:
|
||||
print("TEST!")
|
||||
|
||||
func initiate(member : AdventurerData) -> void:
|
||||
questor = member
|
||||
taken = true
|
||||
status_changed.emit(Status.TAKEN)
|
||||
|
||||
#TODO: Put in quest requirements
|
||||
func is_eligible(member : AdventurerData) -> bool:
|
||||
return !taken
|
||||
|
||||
func difficulty_name() -> String:
|
||||
match(difficulty):
|
||||
0: return "None"
|
||||
|
||||
@@ -3,11 +3,12 @@ class_name QuestBoard extends Interactable
|
||||
|
||||
@onready var polygon : CollisionPolygon2D = $CollisionPolygon2D
|
||||
@onready var window : QuestBoardWindow = $QuestBoardWindow
|
||||
@onready var btplayer : BTPlayer = $BTPlayer
|
||||
|
||||
signal interaction_complete()
|
||||
|
||||
func _ready() -> void:
|
||||
register_board.call_deferred()
|
||||
super._ready()
|
||||
|
||||
func register_board() -> void:
|
||||
Guild.hall.register_interactables(self)
|
||||
@@ -25,7 +26,19 @@ func interact(interactor, type : String = "") -> void:
|
||||
window.populate(Guild.quests.keys())
|
||||
window.popup_centered()
|
||||
elif type == "quest":
|
||||
var viable_quests : Dictionary[Quest,int] = {}
|
||||
#Go through all quests and create a list of open quests suitable for their level
|
||||
for quest in Guild.quests:
|
||||
if quest.is_eligible(interactor.data):
|
||||
#TODO: Make them weight different quests differently.
|
||||
viable_quests[quest] = 1
|
||||
#If that list is zero, return without giving them a quest
|
||||
if viable_quests.size() != 0:
|
||||
var rnd_quest = []
|
||||
for quest in viable_quests.keys():
|
||||
for i in range(viable_quests[quest]):
|
||||
rnd_quest.append(quest)
|
||||
var quest = rnd_quest.pick_random()
|
||||
Guild.assign_quest(interactor.data, quest)
|
||||
interaction_complete.emit()
|
||||
#Else pick a random quest from the list and assign it to them
|
||||
pass
|
||||
|
||||
32
quest_board.tscn
Normal file
32
quest_board.tscn
Normal file
@@ -0,0 +1,32 @@
|
||||
[gd_scene load_steps=7 format=3 uid="uid://b3mksvn2jf7e0"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://drrtypncppjps" path="res://quest_board_window.tscn" id="1_4poi3"]
|
||||
[ext_resource type="Script" uid="uid://blo7tb5135vfm" path="res://quest_board.gd" id="1_38mwx"]
|
||||
[ext_resource type="Texture2D" uid="uid://bnt2dlv7kxw7s" path="res://questboard.png" id="2_3ceph"]
|
||||
[ext_resource type="Script" uid="uid://b0q2233msdtgo" path="res://guild_queue.gd" id="3_38mwx"]
|
||||
[ext_resource type="BehaviorTree" uid="uid://tr5enbq48w6x" path="res://ai/trees/quest_board.tres" id="4_3ceph"]
|
||||
|
||||
[sub_resource type="BlackboardPlan" id="BlackboardPlan_2xphb"]
|
||||
|
||||
[node name="Quest Board" type="StaticBody2D"]
|
||||
script = ExtResource("1_38mwx")
|
||||
|
||||
[node name="QuestBoardWindow" parent="." instance=ExtResource("1_4poi3")]
|
||||
|
||||
[node name="Sprite2D" type="Sprite2D" parent="."]
|
||||
position = Vector2(0, -64)
|
||||
texture = ExtResource("2_3ceph")
|
||||
|
||||
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="."]
|
||||
position = Vector2(-1, 11)
|
||||
rotation = 1.5707964
|
||||
polygon = PackedVector2Array(-39.999996, 128, -26.999994, 139, -3.9999943, 139, 12.000006, 129, 13.999994, -127, -7.6293945e-06, -140, -30.000008, -140, -43.000008, -126)
|
||||
|
||||
[node name="Queue" type="Node2D" parent="."]
|
||||
position = Vector2(-12, 44)
|
||||
script = ExtResource("3_38mwx")
|
||||
direction = Vector2(0, 1)
|
||||
|
||||
[node name="BTPlayer" type="BTPlayer" parent="."]
|
||||
behavior_tree = ExtResource("4_3ceph")
|
||||
blackboard_plan = SubResource("BlackboardPlan_2xphb")
|
||||
Reference in New Issue
Block a user