Rewrote entity system
This commit is contained in:
@@ -106,6 +106,11 @@ run={
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[layer_names]
|
||||||
|
|
||||||
|
3d_physics/layer_2="Overworld Entities"
|
||||||
|
3d_physics/layer_9="Overworld Solid"
|
||||||
|
|
||||||
[rendering]
|
[rendering]
|
||||||
|
|
||||||
textures/canvas_textures/default_texture_filter=0
|
textures/canvas_textures/default_texture_filter=0
|
||||||
|
@@ -1,8 +1,11 @@
|
|||||||
[gd_scene load_steps=8 format=3 uid="uid://yhtpoum3eek7"]
|
[gd_scene load_steps=11 format=3 uid="uid://yhtpoum3eek7"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://ixwikdguyhf0" path="res://scripts/Entity/RosaController.gd" id="1_3g383"]
|
[ext_resource type="Script" uid="uid://ixwikdguyhf0" path="res://scripts/Entity/Rosa.gd" id="1_r5ufg"]
|
||||||
|
[ext_resource type="Script" uid="uid://dtjjqp2atjyhr" path="res://scripts/Entity/Entity.gd" id="1_rvn3n"]
|
||||||
[ext_resource type="Script" uid="uid://jd50n00bo05y" path="res://scripts/Entity/RosaCamera.gd" id="2_tr66j"]
|
[ext_resource type="Script" uid="uid://jd50n00bo05y" path="res://scripts/Entity/RosaCamera.gd" id="2_tr66j"]
|
||||||
|
[ext_resource type="Script" uid="uid://cjfcpi7sxentf" path="res://scripts/Entity/Component/EntityDirection.gd" id="2_vcxxc"]
|
||||||
[ext_resource type="Shader" uid="uid://7h2axb2tsh17" path="res://shaders/NPC Shader.gdshader" id="3_j5vis"]
|
[ext_resource type="Shader" uid="uid://7h2axb2tsh17" path="res://shaders/NPC Shader.gdshader" id="3_j5vis"]
|
||||||
|
[ext_resource type="Script" uid="uid://c5nfs0m6ua4eb" path="res://scripts/Entity/Component/EntityMovement.gd" id="4_7s3uq"]
|
||||||
[ext_resource type="Texture2D" uid="uid://cofrgefp8e617" path="res://textures/human.png" id="4_rvn3n"]
|
[ext_resource type="Texture2D" uid="uid://cofrgefp8e617" path="res://textures/human.png" id="4_rvn3n"]
|
||||||
|
|
||||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_ls7r8"]
|
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_ls7r8"]
|
||||||
@@ -17,13 +20,34 @@ shader = ExtResource("3_j5vis")
|
|||||||
shader_parameter/npcTexture = ExtResource("4_rvn3n")
|
shader_parameter/npcTexture = ExtResource("4_rvn3n")
|
||||||
shader_parameter/color = Color(1, 1, 1, 1)
|
shader_parameter/color = Color(1, 1, 1, 1)
|
||||||
shader_parameter/frame = 0
|
shader_parameter/frame = 0
|
||||||
shader_parameter/direction = 1
|
shader_parameter/direction = 2
|
||||||
|
|
||||||
[node name="Rosa" type="CharacterBody3D"]
|
[node name="Rosa" type="CharacterBody3D"]
|
||||||
script = ExtResource("1_3g383")
|
collision_layer = 2
|
||||||
|
collision_mask = 258
|
||||||
|
script = ExtResource("1_r5ufg")
|
||||||
|
metadata/_custom_type_script = "uid://ixwikdguyhf0"
|
||||||
|
|
||||||
|
[node name="Entity" type="Node" parent="."]
|
||||||
|
script = ExtResource("1_rvn3n")
|
||||||
|
metadata/_custom_type_script = "uid://dtjjqp2atjyhr"
|
||||||
|
|
||||||
|
[node name="EntityDirection" type="Node" parent="Entity" node_paths=PackedStringArray("meshInstance")]
|
||||||
|
script = ExtResource("2_vcxxc")
|
||||||
|
meshInstance = NodePath("../../MeshInstance3D")
|
||||||
|
direction = 2
|
||||||
|
metadata/_custom_type_script = "uid://cjfcpi7sxentf"
|
||||||
|
|
||||||
|
[node name="EntityMoving" type="Node" parent="Entity" node_paths=PackedStringArray("characterBody", "entity", "entityDirection")]
|
||||||
|
script = ExtResource("4_7s3uq")
|
||||||
|
characterBody = NodePath("../..")
|
||||||
|
entity = NodePath("..")
|
||||||
|
entityDirection = NodePath("../EntityDirection")
|
||||||
|
movementType = 0
|
||||||
|
|
||||||
[node name="Rosa Camera" type="Camera3D" parent="." node_paths=PackedStringArray("follow")]
|
[node name="Rosa Camera" type="Camera3D" parent="." node_paths=PackedStringArray("follow")]
|
||||||
transform = Transform3D(1, 0, 0, 0, 0.130388, 0.991463, 0, -0.991463, 0.130388, 0, 3.14994, 0.404846)
|
transform = Transform3D(1, 0, 0, 0, 0.130388, 0.991463, 0, -0.991463, 0.130388, 0, 3.14994, 0.404846)
|
||||||
|
current = true
|
||||||
fov = 30.0
|
fov = 30.0
|
||||||
script = ExtResource("2_tr66j")
|
script = ExtResource("2_tr66j")
|
||||||
follow = NodePath("..")
|
follow = NodePath("..")
|
||||||
@@ -32,6 +56,6 @@ follow = NodePath("..")
|
|||||||
shape = SubResource("CapsuleShape3D_ls7r8")
|
shape = SubResource("CapsuleShape3D_ls7r8")
|
||||||
|
|
||||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
|
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
|
||||||
transform = Transform3D(1, 0, 0, 0, 0.173648, 0.984808, 0, -0.984808, 0.173648, 0.00989294, 0, 0)
|
transform = Transform3D(1, 0, 0, 0, 0.173648, 0.984808, 0, -0.984808, 0.173648, 0, 0, 0)
|
||||||
mesh = SubResource("QuadMesh_dyaax")
|
mesh = SubResource("QuadMesh_dyaax")
|
||||||
surface_material_override/0 = SubResource("ShaderMaterial_fegux")
|
surface_material_override/0 = SubResource("ShaderMaterial_fegux")
|
||||||
|
@@ -1,7 +1,10 @@
|
|||||||
[gd_scene load_steps=7 format=3 uid="uid://dr4b2pmsknuhc"]
|
[gd_scene load_steps=10 format=3 uid="uid://dr4b2pmsknuhc"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://d23qg1ovkbxst" path="res://scripts/Entity/BasicNPCEntity.gd" id="1_1muh7"]
|
[ext_resource type="Script" uid="uid://d23qg1ovkbxst" path="res://scripts/Entity/BasicNPCEntity.gd" id="1_1muh7"]
|
||||||
[ext_resource type="Shader" uid="uid://7h2axb2tsh17" path="res://shaders/NPC Shader.gdshader" id="1_xgcv1"]
|
[ext_resource type="Shader" uid="uid://7h2axb2tsh17" path="res://shaders/NPC Shader.gdshader" id="1_xgcv1"]
|
||||||
|
[ext_resource type="Script" uid="uid://dtjjqp2atjyhr" path="res://scripts/Entity/Entity.gd" id="2_ehu3x"]
|
||||||
|
[ext_resource type="Script" uid="uid://cjfcpi7sxentf" path="res://scripts/Entity/Component/EntityDirection.gd" id="3_gyi1p"]
|
||||||
|
[ext_resource type="Script" uid="uid://c5nfs0m6ua4eb" path="res://scripts/Entity/Component/EntityMovement.gd" id="4_3wesq"]
|
||||||
[ext_resource type="Texture2D" uid="uid://cofrgefp8e617" path="res://textures/human.png" id="4_vo0ku"]
|
[ext_resource type="Texture2D" uid="uid://cofrgefp8e617" path="res://textures/human.png" id="4_vo0ku"]
|
||||||
|
|
||||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_dw1sy"]
|
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_dw1sy"]
|
||||||
@@ -16,10 +19,29 @@ shader = ExtResource("1_xgcv1")
|
|||||||
shader_parameter/npcTexture = ExtResource("4_vo0ku")
|
shader_parameter/npcTexture = ExtResource("4_vo0ku")
|
||||||
shader_parameter/color = Color(0, 0.563816, 0, 1)
|
shader_parameter/color = Color(0, 0.563816, 0, 1)
|
||||||
shader_parameter/frame = 0
|
shader_parameter/frame = 0
|
||||||
shader_parameter/direction = 1
|
shader_parameter/direction = 0
|
||||||
|
|
||||||
[node name="TestNpc" type="CharacterBody3D"]
|
[node name="TestNpc" type="CharacterBody3D"]
|
||||||
|
collision_layer = 2
|
||||||
|
collision_mask = 258
|
||||||
script = ExtResource("1_1muh7")
|
script = ExtResource("1_1muh7")
|
||||||
|
metadata/_custom_type_script = "uid://d23qg1ovkbxst"
|
||||||
|
|
||||||
|
[node name="Entity" type="Node" parent="."]
|
||||||
|
script = ExtResource("2_ehu3x")
|
||||||
|
metadata/_custom_type_script = "uid://dtjjqp2atjyhr"
|
||||||
|
|
||||||
|
[node name="EntityDirection" type="Node" parent="Entity" node_paths=PackedStringArray("meshInstance")]
|
||||||
|
script = ExtResource("3_gyi1p")
|
||||||
|
meshInstance = NodePath("../../MeshInstance3D")
|
||||||
|
metadata/_custom_type_script = "uid://cjfcpi7sxentf"
|
||||||
|
|
||||||
|
[node name="EntityMoving" type="Node" parent="Entity" node_paths=PackedStringArray("characterBody", "entity", "entityDirection")]
|
||||||
|
script = ExtResource("4_3wesq")
|
||||||
|
characterBody = NodePath("../..")
|
||||||
|
entity = NodePath("..")
|
||||||
|
entityDirection = NodePath("../EntityDirection")
|
||||||
|
movementType = 2
|
||||||
|
|
||||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||||
shape = SubResource("CapsuleShape3D_dw1sy")
|
shape = SubResource("CapsuleShape3D_dw1sy")
|
||||||
|
@@ -32,11 +32,8 @@ environment = SubResource("Environment_nyivo")
|
|||||||
[node name="Rosa" parent="." instance=ExtResource("1_7b7hx")]
|
[node name="Rosa" parent="." instance=ExtResource("1_7b7hx")]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.19857, 0.684572, 0.968477)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.19857, 0.684572, 0.968477)
|
||||||
|
|
||||||
[node name="Green" parent="." node_paths=PackedStringArray("interactEvent") instance=ExtResource("2_cg1ph")]
|
[node name="Green" parent="." instance=ExtResource("2_cg1ph")]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.68747, 0.459578, -0.399262)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.68747, 0.459578, -0.399262)
|
||||||
interactEvent = NodePath("../Events/TestConversation")
|
|
||||||
moveType = 1
|
|
||||||
direction = 1
|
|
||||||
|
|
||||||
[node name="OmniLight3D" type="OmniLight3D" parent="."]
|
[node name="OmniLight3D" type="OmniLight3D" parent="."]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 7.20244, 3.80554)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 7.20244, 3.80554)
|
||||||
@@ -52,9 +49,13 @@ metadata/_edit_lock_ = true
|
|||||||
|
|
||||||
[node name="Building2" parent="Map" instance=ExtResource("4_brp0k")]
|
[node name="Building2" parent="Map" instance=ExtResource("4_brp0k")]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8.13514, 2.62692, -0.0984068)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8.13514, 2.62692, -0.0984068)
|
||||||
|
collision_layer = 256
|
||||||
|
collision_mask = 2
|
||||||
|
|
||||||
[node name="Building" parent="Map" instance=ExtResource("4_brp0k")]
|
[node name="Building" parent="Map" instance=ExtResource("4_brp0k")]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2.92766, 2.37929, -4.38178)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2.92766, 2.37929, -4.38178)
|
||||||
|
collision_layer = 256
|
||||||
|
collision_mask = 2
|
||||||
|
|
||||||
[node name="Events" type="Node" parent="."]
|
[node name="Events" type="Node" parent="."]
|
||||||
|
|
||||||
|
@@ -17,6 +17,8 @@ shader_parameter/tileset = ExtResource("2_3bnhs")
|
|||||||
size = Vector3(50, 0.1, 50)
|
size = Vector3(50, 0.1, 50)
|
||||||
|
|
||||||
[node name="Ground" type="StaticBody3D"]
|
[node name="Ground" type="StaticBody3D"]
|
||||||
|
collision_layer = 256
|
||||||
|
collision_mask = 2
|
||||||
metadata/_edit_lock_ = true
|
metadata/_edit_lock_ = true
|
||||||
|
|
||||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
|
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
|
||||||
|
@@ -8,7 +8,7 @@ anchors_preset = 12
|
|||||||
anchor_top = 1.0
|
anchor_top = 1.0
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
offset_top = -60.0
|
offset_top = -50.0
|
||||||
grow_horizontal = 2
|
grow_horizontal = 2
|
||||||
grow_vertical = 0
|
grow_vertical = 0
|
||||||
theme = ExtResource("1_wx4lp")
|
theme = ExtResource("1_wx4lp")
|
||||||
|
@@ -1,34 +1 @@
|
|||||||
class_name BasicNPCEntity extends "res://scripts/Entity/OverworldEntity.gd"
|
class_name BasicNPCEntity extends CharacterBody3D
|
||||||
const Event = preload("res://scripts/Event/Event.gd");
|
|
||||||
|
|
||||||
enum BasicNPCMoveType {
|
|
||||||
STILL,
|
|
||||||
RANDOM_LOOK
|
|
||||||
};
|
|
||||||
|
|
||||||
@export var interactEvent:Event;
|
|
||||||
|
|
||||||
@export var moveType:BasicNPCMoveType = BasicNPCMoveType.STILL;
|
|
||||||
|
|
||||||
@export var randomLookMinTime:float = 1.5;
|
|
||||||
@export var randomLookMaxTime:float = 4.0;
|
|
||||||
var randomLookTimer:float = 0.0;
|
|
||||||
|
|
||||||
func interact(interactor:OverworldEntity) -> void:
|
|
||||||
if interactEvent == null:
|
|
||||||
push_error("BasicNPCEntity: interactType EVENT but no event set");
|
|
||||||
return
|
|
||||||
interactEvent.onEntityInteract(interactor, self);
|
|
||||||
|
|
||||||
func updateMovement(delta:float) -> void:
|
|
||||||
if moveType == BasicNPCMoveType.STILL:
|
|
||||||
return
|
|
||||||
|
|
||||||
if moveType == BasicNPCMoveType.RANDOM_LOOK:
|
|
||||||
randomLookTimer -= delta;
|
|
||||||
if randomLookTimer <= 0:
|
|
||||||
randomLookTimer = randf_range(randomLookMinTime, randomLookMaxTime);
|
|
||||||
self.direction = randi_range(0, 3);
|
|
||||||
return
|
|
||||||
|
|
||||||
pass
|
|
||||||
|
78
scripts/Entity/Component/EntityDirection.gd
Normal file
78
scripts/Entity/Component/EntityDirection.gd
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
@tool
|
||||||
|
class_name EntityDirection extends Node
|
||||||
|
|
||||||
|
enum Direction {
|
||||||
|
SOUTH,
|
||||||
|
WEST,
|
||||||
|
NORTH,
|
||||||
|
EAST,
|
||||||
|
}
|
||||||
|
|
||||||
|
@export var meshInstance:MeshInstance3D = null:
|
||||||
|
set(newInstance):
|
||||||
|
meshInstance = newInstance;
|
||||||
|
_updateMaterial();
|
||||||
|
|
||||||
|
@export var direction = Direction.SOUTH:
|
||||||
|
set(newDirection):
|
||||||
|
direction = newDirection;
|
||||||
|
_updateMaterial();
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
_updateMaterial();
|
||||||
|
|
||||||
|
func _updateMaterial() -> void:
|
||||||
|
if !meshInstance:
|
||||||
|
return
|
||||||
|
|
||||||
|
for i in range(meshInstance.get_surface_override_material_count()):
|
||||||
|
var material:ShaderMaterial = meshInstance.get_surface_override_material(i)
|
||||||
|
if !material:
|
||||||
|
continue
|
||||||
|
material.set_shader_parameter("direction", direction)
|
||||||
|
|
||||||
|
func getDirectionVector() -> Vector3:
|
||||||
|
match direction:
|
||||||
|
Direction.NORTH:
|
||||||
|
return Vector3(0, 0, -1);
|
||||||
|
Direction.SOUTH:
|
||||||
|
return Vector3(0, 0, 1);
|
||||||
|
Direction.WEST:
|
||||||
|
return Vector3(-1, 0, 0);
|
||||||
|
Direction.EAST:
|
||||||
|
return Vector3(1, 0, 0);
|
||||||
|
_:
|
||||||
|
assert(false, "Invalid direction");
|
||||||
|
return Vector3(0, 0, 0);
|
||||||
|
|
||||||
|
func updateDirectionFromMovement(movement:Vector2) -> void:
|
||||||
|
if movement.x >= abs(movement.y) and(
|
||||||
|
movement.y == 0 or
|
||||||
|
(movement.y > 0 and direction != Direction.SOUTH) or
|
||||||
|
(movement.y < 0 and direction != Direction.NORTH)
|
||||||
|
):
|
||||||
|
direction = Direction.EAST;
|
||||||
|
elif (movement.x <= -abs(movement.y) and (
|
||||||
|
movement.y == 0 or
|
||||||
|
(movement.y > 0 and direction != Direction.SOUTH) or
|
||||||
|
(movement.y < 0 and direction != Direction.NORTH)
|
||||||
|
)):
|
||||||
|
direction = Direction.WEST;
|
||||||
|
elif (movement.y > 0):
|
||||||
|
direction = Direction.SOUTH;
|
||||||
|
elif (movement.y < 0):
|
||||||
|
direction = Direction.NORTH;
|
||||||
|
|
||||||
|
# func getDirectionToFace(position:Vector3) -> Direction:
|
||||||
|
# var diff = position - self.position;
|
||||||
|
# if abs(diff.x) > abs(diff.z):
|
||||||
|
# if diff.x > 0:
|
||||||
|
# return Direction.EAST;
|
||||||
|
# else:
|
||||||
|
# return Direction.WEST;
|
||||||
|
# else:
|
||||||
|
# if diff.z > 0:
|
||||||
|
# return Direction.SOUTH;
|
||||||
|
# else:
|
||||||
|
# return Direction.NORTH;
|
||||||
|
# return Direction.SOUTH;
|
1
scripts/Entity/Component/EntityDirection.gd.uid
Normal file
1
scripts/Entity/Component/EntityDirection.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://cjfcpi7sxentf
|
77
scripts/Entity/Component/EntityMovement.gd
Normal file
77
scripts/Entity/Component/EntityMovement.gd
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
class_name EntityMovement extends Node
|
||||||
|
|
||||||
|
enum MovementType {
|
||||||
|
PLAYER_INPUT,
|
||||||
|
STILL,
|
||||||
|
NPC_RANDOM_LOOK
|
||||||
|
};
|
||||||
|
|
||||||
|
@export var characterBody:CharacterBody3D = null;
|
||||||
|
@export var entity:Entity = null;
|
||||||
|
@export var entityDirection:EntityDirection = null;
|
||||||
|
|
||||||
|
@export var speed:float = 200;
|
||||||
|
@export var runSpeed:float = 400;
|
||||||
|
@export var friction:float = 8.5;
|
||||||
|
@export var gravity:float = 30;
|
||||||
|
|
||||||
|
@export var movementType:MovementType = MovementType.STILL;
|
||||||
|
|
||||||
|
@export var randomLookMinTime:float = 1.5;
|
||||||
|
@export var randomLookMaxTime:float = 4.0;
|
||||||
|
var randomLookTimer:float = 0.0;
|
||||||
|
|
||||||
|
func _physics_process(delta:float) -> void:
|
||||||
|
if !entity || entity.isPaused() || !characterBody:
|
||||||
|
return;
|
||||||
|
|
||||||
|
# Update movement
|
||||||
|
_updateVelocity(delta)
|
||||||
|
|
||||||
|
# Gravity and friction
|
||||||
|
if !characterBody.is_on_floor():
|
||||||
|
characterBody.velocity.y -= gravity * delta;
|
||||||
|
else:
|
||||||
|
characterBody.velocity += -(characterBody.velocity * friction * delta);
|
||||||
|
# if velocity.length() != 0:
|
||||||
|
# _updateTileData();
|
||||||
|
|
||||||
|
# Update character controller.
|
||||||
|
characterBody.move_and_slide();
|
||||||
|
|
||||||
|
func _updateVelocity(delta:float):
|
||||||
|
match movementType:
|
||||||
|
MovementType.PLAYER_INPUT:
|
||||||
|
_updatePlayerInput(delta);
|
||||||
|
MovementType.STILL:
|
||||||
|
_updateStill(delta);
|
||||||
|
MovementType.NPC_RANDOM_LOOK:
|
||||||
|
_updateNPCRandomLook(delta);
|
||||||
|
|
||||||
|
func _updatePlayerInput(delta:float) -> void:
|
||||||
|
var dir:Vector2 = Input.get_vector("left", "right", "up", "down");
|
||||||
|
|
||||||
|
var moveSpeed:float;
|
||||||
|
if Input.is_action_pressed("run"):
|
||||||
|
moveSpeed = runSpeed;
|
||||||
|
else:
|
||||||
|
moveSpeed = speed;
|
||||||
|
|
||||||
|
if dir.x != 0 or dir.y != 0:
|
||||||
|
characterBody.velocity.x = dir.x * moveSpeed * delta;
|
||||||
|
characterBody.velocity.z = dir.y * moveSpeed * delta;
|
||||||
|
|
||||||
|
if entityDirection:
|
||||||
|
entityDirection.updateDirectionFromMovement(dir);
|
||||||
|
|
||||||
|
func _updateStill(delta:float):
|
||||||
|
pass
|
||||||
|
|
||||||
|
func _updateNPCRandomLook(delta:float):
|
||||||
|
if !entityDirection:
|
||||||
|
return
|
||||||
|
randomLookTimer -= delta;
|
||||||
|
|
||||||
|
if randomLookTimer <= 0:
|
||||||
|
randomLookTimer = randf_range(randomLookMinTime, randomLookMaxTime);
|
||||||
|
entityDirection.direction = randi_range(0, 3);
|
1
scripts/Entity/Component/EntityMovement.gd.uid
Normal file
1
scripts/Entity/Component/EntityMovement.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://c5nfs0m6ua4eb
|
1
scripts/Entity/Component/EntityMoving.gd.uid
Normal file
1
scripts/Entity/Component/EntityMoving.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://dp6itsmbl0ucn
|
88
scripts/Entity/Entity.gd
Normal file
88
scripts/Entity/Entity.gd
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
class_name Entity extends Node
|
||||||
|
|
||||||
|
# var meshInstance:MeshInstance3D;
|
||||||
|
# var underFootTile:int = -1;
|
||||||
|
# var underFootPosition:Vector3;
|
||||||
|
# var material:ShaderMaterial;
|
||||||
|
|
||||||
|
# func updateMaterial() -> bool:
|
||||||
|
# if !meshInstance:
|
||||||
|
# return false
|
||||||
|
# if !material:
|
||||||
|
# return false
|
||||||
|
# return true
|
||||||
|
|
||||||
|
# # Virtual Methods
|
||||||
|
# func updateMovement(delta) -> void:
|
||||||
|
# pass
|
||||||
|
|
||||||
|
# func updateOverworldLogic(delta) -> void:
|
||||||
|
# pass
|
||||||
|
|
||||||
|
func isPaused() -> bool:
|
||||||
|
var ps = PAUSE.getPauseState();
|
||||||
|
match ps:
|
||||||
|
PauseSystem.PauseType.NOT_PAUSED:
|
||||||
|
return false;
|
||||||
|
PauseSystem.PauseType.FULLY_PAUSED:
|
||||||
|
return true;
|
||||||
|
PauseSystem.PauseType.ENTITY_PAUSED:
|
||||||
|
if PAUSE.entities.find(self) != -1:
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
PauseSystem.PauseType.CUTSCENE_PAUSED:
|
||||||
|
if PAUSE.entities.find(self) != -1:
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
_:
|
||||||
|
assert(false, "Invalid pause state");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
# Private methods
|
||||||
|
# func _updateTileData() -> void:
|
||||||
|
# # ray cast down
|
||||||
|
# var offset = Vector3(0, 0, 0.426);
|
||||||
|
# var query = PhysicsRayQueryParameters3D.create(
|
||||||
|
# position + offset,
|
||||||
|
# position + Vector3(0, -1, 0) + offset
|
||||||
|
# )
|
||||||
|
# query.collide_with_areas = true
|
||||||
|
# query.exclude = [self]
|
||||||
|
|
||||||
|
# var result = get_world_3d().direct_space_state.intersect_ray(query)
|
||||||
|
# if !result or !result.collider:
|
||||||
|
# return;
|
||||||
|
|
||||||
|
# var collider = result.collider;
|
||||||
|
# var colliderMesh = collider.get_node("../");
|
||||||
|
# if !colliderMesh or !(colliderMesh is ArrayMesh) or !colliderMesh.mesh or colliderMesh.mesh.get_surface_count() == 0:
|
||||||
|
# return;
|
||||||
|
|
||||||
|
# # Get the face index (triangle)
|
||||||
|
# var arrays = colliderMesh.mesh.surface_get_arrays(0);
|
||||||
|
# var indiceIdx = result.face_index * 3;
|
||||||
|
|
||||||
|
# # Get each indice of the triangle
|
||||||
|
# var index0 = arrays[Mesh.ARRAY_INDEX][indiceIdx+0];
|
||||||
|
# var index1 = arrays[Mesh.ARRAY_INDEX][indiceIdx+1];
|
||||||
|
# var index2 = arrays[Mesh.ARRAY_INDEX][indiceIdx+2];
|
||||||
|
|
||||||
|
# # Get each uv of each indice
|
||||||
|
# var uv0:Vector2 = arrays[Mesh.ARRAY_TEX_UV][index0];
|
||||||
|
# var uv1:Vector2 = arrays[Mesh.ARRAY_TEX_UV][index1];
|
||||||
|
# var uv2:Vector2 = arrays[Mesh.ARRAY_TEX_UV][index2];
|
||||||
|
|
||||||
|
# # Determine the lowest texture coordinate
|
||||||
|
# var min = Vector2(min(uv0.x, uv1.x, uv2.x), min(uv0.y, uv1.y, uv2.y));
|
||||||
|
|
||||||
|
# # Convert to column/row
|
||||||
|
# var w = 256;
|
||||||
|
# var h = w;
|
||||||
|
# var tw = 48;
|
||||||
|
# var th = tw;
|
||||||
|
# var column = int(roundf(min.x * w)) / tw;
|
||||||
|
# var row = int(roundf(min.y * h)) / th;
|
||||||
|
# var columns = 768 / tw;
|
||||||
|
# underFootPosition = result.position;
|
||||||
|
# underFootTile = column % columns + row * columns;
|
1
scripts/Entity/Entity.gd.uid
Normal file
1
scripts/Entity/Entity.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://dtjjqp2atjyhr
|
1
scripts/Entity/MovingEntity.gd.uid
Normal file
1
scripts/Entity/MovingEntity.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://bcei5b2x3gu8y
|
@@ -1,160 +0,0 @@
|
|||||||
class_name OverworldEntity extends CharacterBody3D
|
|
||||||
|
|
||||||
enum Direction {
|
|
||||||
SOUTH,
|
|
||||||
WEST,
|
|
||||||
NORTH,
|
|
||||||
EAST,
|
|
||||||
}
|
|
||||||
|
|
||||||
var speed:float = 200;
|
|
||||||
var runSpeed:float = 400;
|
|
||||||
var friction:float = 8.5;
|
|
||||||
var gravity:float = 30;
|
|
||||||
|
|
||||||
@export var direction = Direction.SOUTH:
|
|
||||||
set(newDirection):
|
|
||||||
direction = newDirection;
|
|
||||||
_updateMaterial();
|
|
||||||
|
|
||||||
var meshInstance:MeshInstance3D;
|
|
||||||
var underFootTile:int = -1;
|
|
||||||
var underFootPosition:Vector3;
|
|
||||||
|
|
||||||
func _updateMaterial():
|
|
||||||
if !meshInstance:
|
|
||||||
return
|
|
||||||
var material:ShaderMaterial = meshInstance.get_surface_override_material(0)
|
|
||||||
if !material:
|
|
||||||
return
|
|
||||||
material.set_shader_parameter("direction", direction)
|
|
||||||
|
|
||||||
func getDirectionVector() -> Vector3:
|
|
||||||
match direction:
|
|
||||||
Direction.NORTH:
|
|
||||||
return Vector3(0, 0, -1);
|
|
||||||
Direction.SOUTH:
|
|
||||||
return Vector3(0, 0, 1);
|
|
||||||
Direction.WEST:
|
|
||||||
return Vector3(-1, 0, 0);
|
|
||||||
Direction.EAST:
|
|
||||||
return Vector3(1, 0, 0);
|
|
||||||
return Vector3(0, 0, 0);
|
|
||||||
|
|
||||||
func getDirectionToFace(position:Vector3) -> Direction:
|
|
||||||
var diff = position - self.position;
|
|
||||||
if abs(diff.x) > abs(diff.z):
|
|
||||||
if diff.x > 0:
|
|
||||||
return Direction.EAST;
|
|
||||||
else:
|
|
||||||
return Direction.WEST;
|
|
||||||
else:
|
|
||||||
if diff.z > 0:
|
|
||||||
return Direction.SOUTH;
|
|
||||||
else:
|
|
||||||
return Direction.NORTH;
|
|
||||||
return Direction.SOUTH;
|
|
||||||
|
|
||||||
# Virtual Methods
|
|
||||||
func updateMovement(delta) -> void:
|
|
||||||
pass
|
|
||||||
|
|
||||||
func updateOverworldLogic(delta) -> void:
|
|
||||||
pass
|
|
||||||
|
|
||||||
func isPaused() -> bool:
|
|
||||||
var ps = PAUSE.getPauseState();
|
|
||||||
|
|
||||||
if ps == PauseSystem.PauseType.NOT_PAUSED:
|
|
||||||
return false;
|
|
||||||
elif ps == PauseSystem.PauseType.FULLY_PAUSED:
|
|
||||||
return true;
|
|
||||||
elif ps == PauseSystem.PauseType.ENTITY_PAUSED:
|
|
||||||
if PAUSE.entities.find(self) != -1:
|
|
||||||
return true;
|
|
||||||
return false
|
|
||||||
elif ps == PauseSystem.PauseType.CUTSCENE_PAUSED:
|
|
||||||
if PAUSE.entities.find(self) != -1:
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
|
|
||||||
# Private methods
|
|
||||||
func _updateTileData() -> void:
|
|
||||||
# ray cast down
|
|
||||||
var offset = Vector3(0, 0, 0.426);
|
|
||||||
var query = PhysicsRayQueryParameters3D.create(
|
|
||||||
position + offset,
|
|
||||||
position + Vector3(0, -1, 0) + offset
|
|
||||||
)
|
|
||||||
query.collide_with_areas = true
|
|
||||||
query.exclude = [self]
|
|
||||||
|
|
||||||
var result = get_world_3d().direct_space_state.intersect_ray(query)
|
|
||||||
if !result or !result.collider:
|
|
||||||
return;
|
|
||||||
|
|
||||||
var collider = result.collider;
|
|
||||||
var colliderMesh = collider.get_node("../");
|
|
||||||
if !colliderMesh or !(colliderMesh is ArrayMesh) or !colliderMesh.mesh or colliderMesh.mesh.get_surface_count() == 0:
|
|
||||||
return;
|
|
||||||
|
|
||||||
# Get the face index (triangle)
|
|
||||||
var arrays = colliderMesh.mesh.surface_get_arrays(0);
|
|
||||||
var indiceIdx = result.face_index * 3;
|
|
||||||
|
|
||||||
# Get each indice of the triangle
|
|
||||||
var index0 = arrays[Mesh.ARRAY_INDEX][indiceIdx+0];
|
|
||||||
var index1 = arrays[Mesh.ARRAY_INDEX][indiceIdx+1];
|
|
||||||
var index2 = arrays[Mesh.ARRAY_INDEX][indiceIdx+2];
|
|
||||||
|
|
||||||
# Get each uv of each indice
|
|
||||||
var uv0:Vector2 = arrays[Mesh.ARRAY_TEX_UV][index0];
|
|
||||||
var uv1:Vector2 = arrays[Mesh.ARRAY_TEX_UV][index1];
|
|
||||||
var uv2:Vector2 = arrays[Mesh.ARRAY_TEX_UV][index2];
|
|
||||||
|
|
||||||
# Determine the lowest texture coordinate
|
|
||||||
var min = Vector2(min(uv0.x, uv1.x, uv2.x), min(uv0.y, uv1.y, uv2.y));
|
|
||||||
|
|
||||||
# Convert to column/row
|
|
||||||
var w = 256;
|
|
||||||
var h = w;
|
|
||||||
var tw = 48;
|
|
||||||
var th = tw;
|
|
||||||
var column = int(roundf(min.x * w)) / tw;
|
|
||||||
var row = int(roundf(min.y * h)) / th;
|
|
||||||
var columns = 768 / tw;
|
|
||||||
underFootPosition = result.position;
|
|
||||||
underFootTile = column % columns + row * columns;
|
|
||||||
|
|
||||||
# Events
|
|
||||||
func _ready() -> void:
|
|
||||||
meshInstance = get_node("MeshInstance3D")
|
|
||||||
_updateTileData();
|
|
||||||
_updateMaterial();
|
|
||||||
pass
|
|
||||||
|
|
||||||
func _process(delta:float) -> void:
|
|
||||||
if isPaused():
|
|
||||||
return;
|
|
||||||
|
|
||||||
# Update logic
|
|
||||||
updateOverworldLogic(delta)
|
|
||||||
|
|
||||||
func _physics_process(delta: float) -> void:
|
|
||||||
if isPaused():
|
|
||||||
return;
|
|
||||||
|
|
||||||
# Update movement
|
|
||||||
updateMovement(delta);
|
|
||||||
|
|
||||||
# Gravity and friction
|
|
||||||
if !is_on_floor():
|
|
||||||
velocity.y -= gravity * delta;
|
|
||||||
else:
|
|
||||||
velocity += -(velocity * friction * delta);
|
|
||||||
if velocity.length() != 0:
|
|
||||||
_updateTileData();
|
|
||||||
|
|
||||||
# Update character controller.
|
|
||||||
move_and_slide();
|
|
27
scripts/Entity/Rosa.gd
Normal file
27
scripts/Entity/Rosa.gd
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
class_name Rosa extends CharacterBody3D
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# var interactRange = 0.7;
|
||||||
|
|
||||||
|
# func updateOverworldLogic(delta) -> void:
|
||||||
|
# # Check if interact button is pressed
|
||||||
|
# if(Input.is_action_just_pressed("interact")):
|
||||||
|
# var rayDirection = getDirectionVector();
|
||||||
|
# # cast ray
|
||||||
|
|
||||||
|
# var query = PhysicsRayQueryParameters3D.create(
|
||||||
|
# position,
|
||||||
|
# position + (rayDirection * interactRange)
|
||||||
|
# )
|
||||||
|
# query.collide_with_areas = true
|
||||||
|
# query.exclude = [self]
|
||||||
|
|
||||||
|
# var result = get_world_3d().direct_space_state.intersect_ray(query)
|
||||||
|
# if result and result.collider:
|
||||||
|
# var collider = result.collider
|
||||||
|
# if(collider.has_method("interact")):
|
||||||
|
# collider.interact(self)
|
||||||
|
|
||||||
|
# if Input.is_action_just_pressed("pause"):
|
||||||
|
# PAUSE.playerPauseToggle();
|
@@ -1,7 +1,7 @@
|
|||||||
extends Camera3D
|
extends Camera3D
|
||||||
|
|
||||||
@export var pixelScale:float = 1.0;
|
@export var pixelScale:float = 1.0;
|
||||||
@export var follow:Node;
|
@export var follow:Node3D;
|
||||||
|
|
||||||
const WORLD_UNITS:float = 32.0;
|
const WORLD_UNITS:float = 32.0;
|
||||||
|
|
||||||
|
@@ -1,57 +0,0 @@
|
|||||||
class_name RosaController extends "res://scripts/Entity/OverworldEntity.gd"
|
|
||||||
|
|
||||||
var interactRange = 0.7;
|
|
||||||
|
|
||||||
func updateOverworldLogic(delta) -> void:
|
|
||||||
# Check if interact button is pressed
|
|
||||||
if(Input.is_action_just_pressed("interact")):
|
|
||||||
var rayDirection = getDirectionVector();
|
|
||||||
# cast ray
|
|
||||||
|
|
||||||
var query = PhysicsRayQueryParameters3D.create(
|
|
||||||
position,
|
|
||||||
position + (rayDirection * interactRange)
|
|
||||||
)
|
|
||||||
query.collide_with_areas = true
|
|
||||||
query.exclude = [self]
|
|
||||||
|
|
||||||
var result = get_world_3d().direct_space_state.intersect_ray(query)
|
|
||||||
if result and result.collider:
|
|
||||||
var collider = result.collider
|
|
||||||
if(collider.has_method("interact")):
|
|
||||||
collider.interact(self)
|
|
||||||
|
|
||||||
if Input.is_action_just_pressed("pause"):
|
|
||||||
PAUSE.playerPauseToggle();
|
|
||||||
|
|
||||||
func updateMovement(delta) -> void:
|
|
||||||
# User movement
|
|
||||||
var dir:Vector2 = Input.get_vector("left", "right", "up", "down");
|
|
||||||
|
|
||||||
var moveSpeed:float;
|
|
||||||
if Input.is_action_pressed("run"):
|
|
||||||
moveSpeed = runSpeed;
|
|
||||||
else:
|
|
||||||
moveSpeed = speed;
|
|
||||||
|
|
||||||
if(dir.x != 0 or dir.y != 0):
|
|
||||||
velocity.x = dir.x * moveSpeed * delta;
|
|
||||||
velocity.z = dir.y * moveSpeed * delta;
|
|
||||||
|
|
||||||
# Update direction
|
|
||||||
if(dir.x >= abs(dir.y) and(
|
|
||||||
dir.y == 0 or
|
|
||||||
(dir.y > 0 and direction != Direction.SOUTH) or
|
|
||||||
(dir.y < 0 and direction != Direction.NORTH)
|
|
||||||
)):
|
|
||||||
direction = Direction.EAST;
|
|
||||||
elif (dir.x <= -abs(dir.y) and (
|
|
||||||
dir.y == 0 or
|
|
||||||
(dir.y > 0 and direction != Direction.SOUTH) or
|
|
||||||
(dir.y < 0 and direction != Direction.NORTH)
|
|
||||||
)):
|
|
||||||
direction = Direction.WEST;
|
|
||||||
elif (dir.y > 0):
|
|
||||||
direction = Direction.SOUTH;
|
|
||||||
elif (dir.y < 0):
|
|
||||||
direction = Direction.NORTH;
|
|
@@ -1,7 +1,7 @@
|
|||||||
class_name EventEntityTurn extends "res://scripts/Event/Event.gd"
|
class_name EventEntityTurn extends "res://scripts/Event/Event.gd"
|
||||||
|
|
||||||
@export var entity:OverworldEntity = null
|
@export var entity:Entity = null
|
||||||
@export var direction:OverworldEntity.Direction = OverworldEntity.Direction.SOUTH
|
@export var direction:EntityDirection.Direction = EntityDirection.Direction.SOUTH
|
||||||
|
|
||||||
func start():
|
func start():
|
||||||
if entity == null:
|
if entity == null:
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
class_name Event extends Node
|
class_name Event extends Node
|
||||||
|
|
||||||
const OverworldEntity = preload("res://scripts/Entity/OverworldEntity.gd");
|
const Entity = preload("res://scripts/Entity/Entity.gd");
|
||||||
|
|
||||||
|
|
||||||
var started:bool = false;
|
var started:bool = false;
|
||||||
var ended:bool = false;
|
var ended:bool = false;
|
||||||
var interactor:OverworldEntity = null
|
var interactor:Entity = null
|
||||||
var interactee:OverworldEntity = null
|
var interactee:Entity = null
|
||||||
|
|
||||||
# Godot Methods
|
# Godot Methods
|
||||||
func _init() -> void:
|
func _init() -> void:
|
||||||
@@ -43,8 +43,8 @@ func reset() -> void:
|
|||||||
interactee = null
|
interactee = null
|
||||||
|
|
||||||
func onEntityInteract(
|
func onEntityInteract(
|
||||||
interactor:OverworldEntity,
|
interactor:Entity,
|
||||||
interactee:OverworldEntity
|
interactee:Entity
|
||||||
) -> void:
|
) -> void:
|
||||||
self.reset()
|
self.reset()
|
||||||
self.interactor = interactor
|
self.interactor = interactor
|
||||||
|
@@ -3,7 +3,7 @@ class_name EventConversation extends "res://scripts/Event/Flow/EventGroup.gd"
|
|||||||
@export var startPauseType:PauseSystem.PauseType = PauseSystem.PauseType.ENTITY_PAUSED
|
@export var startPauseType:PauseSystem.PauseType = PauseSystem.PauseType.ENTITY_PAUSED
|
||||||
@export var endPauseType:PauseSystem.PauseType = PauseSystem.PauseType.NOT_PAUSED
|
@export var endPauseType:PauseSystem.PauseType = PauseSystem.PauseType.NOT_PAUSED
|
||||||
|
|
||||||
@export var entities:Array[OverworldEntity] = []
|
@export var entities:Array[Entity] = []
|
||||||
|
|
||||||
@export var pauseInteractee:bool = true
|
@export var pauseInteractee:bool = true
|
||||||
@export var pauseInteractor:bool = true
|
@export var pauseInteractor:bool = true
|
||||||
|
@@ -3,12 +3,12 @@ class_name EventPause extends "res://scripts/Event/Event.gd"
|
|||||||
const PauseSystem = preload("res://scripts/Singleton/Pause.gd")
|
const PauseSystem = preload("res://scripts/Singleton/Pause.gd")
|
||||||
|
|
||||||
@export var pauseType:PauseSystem.PauseType = PauseSystem.PauseType.ENTITY_PAUSED
|
@export var pauseType:PauseSystem.PauseType = PauseSystem.PauseType.ENTITY_PAUSED
|
||||||
@export var entities:Array[OverworldEntity] = []
|
@export var entities:Array[Entity] = []
|
||||||
@export var includeInteractee:bool = true
|
@export var includeInteractee:bool = true
|
||||||
@export var includeInteractor:bool = true
|
@export var includeInteractor:bool = true
|
||||||
|
|
||||||
func start() -> void:
|
func start() -> void:
|
||||||
var ents:Array[OverworldEntity] = entities
|
var ents:Array[Entity] = entities
|
||||||
if interactor != null and includeInteractor:
|
if interactor != null and includeInteractor:
|
||||||
ents.append(interactor)
|
ents.append(interactor)
|
||||||
if interactee != null and includeInteractee:
|
if interactee != null and includeInteractee:
|
||||||
|
@@ -13,12 +13,13 @@ func _ready() -> void:
|
|||||||
for child in get_children():
|
for child in get_children():
|
||||||
if child is QuestObjective:
|
if child is QuestObjective:
|
||||||
objectives.append(child)
|
objectives.append(child)
|
||||||
|
child.onQuestReady(self)
|
||||||
|
|
||||||
func start() -> void:
|
func start() -> void:
|
||||||
questStarted = true
|
questStarted = true
|
||||||
questComplete = false
|
questComplete = false
|
||||||
QUEST.questStarted.emit(questKey)
|
QUEST.questStarted.emit(self)
|
||||||
QUEST.questUpdated.emit(questKey)
|
QUEST.questUpdated.emit(self)
|
||||||
|
|
||||||
func isCompleted() -> bool:
|
func isCompleted() -> bool:
|
||||||
return questComplete
|
return questComplete
|
||||||
|
@@ -1,7 +1,13 @@
|
|||||||
class_name QuestObjective extends Node
|
class_name QuestObjective extends Node
|
||||||
|
|
||||||
# enum Type {
|
enum Type {
|
||||||
# }
|
Item,
|
||||||
|
}
|
||||||
|
|
||||||
@export var objectiveName:String = "Some objective"
|
@export var objectiveName:String = "Some objective"
|
||||||
# @export var objectiveType:Type = Type.Item
|
@export var objectiveType:Type = Type.Item
|
||||||
|
|
||||||
|
var quest:Quest
|
||||||
|
|
||||||
|
func onQuestReady(quest:Quest) -> void:
|
||||||
|
self.quest = quest
|
1
scripts/Sign.gd.uid
Normal file
1
scripts/Sign.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://cctqgee7dumwg
|
@@ -6,9 +6,10 @@ enum QuestKey {
|
|||||||
|
|
||||||
var quests:Dictionary[int, Quest]
|
var quests:Dictionary[int, Quest]
|
||||||
|
|
||||||
signal questStarted(questKey:QuestKey)
|
signal questStarted(quest:Quest)
|
||||||
signal questUpdated(questKey:QuestKey)
|
signal questUpdated(quest:Quest)
|
||||||
signal questCompleted(questKey:QuestKey)
|
signal questCompleted(quest:Quest)
|
||||||
|
# signal questObjectiveCompleted(quest:Quest, objective:QuestObjective)
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
_updateQuests()
|
_updateQuests()
|
||||||
|
@@ -100,7 +100,7 @@ func _onQuestSelected(index:int) -> void:
|
|||||||
func _onQuestObjectiveSelected(index:int) -> void:
|
func _onQuestObjectiveSelected(index:int) -> void:
|
||||||
setQuestObjective(index)
|
setQuestObjective(index)
|
||||||
|
|
||||||
func _onQuestUpdated(questKey:QuestSystem.QuestKey) -> void:
|
func _onQuestUpdated(_q:Quest) -> void:
|
||||||
_updateQuestList()
|
_updateQuestList()
|
||||||
|
|
||||||
func _onCloseClicked() -> void:
|
func _onCloseClicked() -> void:
|
||||||
|
Reference in New Issue
Block a user