174 lines
5.8 KiB
GDScript
174 lines
5.8 KiB
GDScript
extends CharacterBody3D
|
|
|
|
# Movement settings
|
|
@export var speed: float = 5.0
|
|
@export var jump_force: float = 10.0
|
|
@export var gravity: float = 20.0
|
|
@export var push_force: float = 10.0 # Force applied to RigidBody3D
|
|
@export var mouse_sensitivity: float = 0.002 # Mouse sensitivity
|
|
@export var max_look_angle: float = 90.0 # Maximum vertical look angle
|
|
@export var interaction_range: float = 3.0 # Range for interacting with objects
|
|
@export var interaction_strenght: int = 10
|
|
|
|
# Ghost mode settings
|
|
@export var ghost_mode: bool = false # Toggle ghost mode
|
|
@export var ghost_speed: float = 10.0 # Movement speed in ghost mode
|
|
|
|
# Collision layers
|
|
@export var normal_collision_layer: int = 1 # Layer 1: Normal
|
|
@export var ghost_collision_layer: int = 2 # Layer 2: Ghost
|
|
|
|
# Light flicker settings
|
|
@export var flicker_interval: float = 0.1 # Time between flickers
|
|
@export var flicker_intensity: float = 0.5 # Intensity of flicker (0 to 1)
|
|
@export var flicker_range: float = 10.0 # Range within which lights flicker
|
|
var flicker_timer: float = 0.0
|
|
|
|
func _ready() -> void:
|
|
# Capture the mouse so it doesn't leave the game window
|
|
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
|
|
# Initialize collision layer based on starting mode
|
|
update_collision_layer()
|
|
|
|
func _input(event: InputEvent) -> void:
|
|
if event is InputEventMouseMotion:
|
|
# Rotate the player horizontally (yaw)
|
|
rotate_y(-event.relative.x * mouse_sensitivity)
|
|
|
|
# Rotate the camera vertically (pitch)
|
|
$Camera3D.rotate_x(-event.relative.y * mouse_sensitivity)
|
|
$Camera3D.rotation_degrees.x = clamp($Camera3D.rotation_degrees.x, -max_look_angle, max_look_angle)
|
|
|
|
# Check for interaction input (e.g., pressing "E")
|
|
if event.is_action_pressed("interact"):
|
|
interact_with_object()
|
|
|
|
# Toggle ghost mode (e.g., pressing "G")
|
|
if event.is_action_pressed("toggle_ghost_mode"):
|
|
if ghost_mode:
|
|
interaction_strenght=10
|
|
else:
|
|
interaction_strenght=50
|
|
ghost_mode = !ghost_mode
|
|
print("Ghost mode: ", ghost_mode)
|
|
# Update collision layer when toggling ghost mode
|
|
update_collision_layer()
|
|
|
|
func update_collision_layer() -> void:
|
|
if ghost_mode:
|
|
# Set collision layer and mask for ghost mode
|
|
collision_layer = ghost_collision_layer
|
|
collision_mask = ghost_collision_layer
|
|
else:
|
|
# Set collision layer and mask for normal mode
|
|
collision_layer = normal_collision_layer
|
|
collision_mask = normal_collision_layer
|
|
|
|
func _physics_process(delta: float) -> void:
|
|
if ghost_mode:
|
|
ghost_movement(delta)
|
|
flicker_lights(delta)
|
|
else:
|
|
normal_movement(delta)
|
|
|
|
func normal_movement(delta: float) -> void:
|
|
var input_direction: Vector3 = Vector3.ZERO
|
|
|
|
# Get input for movement
|
|
if Input.is_action_pressed("move_forward"):
|
|
input_direction.z -= 1
|
|
if Input.is_action_pressed("move_backward"):
|
|
input_direction.z += 1
|
|
if Input.is_action_pressed("move_left"):
|
|
input_direction.x -= 1
|
|
if Input.is_action_pressed("move_right"):
|
|
input_direction.x += 1
|
|
|
|
# Normalize input to prevent faster diagonal movement
|
|
input_direction = input_direction.normalized()
|
|
|
|
# Apply movement in the camera's direction
|
|
var direction: Vector3 = (transform.basis * input_direction).normalized()
|
|
velocity.x = direction.x * speed
|
|
velocity.z = direction.z * speed
|
|
|
|
# Apply gravity
|
|
if not is_on_floor():
|
|
velocity.y -= gravity * delta
|
|
|
|
# Jumping
|
|
if Input.is_action_just_pressed("jump") and is_on_floor():
|
|
velocity.y = jump_force
|
|
|
|
# Move the player and detect collisions
|
|
move_and_slide()
|
|
|
|
# Apply force to RigidBody3D objects on collision
|
|
for index in range(get_slide_collision_count()):
|
|
var collision = get_slide_collision(index)
|
|
var collider = collision.get_collider()
|
|
|
|
if collider is RigidBody3D:
|
|
# Calculate the direction and force to apply
|
|
var force_direction = -collision.get_normal()
|
|
var force = force_direction * push_force
|
|
|
|
# Apply the force to the RigidBody3D
|
|
collider.apply_central_impulse(force)
|
|
|
|
func ghost_movement(delta: float) -> void:
|
|
var input_direction: Vector3 = Vector3.ZERO
|
|
|
|
# Get input for movement
|
|
if Input.is_action_pressed("move_forward"):
|
|
input_direction.z -= 1 # Forward
|
|
if Input.is_action_pressed("move_backward"):
|
|
input_direction.z += 1 # Backward
|
|
if Input.is_action_pressed("move_left"):
|
|
input_direction.x -= 1 # Left
|
|
if Input.is_action_pressed("move_right"):
|
|
input_direction.x += 1 # Right
|
|
|
|
# Normalize input to prevent faster diagonal movement
|
|
input_direction = input_direction.normalized()
|
|
|
|
# Calculate movement direction relative to the camera
|
|
var camera_basis = $Camera3D.global_transform.basis
|
|
var direction: Vector3 = (
|
|
camera_basis.z * input_direction.z + # Forward/backward
|
|
camera_basis.x * input_direction.x # Left/right
|
|
).normalized()
|
|
|
|
# Apply movement
|
|
velocity = direction * ghost_speed
|
|
|
|
# Move the player
|
|
move_and_slide()
|
|
|
|
func flicker_lights(delta: float) -> void:
|
|
flicker_timer += delta
|
|
if flicker_timer >= flicker_interval:
|
|
flicker_timer = 0.0
|
|
# Get all lights in the "flicker_lights" group
|
|
var lights = get_tree().get_nodes_in_group("flicker_lights")
|
|
for light in lights:
|
|
if light is OmniLight3D or light is SpotLight3D:
|
|
# Check if the light is within range
|
|
if light.global_transform.origin.distance_to(global_transform.origin) <= flicker_range:
|
|
# Randomly adjust the light's energy
|
|
light.light_energy = randf_range(1.0 - flicker_intensity, 1.0 + flicker_intensity)
|
|
|
|
func interact_with_object() -> void:
|
|
# Raycast to check for interactable objects in front of the player
|
|
var raycast = $Camera3D/RayCast3D
|
|
if raycast.is_colliding():
|
|
var collider = raycast.get_collider()
|
|
|
|
if collider is RigidBody3D:
|
|
# Apply a force or torque to flip the object
|
|
collider.freeze = false
|
|
var flip_force = Vector3(0, interaction_strenght, 0) # Force to flip the object upward
|
|
var flip_torque = Vector3(interaction_strenght, 0, 0) # Torque to rotate the object
|
|
collider.apply_central_impulse(flip_force)
|
|
collider.apply_torque_impulse(flip_torque)
|