mirror of
https://codeberg.org/sunder/sunder.git
synced 2026-07-10 11:24:33 +00:00
89 lines
3.3 KiB
GDScript
89 lines
3.3 KiB
GDScript
# This file is part of sunder.
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU Affero General Public License as
|
|
# published by the Free Software Foundation, either version 3 of the
|
|
# License, or (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU Affero General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
@icon("res://assets/icons/flag_holder.svg")
|
|
## This component is a unified system to manage [Flag] ownership, interaction
|
|
## logic, and visual displays for the owning Entity.
|
|
class_name FlagHolder extends Node3D
|
|
|
|
@export var throw_force:int = 16
|
|
|
|
## The radial progress bar to display the throwing force
|
|
@onready var texture_progress:TextureProgressBar = $ThrowForce
|
|
@onready var timer:Timer = $ThrowTimer
|
|
|
|
## The flag mesh to display when the owner carries the flag
|
|
@onready var mesh: Node3D = $Mesh
|
|
|
|
## The [Flag] instance to hold
|
|
var flag:Flag
|
|
|
|
func _process(_delta: float) -> void:
|
|
if is_visible_in_tree() and not timer.is_stopped():
|
|
var time_elapsed: float = timer.wait_time - timer.time_left
|
|
texture_progress.value = time_elapsed / (timer.wait_time / 2) * 100
|
|
|
|
## This method grabs a [Flag] which set the mesh visible, holds a reference to it
|
|
## and emits the [Flag.grabbed] signal to handle further state changes
|
|
func grab(p_flag:Flag) -> void:
|
|
if p_flag.state < Flag.FlagState.TAKEN:
|
|
flag = p_flag
|
|
flag.grabbed.emit(self)
|
|
show()
|
|
|
|
func drop() -> void:
|
|
if multiplayer.is_server() and flag and flag.state == flag.FlagState.TAKEN:
|
|
flag.global_position = global_position
|
|
flag.global_rotation.y = global_rotation.y
|
|
# inheritance
|
|
if owner is RigidBody3D:
|
|
flag.global_rotation.y = -flag.global_basis.z.dot(owner.linear_velocity)
|
|
flag.apply_impulse.call_deferred(flag.mass * owner.linear_velocity)
|
|
hide()
|
|
flag.dropped.emit(self)
|
|
flag = null
|
|
|
|
## This method displays throw force progress on the [HUD] of a client and upon release
|
|
## it throws the [Flag]. It has no effect when holding no flag or flag is not [member Flag.FlagState.TAKEN]
|
|
func throw(pressed:bool) -> void:
|
|
if flag and flag.state == flag.FlagState.TAKEN:
|
|
if pressed:
|
|
timer.start()
|
|
texture_progress.visible = true
|
|
timer.timeout.connect(func() -> void: texture_progress.visible = false)
|
|
else:
|
|
if timer.is_stopped():
|
|
return
|
|
var time_elapsed:float = timer.wait_time - timer.time_left
|
|
timer.stop()
|
|
texture_progress.visible = false
|
|
|
|
var pumped_force:float = clampf(time_elapsed / timer.wait_time * throw_force, 6., throw_force)
|
|
var throw_velocity:Vector3 = -global_basis.z * pumped_force
|
|
|
|
if owner is Player:
|
|
# player has camera and linear velocity
|
|
flag.global_position = owner.global_position
|
|
flag.global_rotation.y = owner.camera.global_rotation.y
|
|
throw_velocity = -owner.camera.global_basis.z * pumped_force + owner.linear_velocity
|
|
else:
|
|
flag.global_position = global_position
|
|
flag.global_position.y = global_rotation.y
|
|
|
|
var impulse:Vector3 = flag.mass * throw_velocity
|
|
flag.apply_impulse.call_deferred(impulse)
|
|
|
|
hide()
|
|
flag.dropped.emit(self)
|
|
flag = null
|