extends Spatial class_name TPSController # debug camera export var reaper_path: NodePath export var vimp_path: NodePath export var character_path: NodePath onready var character: Character = get_node(character_path) var head: Spatial var cam: Camera var default_camera_trans: Transform var is_in_menu: bool = false export var FOV = 80.0 export var HUD_scene: PackedScene onready var HUD: Control onready var debug_label: Label = $DebugText var mouse_axis: Vector2 = Vector2.ZERO export var mouse_sensitivity: float = 10.0 var cursor_no_enemy: Control var cursor_enemy: Control func set_character(c: Character): if cam: cam.current = false character = c cam = character.back_camera default_camera_trans = cam.transform head = character.head cam.fov = FOV cam.current = true func _ready(): set_character(character) if not Engine.editor_hint: Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) HUD = HUD_scene.instance() add_child(HUD) character.connect("health_changed", self, "update_health") if HUD.has_node("cursor_enemy"): cursor_enemy = HUD.get_node("cursor_enemy") if HUD.has_node("cursor_no_enemy"): cursor_enemy = HUD.get_node("cursor_no_enemy") func get_target() -> Dictionary: var weapon = character.current_weapon var ray_from = cam.global_transform.origin var ray_to = cam.global_transform.basis.z * -20000 var space_state = get_world().direct_space_state var result = space_state.intersect_ray(ray_from, ray_to, [self, weapon]) if not result: return Globals.create_empty_collision_dictionnary(ray_to) else: return result func _physics_process(delta): if Engine.editor_hint: return debug_label.text = "FPS: " + str(Engine.get_frames_per_second()) + " | Objects: " + str(Performance.get_monitor(Performance.OBJECT_COUNT)) # calculate and export target var target = get_target() Globals.target_position = target # cursor change if cursor_no_enemy and cursor_enemy: if target["collider"] and target["collider"] is Entity: cursor_no_enemy.visible = false cursor_enemy.visible = true else: cursor_enemy.visible = false cursor_no_enemy.visible = true # update camera if character.sprinting: cam.set_fov(lerp(cam.fov, FOV * 1.2, delta * 8)) else: cam.set_fov(lerp(cam.fov, FOV, delta * 8)) # head.global_transform.origin = character.global_transform.origin func camera_rotation() -> void: if mouse_axis.length() > 0: var _smoothness := 80 # Get mouse delta var horizontal: float = -(mouse_axis.x * mouse_sensitivity) / _smoothness var vertical: float = -(mouse_axis.y * mouse_sensitivity) / _smoothness mouse_axis = Vector2.ZERO character.rotate_y(deg2rad(horizontal)) var temp_rot: Vector3 = head.rotation_degrees temp_rot += Vector3(vertical, 0, 0) # temp_rot += Vector3(vertical, horizontal, 0) # clamp vertical rotation temp_rot.x = clamp(temp_rot.x, -75, 75) head.rotation_degrees = temp_rot func _input(event: InputEvent) -> void: if Engine.editor_hint: return if not Globals.process_3d_inputs: return if event is InputEventMouseMotion: mouse_axis = event.relative if Input.is_action_pressed("camera_front"): var camera_front_transform = default_camera_trans camera_front_transform = default_camera_trans.translated(Vector3(5, 0, -5)) camera_front_transform = camera_front_transform.rotated(Vector3.UP, deg2rad(-180)) cam.transform = camera_front_transform if Input.is_action_just_released("camera_front"): cam.transform = default_camera_trans if Input.is_action_just_pressed("inp_fire"): character.fire_pressed() if Input.is_action_just_released("inp_fire"): character.fire_released() if Input.is_action_just_pressed("weapon_forward"): character.switch_next_weapon_slot() if Globals.process_3d_inputs and Input.is_action_just_pressed("ui_cancel"): var ingame_menu = preload("res://ui/menus/ingame_menu.tscn").instance() Input.set_mouse_mode(Input.MOUSE_MODE_CONFINED) add_child(ingame_menu) ingame_menu.connect("tree_exited", self, "_ingamemenu_closed") Globals.process_3d_inputs = false if Input.is_action_just_pressed("camera_reaper"): set_character(get_node(reaper_path)) if Input.is_action_just_pressed("camera_vimp"): set_character(get_node(vimp_path)) if Input.is_action_just_pressed("move_jump"): character.jump() if Input.is_action_just_pressed("move_sprint"): character.set_sprint(true) if Input.is_action_just_released("move_sprint"): character.set_sprint(false) func _ingamemenu_closed(): Globals.process_3d_inputs = true Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) func _process(_delta: float) -> void: if Engine.editor_hint: return if Globals.process_3d_inputs: camera_rotation() character.move_axis.x = Input.get_action_strength("move_forward") - Input.get_action_strength("move_backward") character.move_axis.y = Input.get_action_strength("move_right") - Input.get_action_strength("move_left") update_hud() func update_hud() -> void: # for weapon_slot in HUD.find_node("Weapon*"): # for child in weapon_slot.get_children(): # weapon_slot.remove_child(child) for weapon in character.weapons: var weapon_slot = character.get_weapon_slot(weapon) var hud_weapon_slot = HUD.find_node("Weapon%s" % weapon_slot) var weapon_icon: Control = weapon.ui_icon if not weapon_icon.get_parent() == hud_weapon_slot: hud_weapon_slot.add_child(weapon_icon) if character.current_weapon == weapon: hud_weapon_slot.get_node("selected").visible = true else: hud_weapon_slot.get_node("selected").visible = false func update_health() -> void: var current_health = character.health var max_health = character.max_health var hp_percent = current_health/max_health # UI/hp polygon: 0 means 100% hp, 250 means 0% var val = 250 - 250*hp_percent HUD.find_node("hp").texture_offset = Vector2(val, 0)