extends Node signal penalty() signal bonus() const BOX = preload("res://props/box/box.tscn") @export var starting_wage: float = 7.25 @export var wage_penalty: float = 0.50 @export var wage_bonus: float = 0.10 @export var bonus_count: int = 10 @export var conveyor_speed: float = 3 @export var convery_accel: float = 0.007 @export var distancePerBox: float = 2 @export var prop_spawn_dist: float = 0.8 @export_category("Quicktime") @export var dodge_timer_max: float = 0.4 @export var rock_throw_time: float = 0.1 @export var bezos_descent_min: float = 0.1 @export var bezos_descent_max: float = 5.0 @export var bezos_cooldown_min: float = 1.0 @export var bezos_cooldown_max: float = 30.0 @export var stun_timer_max: float = 1.0 @export_group("Props") @export var props: Array[PackedScene] = [] @onready var conveyor: StaticBody3D = %conveyor @onready var box_spawner: Node3D = %box_spawner @onready var prop_spawn: Node3D = %prop_spawn @onready var salary: Label = %salary @onready var conveyor_mesh: MeshInstance3D = %conveyor_mesh @onready var camera: Camera3D = %camera @onready var bezos: Node3D = %bezos @onready var hand_target: Node3D = %hand_target @onready var animtree: AnimationTree = $world/Armondo/AnimationTree @onready var bezostree: AnimationTree = $world/bezos/BALLZ/AnimationTree @onready var throwable: BoneAttachment3D = %throwable @onready var current_prop: PackageItem = null @onready var boxes_in_row: int = 0 @onready var wage: float = starting_wage: set(newWage): wage = newWage salary.text = '$%.2f / hr' % newWage func _ready() -> void: update_conveyor() bezos.visible = false $events/bezos_cooldown.start(randf_range(bezos_cooldown_min, bezos_cooldown_max)) #$events/bezos_cooldown.start(2) Scoring.reset_score() get_node('%arm_ik').start() CameraRumble.grab.connect(anim_grab) func anim_grab(): animtree.set("parameters/shot_grab/request", AnimationNodeOneShot.ONE_SHOT_REQUEST_FIRE) @onready var timer: float = 0 @onready var quicktime_timer: float = 0 @onready var quicktime_tween: Tween = null @onready var dodge_timer: float = 0 @onready var stun_timer: float = 0 func _process(delta: float) -> void: timer += delta $world/light_parent/light.transform.basis = Basis.from_euler(Vector3(0,cos(timer * PI / 3.9) * 0.2,0)) camera.v_offset = (cos(timer * 10) * CameraRumble.rumble) * 0.01 CameraRumble.rumble = clampf(CameraRumble.rumble - delta * 10.0, 0, 1000) var inQuickTime: bool = quicktime_timer > 0 $Control/spacebar1.visible = inQuickTime and bool(int(floor(timer * 10)) % 2 == 0) $Control/spacebar2.visible = inQuickTime and bool(int(floor(timer * 10)) % 2 == 1) quicktime_timer -= delta stun_timer -= delta animtree.set("parameters/blend_stun/blend_amount", clampf(stun_timer * 2, 0, 1.0)) animtree.set("parameters/blend_hold/blend_amount", float(CameraRumble.holding)) # Animate arm transforms var mousePos: Vector3 = CameraRumble.get_mouse_pos() var a: Node3D = $world/Armondo var d: float = a.global_position.distance_to(mousePos) a.global_position = a.global_position.lerp(mousePos - Vector3(0,0,0.5), delta * 2 * clampf(d, 0, 1)) hand_target.global_position = CameraRumble.get_mouse_pos() var t: Transform3D = Transform3D(Basis(), a.global_position).looking_at(mousePos) t.origin = mousePos hand_target.global_transform = t if dodge_timer > 0: dodge_timer -= delta if dodge_timer <= 0: quicktime_tween = make_quicktime_tween() quicktime_tween.tween_property(camera, 'global_transform', $world/cam_default.global_transform, dodge_timer_max * 0.7) func _input(event: InputEvent) -> void: if event.is_action_pressed("fullscreen"): var w: Window = get_viewport().get_window() match w.mode: Window.MODE_FULLSCREEN: w.mode = Window.MODE_WINDOWED _: w.mode = Window.MODE_FULLSCREEN if event.is_action_pressed("exit"): get_tree().quit() if event.is_action_pressed("quicktime_dodge") and dodge_timer <= 0 and stun_timer < 0: dodge_timer = dodge_timer_max quicktime_tween = make_quicktime_tween() quicktime_tween.tween_property(camera, 'global_transform', $world/cam_dodge.global_transform, dodge_timer_max * 0.7) func make_quicktime_tween() -> Tween: if is_instance_valid(quicktime_tween) and quicktime_tween.is_running(): quicktime_tween.kill() var t = camera.create_tween() t.set_ease(Tween.EASE_IN_OUT) t.set_trans(Tween.TRANS_CUBIC) return t @onready var boxTimer: float = 0 func _physics_process(delta: float) -> void: boxTimer -= delta * conveyor_speed conveyor_mesh conveyor_speed += delta * convery_accel update_conveyor() if boxTimer < 0: var b: Package = BOX.instantiate() box_spawner.add_child(b) boxTimer += distancePerBox if (not is_instance_valid(current_prop)) or current_prop.global_position.distance_to(prop_spawn.global_position) > prop_spawn_dist: current_prop = spawn_random_prop(prop_spawn) func spawn_random_prop(parent: Node3D) -> PackageItem: var scn = props.pick_random() as PackedScene var prop: PackageItem = scn.instantiate() parent.add_child(prop) return prop func update_conveyor(): conveyor.constant_linear_velocity = Vector3(-conveyor_speed,0,0) var shade: ShaderMaterial = conveyor_mesh.get_surface_override_material(1) shade.set_shader_parameter("speed", conveyor_speed) ## PACKAGE VALIDATION (was it packed properly?) func _on_box_entered(body_rid: RID, body: Node3D, body_shape_index: int, local_shape_index: int) -> void: if body is Package: if body.counted: return body.counted = true Scoring.increment_boxes() # print("box has: ", body.items.size()) # Ensure package is loaded, but don't penalize overloaded packages (players tend to do that when conveyor is slow) if not body.items.size() > 0: do_penalty() boxes_in_row = 0 else: Scoring.increment_score() %points.text = str(Scoring.score) + " pts" boxes_in_row += 1 if boxes_in_row >= bonus_count: boxes_in_row = 0 do_bonus() for item in body.items: item.queue_free() body.queue_free() func do_bonus(): wage += wage_bonus emit_signal("bonus") func do_penalty(): wage -= wage_penalty if wage < 0: #get_tree().quit() get_tree().call_deferred("change_scene_to_file", "res://score_screen.tscn") return emit_signal("penalty") func _on_trash(body_rid: RID, body: Node3D, body_shape_index: int, local_shape_index: int) -> void: body.queue_free() ## QUICKTIME EVENT @onready var bezos_timer: float = 0 func quicktime_start(): bezos.visible = true bezos_timer = randf_range(bezos_descent_min,bezos_descent_max) var qt: Tween = create_tween() qt.set_ease(Tween.EASE_OUT) qt.set_trans(Tween.TRANS_QUAD) var newPos: Vector3 = bezos.position * Vector3(1,0,1) qt.tween_property(bezos, 'position', newPos + Vector3(0,2.5,0), bezos_timer) qt.tween_callback(quicktime_run) quicktime_timer = bezos_timer + rock_throw_time $events/bezos_cooldown.start(bezos_timer * 2 + rock_throw_time + randf_range(bezos_cooldown_min, bezos_cooldown_max)) func quicktime_end(): var qt: Tween = create_tween() qt.set_ease(Tween.EASE_IN) qt.set_trans(Tween.TRANS_QUAD) var newPos: Vector3 = bezos.position * Vector3(1,0,1) qt.tween_property(bezos, 'position', newPos + Vector3(0,10,0), bezos_timer) qt.tween_callback(quicktime_hide) func quicktime_run(): # play bezos animation # start rock timer $events/rock_timer.start(rock_throw_time) bezostree.set("parameters/shot_attack/request", AnimationNodeOneShot.ONE_SHOT_REQUEST_FIRE) func quicktime_check(): var prop = spawn_random_prop($world) prop.global_transform = throwable.global_transform prop.linear_velocity = Vector3(0,0,10) prop.touched.emit() if dodge_timer > 0: #print("successfull dodge") pass else: $audio/oof.play() stun_timer = stun_timer_max quicktime_tween = make_quicktime_tween() quicktime_tween.set_parallel(false) quicktime_tween.tween_property(camera, 'global_transform', $world/cam_stun.global_transform, stun_timer_max * 0.2) quicktime_tween.tween_property(camera, 'global_transform', $world/cam_stun.global_transform, stun_timer_max * 0.5) quicktime_tween.tween_property(camera, 'global_transform', $world/cam_default.global_transform, stun_timer_max * 0.3) quicktime_end() func quicktime_hide(): bezos.visible = false