Extensive work on animations and partially functional level keys, new UI gears but needs rounding error correction. Particle preloader added.
This commit is contained in:
@@ -19,6 +19,7 @@ var pawns : Dictionary = {
|
||||
|
||||
const blinder_template = preload("res://templates/blinder.tscn")
|
||||
const one_shot_template = preload("res://templates/one_shot.tscn")
|
||||
const level_loading_template = preload("res://scenes/vrep_loading.tscn")
|
||||
|
||||
const story_level = preload("res://scenes/manufactory.tscn")
|
||||
const vs_com_level = preload("res://scenes/test_level.tscn")
|
||||
@@ -29,6 +30,7 @@ var cmd_args : Dictionary = {}
|
||||
var player : PawnController
|
||||
var hud : HUD
|
||||
var level : Level
|
||||
var level_loading
|
||||
var mode : Modes = Modes.STORY
|
||||
var multiplayer_game : bool = false
|
||||
var num_players : int = 1
|
||||
@@ -64,6 +66,10 @@ func setup_player(pc : PawnController) -> void:
|
||||
func is_multiplayer() -> bool:
|
||||
return multiplayer_game
|
||||
|
||||
@rpc("call_local", "any_peer", "reliable")
|
||||
func show_level_loading() -> void:
|
||||
level_loading = level_loading_template.instantiate()
|
||||
add_child(level_loading)
|
||||
|
||||
func start_level(pawn_dict : Dictionary[int, StringName]) -> void:
|
||||
pawns_selected = pawn_dict
|
||||
@@ -73,31 +79,41 @@ func start_level(pawn_dict : Dictionary[int, StringName]) -> void:
|
||||
for i in Multiplayer.players.values():
|
||||
level_synced[i] = false
|
||||
level_synced[1] = true
|
||||
show_level_loading.rpc()
|
||||
match(mode):
|
||||
Modes.STORY:
|
||||
switch_scene(story_level, false)
|
||||
Modes.VS_COM:
|
||||
switch_scene(vs_com_level, false)
|
||||
Modes.VS_MAN:
|
||||
switch_scene(vs_man_level)
|
||||
switch_scene(vs_man_level, true)
|
||||
|
||||
func switch_scene(packed_scene : PackedScene, spawn : bool = true) -> void:
|
||||
func switch_scene(packed_scene : PackedScene, spawn : bool = true, is_level : bool = true) -> void:
|
||||
var blinder = blinder_template.instantiate() as TextureRect
|
||||
var tween = create_tween()
|
||||
blinder.self_modulate.a = 0
|
||||
add_child(blinder)
|
||||
tween.tween_property(blinder, "self_modulate:a", 1, .15)
|
||||
await tween.tween_property(blinder, "self_modulate:a", 1, .15).finished
|
||||
tween = create_tween()
|
||||
if spawn:
|
||||
var spawner = get_tree().get_first_node_in_group("level_spawner") as MultiplayerSpawner
|
||||
tween.tween_callback(spawner.add_child.bind(packed_scene.instantiate(), true))
|
||||
tween.tween_callback(spawner.add_child.bind(packed_scene.instantiate(), true)).finished
|
||||
var current_scene = get_tree().get_first_node_in_group("scenes")
|
||||
if current_scene:
|
||||
tween.tween_callback(current_scene.queue_free)
|
||||
current_scene.process_mode=Node.PROCESS_MODE_DISABLED
|
||||
else:
|
||||
tween.tween_callback(get_tree().change_scene_to_packed.bind(packed_scene))
|
||||
tween.tween_property(blinder, "self_modulate:a", 0, .15)
|
||||
tween.tween_callback(blinder.queue_free)
|
||||
tween.tween_callback(get_tree().change_scene_to_packed.bind(packed_scene)).finished
|
||||
if is_level:
|
||||
await tween.tween_interval(0.1).finished
|
||||
tween = create_tween()
|
||||
level.level_started.connect(level_loading.queue_free)
|
||||
tween.tween_property(blinder, "self_modulate:a", 0, .15)
|
||||
tween.tween_callback(blinder.queue_free)
|
||||
else:
|
||||
tween.tween_property(blinder, "self_modulate:a", 0, .15)
|
||||
tween.tween_callback(blinder.queue_free)
|
||||
|
||||
|
||||
@rpc("call_local", "any_peer", "reliable")
|
||||
func start_pawn_select(mplayer : bool) -> void:
|
||||
@@ -139,8 +155,6 @@ func check_level_ready() -> void:
|
||||
for id in level_synced:
|
||||
if level_synced[id] == false:
|
||||
level_ready = false
|
||||
if level_ready:
|
||||
level.setup()
|
||||
|
||||
func oneshot(stream : AudioStream) -> void:
|
||||
var shot = one_shot_template.instantiate()
|
||||
@@ -149,3 +163,6 @@ func oneshot(stream : AudioStream) -> void:
|
||||
level.add_child(shot)
|
||||
else:
|
||||
add_child(shot)
|
||||
|
||||
func go_to_title_screen() -> void:
|
||||
get_tree().change_scene_to_file("res://scenes/title_screen.tscn")
|
||||
|
||||
@@ -87,6 +87,7 @@ func _process(delta : float) -> void:
|
||||
pawns_selected[selector.player_id] = portraits[selector.selection].pawn.name
|
||||
if locked:
|
||||
Game.start_level(pawns_selected)
|
||||
process_mode = Node.PROCESS_MODE_DISABLED
|
||||
|
||||
if selectors[Multiplayer.id].selected != false:
|
||||
return
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
class_name Pickup extends Area3D
|
||||
class_name Collectable extends Area3D
|
||||
|
||||
|
||||
enum Type{
|
||||
DATABLOCK,
|
||||
DATAKEY,
|
||||
INTEGRITY,
|
||||
SCAN,
|
||||
BASIC_HACK,
|
||||
@@ -13,5 +13,5 @@ enum Type{
|
||||
|
||||
func _on_body_entered(body: Node3D) -> void:
|
||||
if body is PawnController:
|
||||
body.pickup(type)
|
||||
body.collect(type)
|
||||
queue_free()
|
||||
|
||||
18
scripts/collectable_depot.gd
Normal file
18
scripts/collectable_depot.gd
Normal file
@@ -0,0 +1,18 @@
|
||||
extends CSGCylinder3D
|
||||
|
||||
var time_remaining : float
|
||||
var collectable : Collectable
|
||||
|
||||
func generate_collectable() -> void:
|
||||
pass
|
||||
func _process(delta: float) -> void:
|
||||
if time_remaining > 0:
|
||||
time_remaining -= delta
|
||||
|
||||
if time_remaining <= 0 and collectable == null:
|
||||
generate_collectable()
|
||||
time_remaining = Game.level.collectable_drop_time
|
||||
|
||||
|
||||
func _on_collectable_collected() -> void:
|
||||
collectable = null
|
||||
1
scripts/collectable_depot.gd.uid
Normal file
1
scripts/collectable_depot.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cpemfkebfflnv
|
||||
@@ -1 +1,11 @@
|
||||
class_name CombatTarget extends StaticBody3D
|
||||
|
||||
|
||||
func can_hurt() -> bool:
|
||||
return true
|
||||
|
||||
func can_poison() -> bool:
|
||||
return false
|
||||
|
||||
func hurt(amt : int) -> void:
|
||||
pass
|
||||
|
||||
@@ -10,20 +10,20 @@ const action_value : Dictionary[String, int] = {
|
||||
|
||||
const icon_textures : Array = [
|
||||
{
|
||||
"normal" : preload("res://visuals/images/icons/button-detonate.png"),
|
||||
"pressed" : preload("res://visuals/images/icons/button-detonate-hit.png")
|
||||
"normal" : preload("res://visuals/images/icons/detect button.png"),
|
||||
"pressed" : preload("res://visuals/images/icons/lit detect button.png")
|
||||
},
|
||||
{
|
||||
"normal" : preload("res://visuals/images/icons/button-hack.png"),
|
||||
"pressed" : preload("res://visuals/images/icons/button-hack-hit.png")
|
||||
"normal" : preload("res://visuals/images/icons/install button.png"),
|
||||
"pressed" : preload("res://visuals/images/icons/lit install button.png")
|
||||
},
|
||||
{
|
||||
"normal" : preload("res://visuals/images/icons/button-detect.png"),
|
||||
"pressed" : preload("res://visuals/images/icons/button-detect-hit.png")
|
||||
"normal" : preload("res://visuals/images/icons/switch button.png"),
|
||||
"pressed" : preload("res://visuals/images/icons/lit switch button.png")
|
||||
},
|
||||
{
|
||||
"normal" : preload("res://visuals/images/icons/button-attack.png"),
|
||||
"pressed" : preload("res://visuals/images/icons/button-attack-hit.png")
|
||||
"normal" : preload("res://visuals/images/icons/melee attack button.png"),
|
||||
"pressed" : preload("res://visuals/images/icons/lit melee attack button.png")
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
@@ -24,4 +24,5 @@ func setup(h_owner, dam) -> void:
|
||||
func _on_body_entered(body: Node3D) -> void:
|
||||
if body.can_hurt():
|
||||
body.hurt(damage)
|
||||
body.poison(damage, 2.0)
|
||||
if body.can_poison():
|
||||
body.poison(damage, 2.0)
|
||||
|
||||
@@ -5,6 +5,7 @@ class_name HUD extends Control
|
||||
@onready var p2_healthbar : HealthBar = %P2HealthBar
|
||||
@onready var control_display : ControlDisplay = %ControlDisplay
|
||||
@onready var ammo_label : Label = %AmmoLabel
|
||||
#@onready var keys_display : LevelKeysDisplay = %LevelKeysDisplay
|
||||
func _ready() -> void:
|
||||
Game.hud = self
|
||||
|
||||
@@ -28,3 +29,6 @@ func set_ammo(ammo : int) -> void:
|
||||
func _on_ammo_changed(current : int, _max_amt : int) -> void:
|
||||
set_ammo(current)
|
||||
|
||||
func _on_keys_changed() -> void:
|
||||
#keys_display.update()
|
||||
pass
|
||||
|
||||
@@ -12,6 +12,7 @@ const map_marker_templates : Dictionary[String, PackedScene] = {
|
||||
const pawn_controller = preload("res://templates/pawn_controller.tscn")
|
||||
const hack_template = preload("res://templates/hack.tscn")
|
||||
const camera_template = preload("res://templates/pawn_camera.tscn")
|
||||
const particle_preloader_template = preload("res://templates/particle_preloader.tscn")
|
||||
|
||||
const camera_offset = Vector3(0, 10, 5.25)
|
||||
|
||||
@@ -27,15 +28,25 @@ const camera_offset = Vector3(0, 10, 5.25)
|
||||
@onready var multiplayer_level_setup : MultiplayerLevelSetup = %MultiplayerLevelSetup
|
||||
@export var difficulty : int = 1
|
||||
|
||||
var keys : Array[int] = []
|
||||
@export var max_keys = 7
|
||||
|
||||
var hacks : Dictionary[Vector3i, Hack] = {}
|
||||
var pawns : Dictionary[int, PawnController] = {}
|
||||
var cameras : Dictionary[int, PawnCamera] = {}
|
||||
var map_markers : Dictionary[Object, MapMarker] = {}
|
||||
|
||||
signal level_started()
|
||||
signal keys_changed()
|
||||
|
||||
func _ready() -> void:
|
||||
var preloader = particle_preloader_template.instantiate()
|
||||
add_child(preloader)
|
||||
process_mode=Node.PROCESS_MODE_DISABLED
|
||||
Game.level = self
|
||||
if max_keys > 0 and Game.hud:
|
||||
keys_changed.connect(Game.hud._on_keys_changed)
|
||||
keys_changed.emit()
|
||||
if Game.mode == Game.Modes.STORY:
|
||||
setup()
|
||||
#add_level_hack.call_deferred(Hack.Type.PURGE, Vector3.ZERO, Vector3i(-2,2,0))
|
||||
@@ -66,7 +77,7 @@ func spawn_players_singleplayer() -> void:
|
||||
pc.setup(1, Game.pawns_selected[1])
|
||||
add_pawn_camera(pc)
|
||||
cameras[1].register_pawn(1)
|
||||
process_mode=Node.PROCESS_MODE_INHERIT
|
||||
start_level()
|
||||
|
||||
func spawn_players_multiplayer() -> void:
|
||||
var count = 0
|
||||
@@ -107,7 +118,10 @@ func spawn_players_multiplayer() -> void:
|
||||
|
||||
@rpc("authority", "call_local")
|
||||
func start_level() -> void:
|
||||
await get_tree().create_timer(3.0).timeout
|
||||
Game.hud.visible = true
|
||||
process_mode=Node.PROCESS_MODE_INHERIT
|
||||
level_started.emit()
|
||||
|
||||
|
||||
func is_square_detected(crd) -> bool:
|
||||
@@ -222,3 +236,62 @@ func add_level_hack(type : Hack.Type, facing : Vector3, crd : Vector3i) -> void:
|
||||
var hack = hack_template.instantiate()
|
||||
hack.setup(type, facing, -1)
|
||||
add_hack(hack, crd)
|
||||
|
||||
|
||||
func show_win_screen() -> void:
|
||||
#TODO: INITIATE WIN SCREEN
|
||||
pass
|
||||
|
||||
func show_lose_screen() -> void:
|
||||
#TODO: INITIATE LOSE SCREEN
|
||||
pass
|
||||
|
||||
@rpc("authority", "call_local")
|
||||
func end_level(winner_id : int) -> void:
|
||||
if Multiplayer.id == winner_id:
|
||||
show_win_screen()
|
||||
else:
|
||||
show_lose_screen()
|
||||
var win_tween := create_tween()
|
||||
win_tween.set_pause_mode(Tween.TWEEN_PAUSE_PROCESS)
|
||||
win_tween.tween_property(get_tree(), "paused", true, 0)
|
||||
win_tween.tween_interval(5)
|
||||
win_tween.tween_property(get_tree(), "paused", false, 0)
|
||||
#TODO: MOVE TO THE REMATCH SCREEN
|
||||
|
||||
func check_survival_win() -> void:
|
||||
var dead = 0
|
||||
var last_living = -1
|
||||
for pc : PawnController in pawns.values():
|
||||
if pc.is_dead():
|
||||
dead += 1
|
||||
else:
|
||||
last_living = pc.id
|
||||
|
||||
if dead == len(pawns) - 1:
|
||||
end_level.rpc(last_living)
|
||||
|
||||
func check_data_win() -> void:
|
||||
var pcounts : Dictionary = {}
|
||||
for id in pawns.keys():
|
||||
pcounts[id] = 0
|
||||
|
||||
var highest = 0
|
||||
var high_id = -1
|
||||
for key in keys:
|
||||
pcounts[key] += 1
|
||||
if pcounts[key] > highest:
|
||||
highest = pcounts[key]
|
||||
high_id = key
|
||||
if highest >= ceil(max_keys / 2.0):
|
||||
end_level.rpc(high_id)
|
||||
|
||||
|
||||
@rpc("any_peer", "call_local")
|
||||
func award_data_key(player_id : int) -> void:
|
||||
if len(keys) >= max_keys:
|
||||
return
|
||||
keys.append(player_id)
|
||||
keys_changed.emit()
|
||||
if Multiplayer.is_host():
|
||||
check_data_win()
|
||||
|
||||
19
scripts/level_keys_display.gd
Normal file
19
scripts/level_keys_display.gd
Normal file
@@ -0,0 +1,19 @@
|
||||
extends Control
|
||||
|
||||
var keys_slots : Array = []
|
||||
|
||||
func _ready() -> void:
|
||||
for slot : LevelKeysSlot in $KeyIcons.get_children():
|
||||
slot.reset()
|
||||
keys_slots.append(slot)
|
||||
|
||||
func update() -> void:
|
||||
if Game.level == null:
|
||||
return
|
||||
#keys = Game.level.keys
|
||||
#for i in range(len(keys_slots)):
|
||||
#if i < len(keys):
|
||||
#keys_slots[i].set(keys[i])
|
||||
#else:
|
||||
#keys_slots[i].visible = false
|
||||
pass
|
||||
1
scripts/level_keys_display.gd.uid
Normal file
1
scripts/level_keys_display.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://3imn5hdj8u25
|
||||
7
scripts/level_keys_slot.gd
Normal file
7
scripts/level_keys_slot.gd
Normal file
@@ -0,0 +1,7 @@
|
||||
class_name LevelKeysSlot extends TextureRect
|
||||
|
||||
|
||||
func reset() -> void:
|
||||
#TODO: Make this reset their appearance and visibility
|
||||
visible = false
|
||||
pass
|
||||
1
scripts/level_keys_slot.gd.uid
Normal file
1
scripts/level_keys_slot.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://b271comgnsm7k
|
||||
@@ -1,23 +1 @@
|
||||
extends MultiplayerSpawner
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
print(Multiplayer.get_local_ip())
|
||||
if Game.net_test:
|
||||
await get_tree().create_timer(0.25).timeout
|
||||
Multiplayer.join_game("123")
|
||||
|
||||
else:
|
||||
Multiplayer.handle = "456"
|
||||
Multiplayer.become_host()
|
||||
await get_tree().create_timer(2).timeout
|
||||
var pids = Multiplayer.players.values()
|
||||
if Multiplayer.is_host():
|
||||
var ps : Dictionary[int, PawnBaseData] = {
|
||||
pids[0] : load("res://data/pawns/van_reily.tres"),
|
||||
pids[1] : load("res://data/pawns/lou_riche.tres")
|
||||
}
|
||||
Game.start_level(ps)
|
||||
|
||||
func _on_level_spawned(_node: Node) -> void:
|
||||
Game.level_spawned.rpc_id(1, Multiplayer.id)
|
||||
|
||||
11
scripts/particle_preloader.gd
Normal file
11
scripts/particle_preloader.gd
Normal file
@@ -0,0 +1,11 @@
|
||||
extends Node3D
|
||||
|
||||
signal finished()
|
||||
|
||||
func _ready() -> void:
|
||||
for child in get_children():
|
||||
child.restart()
|
||||
|
||||
await get_tree().create_timer(.1).timeout
|
||||
finished.emit()
|
||||
queue_free()
|
||||
1
scripts/particle_preloader.gd.uid
Normal file
1
scripts/particle_preloader.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://wgdonh5sgkbj
|
||||
@@ -52,9 +52,9 @@ var poison_strength : int = 0
|
||||
var poison_time_remaining : float = 0
|
||||
var poison_pulse_timer : float
|
||||
|
||||
var melee_range : float = 3.0
|
||||
var melee_range : float = 1.25
|
||||
var can_melee : bool = false
|
||||
var ranged_range : float = 6
|
||||
var ranged_range : float = 7
|
||||
var attack_timer : float = 0
|
||||
var melee_recovery_time : float = .75
|
||||
var ranged_recovery_time : float = 0.25
|
||||
@@ -348,14 +348,16 @@ func check_attack_target() -> void:
|
||||
var ranged_sq = ranged_range * ranged_range
|
||||
var melee_sq = melee_range * melee_range
|
||||
var space_state = get_world_3d().direct_space_state
|
||||
var list = get_tree().get_nodes_in_group("combat")
|
||||
|
||||
combat_target = null
|
||||
# use global coordinates, not local to node
|
||||
for target : Node3D in get_tree().get_nodes_in_group("combat"):
|
||||
if target == self:
|
||||
continue
|
||||
#Check to see if they're within the correct direction
|
||||
var angle = abs(facing.angle_to(target.global_position - global_position))
|
||||
var xz_diff = (target.global_position - global_position).normalized()
|
||||
xz_diff.y = 0
|
||||
var angle = abs(facing.angle_to(xz_diff))
|
||||
if angle > PI / 4.0:
|
||||
continue
|
||||
#Determine if they're within shot range
|
||||
@@ -364,8 +366,8 @@ func check_attack_target() -> void:
|
||||
continue
|
||||
|
||||
#Raycast to see if they're a valid target
|
||||
var start = global_position + Vector3(0,1,0)
|
||||
var end = target.global_position + Vector3(0,1,0)
|
||||
var start = global_position + Vector3(0,.5,0)
|
||||
var end = target.global_position + Vector3(0,.5,0)
|
||||
var query = PhysicsRayQueryParameters3D.create(start, end, 1|2, [self])
|
||||
var result = space_state.intersect_ray(query)
|
||||
if !result or (result.collider is not PawnController and result.collider is not CombatTarget):
|
||||
@@ -384,6 +386,8 @@ func check_attack_target() -> void:
|
||||
can_melee = false
|
||||
if ranged_closest != null:
|
||||
combat_target = ranged_closest
|
||||
else:
|
||||
combat_target = null
|
||||
combat_target_changed.emit(melee_closest != null)
|
||||
|
||||
func try_install_hack() -> void:
|
||||
@@ -629,6 +633,9 @@ func detonate() -> void:
|
||||
for hack : Hack in switch_list:
|
||||
hack.activate()
|
||||
|
||||
func can_poison() -> bool:
|
||||
return true
|
||||
|
||||
func is_poisoned() -> bool:
|
||||
return poison_time_remaining > 0
|
||||
|
||||
@@ -699,7 +706,8 @@ func _on_melee_hit(_body : Node3D) -> void:
|
||||
#TODO: WRITE THE MELEE DAMAGE CODE
|
||||
pass
|
||||
|
||||
|
||||
func is_flung() -> bool:
|
||||
return state == State.FLUNG
|
||||
func is_attacking() -> bool:
|
||||
return state == State.RANGED_ATTACKING or state == State.MELEE_ATTACKING
|
||||
|
||||
@@ -742,30 +750,34 @@ func add_hack(type : Hack.Type) -> void:
|
||||
hack_list_changed.emit(data.hacks, data.active_hack)
|
||||
|
||||
func add_random_hack(advanced : bool) -> void:
|
||||
#Get their current hack list
|
||||
var choices : Dictionary = {
|
||||
Hack.Type.DESTROY: true,
|
||||
Hack.Type.PURGE: true,
|
||||
Hack.Type.INFECT: true,
|
||||
Hack.Type.REDIRECT: true,
|
||||
Hack.Type.TRIGGER: true,
|
||||
Hack.Type.CONTAIN: true
|
||||
}
|
||||
for hd : PawnLevelData.HackData in data.hacks:
|
||||
if hd.max_quantity == 9:
|
||||
choices.erase(hd.type)
|
||||
|
||||
var choice = choices.keys().pick_random()
|
||||
add_hack.rpc(choice)
|
||||
if !advanced:
|
||||
#Get their current hack list
|
||||
var choices : Dictionary = {
|
||||
Hack.Type.DESTROY: true,
|
||||
Hack.Type.PURGE: true,
|
||||
Hack.Type.INFECT: true,
|
||||
Hack.Type.REDIRECT: true,
|
||||
Hack.Type.TRIGGER: true,
|
||||
Hack.Type.CONTAIN: true
|
||||
}
|
||||
for hd : PawnLevelData.HackData in data.hacks:
|
||||
if hd.max_quantity == 9:
|
||||
choices.erase(hd.type)
|
||||
|
||||
var choice = choices.keys().pick_random()
|
||||
add_hack.rpc(choice)
|
||||
#Create a list of possible hacks, omitting any that they have the max in already
|
||||
#Randomly pick one
|
||||
#RPC Add hack to them
|
||||
#TODO: Add random hack spawning using RPCs
|
||||
pass
|
||||
|
||||
func collect_data_key() -> void:
|
||||
Game.level.award_data_key.rpc(id)
|
||||
|
||||
func pickup(type : Pickup.Type) -> void:
|
||||
func collect(type : Collectable.Type) -> void:
|
||||
if id != Multiplayer.id:
|
||||
return
|
||||
match(type):
|
||||
Pickup.Type.DATABLOCK: print("Datablock picked up!")
|
||||
Pickup.Type.BASIC_HACK: add_random_hack(false)
|
||||
Collectable.Type.DATAKEY: collect_data_key()
|
||||
Collectable.Type.BASIC_HACK: add_random_hack(false)
|
||||
|
||||
@@ -74,7 +74,7 @@ func _process(_delta: float) -> void:
|
||||
switch_menu(wrapi(menu_choice + menu_dir, 0, len(menu_list)))
|
||||
if Input.is_action_just_pressed("ui_accept"):
|
||||
Game.mode = menu_list[menu_choice].mode
|
||||
Game.switch_scene(menu_list[menu_choice].scene, false)
|
||||
Game.switch_scene(menu_list[menu_choice].scene, false, false)
|
||||
|
||||
|
||||
func switch_menu(new_choice : int) -> void:
|
||||
|
||||
14
scripts/ui_gear.gd
Normal file
14
scripts/ui_gear.gd
Normal file
@@ -0,0 +1,14 @@
|
||||
extends Sprite2D
|
||||
@export var gradient : Gradient
|
||||
@export var teeth : int = 1
|
||||
@export var time_per_tooth : float = 5.0
|
||||
@export var clockwise : bool
|
||||
var step : float
|
||||
|
||||
func _ready() -> void:
|
||||
step = 2.0 * PI / (teeth * time_per_tooth)
|
||||
modulate = gradient.sample(randf())
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
var angle = step * delta
|
||||
rotate(angle if clockwise else -angle)
|
||||
1
scripts/ui_gear.gd.uid
Normal file
1
scripts/ui_gear.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dprv45o1blwe8
|
||||
Reference in New Issue
Block a user