Godot-RTS-Template/core/scripts/entity.gd
2025-07-23 15:07:31 +02:00

84 lines
2.7 KiB
GDScript

@icon('uid://br8ndde8qty32')
extends Node
class_name Entity
## Base entity class for everything not static.
##
## Should be the parent of every units, buildings,
## npc, loot, and everything that the player can interact with
##
## Is a node, because we want to deactivate rendering when out of camera and only simulating the world.
## Plus, only the entity is replicated in multiplayer
func _ready() -> void:
add_to_group('entity')
add_to_group('selectable-entity')
## Check if the entity is contained in the [Rect2] [param selection_box] of the player.
## Need the [Camera3D] of the player to work
func is_in_selection(selection_box:Rect2,player_cam:Camera3D) -> bool:
if selection_box.size: # Checking if size is 0,0
var p = player_cam.unproject_position(global_position)
return selection_box.has_point(p)
return false
## Check if the entity is under the raycast (usually made by [method SelectionManager.check_raycast])
## and colliding with entity bouding box
func is_under_mouse(raycast:Dictionary) -> bool:
if raycast:
var aabb:AABB = get_entity_aabb()
return aabb.has_point(raycast.position)
return false
## Calculate the node bouding box
func get_entity_aabb(node: Node3D = self, ignore_top_level: bool = true, bounds_transform: Transform3D = Transform3D()) -> AABB:
if node == null: return AABB()
var box: AABB
var node_transform: Transform3D
# we are going down the child chain, we want the aabb of each subsequent node to be on the same axis as the parent
if bounds_transform.is_equal_approx(Transform3D()):
node_transform = node.global_transform
else:
node_transform = bounds_transform
# no more nodes. return default aabb
if node == null:
return AABB(Vector3(-0.2, -0.2, -0.2), Vector3(0.4, 0.4, 0.4))
# makes sure the transform we get isn't distorted
var top_xform : Transform3D = node_transform.affine_inverse() * node.global_transform
# convert the node into visualinstance3D to access get_aabb() function.
var visual_result : VisualInstance3D = node as VisualInstance3D
if visual_result != null:
box = visual_result.get_aabb()
else:
box = AABB()
# xforms the transform with the box aabb for proper alignment I believe?
box = top_xform * box
# recursion
for i : int in node.get_child_count():
var child : Node3D = node.get_child(i) as Node3D
if child && !(ignore_top_level && child.top_level):
var child_box : AABB = get_entity_aabb(child, ignore_top_level, transform)
box = box.merge(child_box)
return box
func select():
add_to_group('selected-by-'+str(get_tree().get_multiplayer().get_unique_id()))
print(self.name," selected"," by "+str(get_tree().get_multiplayer().get_unique_id()))
func deselect():
remove_from_group('selected-by-'+str(get_tree().get_multiplayer().get_unique_id()))
print(self.name," unselected")