312 lines
10 KiB
GDScript
312 lines
10 KiB
GDScript
extends CharacterBody3D
|
|
|
|
@export var head_bob: bool = true
|
|
|
|
@export_category("Movement")
|
|
@export var WALK = 3
|
|
@export var RUN = 6
|
|
@export var CROUCH = 1.5
|
|
@export var JUMP_VELOCITY = 4
|
|
@export var HEAVY = 0.5
|
|
@export var run_toggle = false
|
|
|
|
@export_category("Jumping")
|
|
@export var floating_jump = false
|
|
@export var infinite_jump = false
|
|
@export var no_jump = false
|
|
|
|
@export_category("Constructs")
|
|
@export var grapple_speed = 20
|
|
#var grap_post = Vector3(0,0,0)
|
|
|
|
@export_category("Items")
|
|
@export var keys = []
|
|
@export var inventory = ["hydrogen_peroxide", "vinegar"]
|
|
|
|
# Get the gravity from the project settings to be synced with RigidBody nodes.
|
|
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
|
|
|
|
## the current modifier to movement speed
|
|
## Changes based on whether player is walking, running, crouching...
|
|
var speed_mode: float
|
|
var con_mod: float = 1
|
|
var switch_state_run = false
|
|
var switch_state_crouch = false
|
|
|
|
var current_time: int = 12
|
|
var contains: bool = false
|
|
|
|
@onready var neck := $Neck
|
|
@onready var con_animation := $ConstructAnimation
|
|
@onready var player_animation: AnimationPlayer = $PlayerAnimation
|
|
@onready var interactor_ray: RayCast3D = $Neck/FirstPersonCamera/InteractorRay
|
|
@onready var dumping_ray: RayCast3D = $Neck/FirstPersonCamera/DumpingRay
|
|
@onready var grapple_ray: RayCast3D = $Neck/FirstPersonCamera/GrappleRay
|
|
@onready var mesh_instance: MeshInstance3D = $MeshInstance3D
|
|
@onready var collision: CollisionShape3D = $CollisionShape3D
|
|
@onready var camera := $Neck/FirstPersonCamera
|
|
@onready var construct: Node3D = $Neck/FirstPersonCamera/ItemRig/Construct
|
|
|
|
func _ready():
|
|
|
|
speed_mode = WALK
|
|
|
|
func _unhandled_input(event):
|
|
|
|
if event is InputEventMouseButton:
|
|
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
|
|
if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
|
|
if event is InputEventMouseMotion:
|
|
if camera.current:
|
|
## First Person Camera
|
|
neck.rotate_y(-event.relative.x * 0.01)
|
|
camera.rotate_x(-event.relative.y * 0.01)
|
|
camera.rotation.x = clamp(camera.rotation.x, deg_to_rad(-60), deg_to_rad(60))
|
|
|
|
func _physics_process(delta):
|
|
|
|
##Neck is magically at 0.56 on the y after being set to 0.3 in the player scene???
|
|
#print("neck positon: " + str(neck.position.y))
|
|
|
|
##CONSTRUCT FUNCTIONS
|
|
if construct.CONSTRUCT_TYPE.name == "Stick":
|
|
use_stick()
|
|
##If the player is using the hammer then go into the hammer function.
|
|
elif construct.CONSTRUCT_TYPE.name == "Hammer":
|
|
use_hammer()
|
|
elif construct.CONSTRUCT_TYPE.name == "Weight":
|
|
use_weight()
|
|
##Change the the current_time when time changing occurs
|
|
elif construct.CONSTRUCT_TYPE.name == "Time":
|
|
use_time()
|
|
elif construct.CONSTRUCT_TYPE.name == "fishing_rod":
|
|
use_fishing_rod(delta)
|
|
elif construct.CONSTRUCT_TYPE.name == "shovel":
|
|
use_shovel()
|
|
|
|
|
|
|
|
##Gravity
|
|
##If not grappling (issue with gravity pulling the player down from grapple spot)
|
|
if not is_on_floor() and Global.grappling == false:
|
|
velocity.y -= gravity * delta
|
|
|
|
##Jumping
|
|
##Check that jumping is enabled
|
|
if not no_jump:
|
|
##Infinite Jump
|
|
if infinite_jump:
|
|
##Handle jump.
|
|
if Input.is_action_just_pressed("Jump"): #and is_on_floor():
|
|
velocity.y = JUMP_VELOCITY * con_mod
|
|
##Floating Jump
|
|
elif floating_jump:
|
|
## Will float up when space is held
|
|
## Mod on jump for TESTING
|
|
if Input.is_action_pressed("Jump"):
|
|
velocity.y = JUMP_VELOCITY * con_mod
|
|
else:
|
|
if Input.is_action_just_pressed("Jump") and is_on_floor():
|
|
velocity.y = JUMP_VELOCITY * con_mod
|
|
|
|
##Player Crouch
|
|
if Input.is_action_just_pressed("Crouch") and is_on_floor():
|
|
if !switch_state_crouch:
|
|
speed_mode = CROUCH
|
|
collision.shape.height = 1
|
|
player_animation.play("crouch")
|
|
switch_state_crouch = true
|
|
elif switch_state_crouch:
|
|
speed_mode = WALK
|
|
collision.shape.height = 2
|
|
player_animation.play_backwards("crouch")
|
|
switch_state_crouch = false
|
|
switch_state_run = false
|
|
|
|
if camera.current:
|
|
# Get the input direction and handle the movement/deceleration.
|
|
var input_dir = Input.get_vector("Left", "Right", "Forward", "Back")
|
|
var direction = (neck.global_basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
|
|
if direction:
|
|
|
|
velocity.x = direction.x * speed_mode * con_mod
|
|
velocity.z = direction.z * speed_mode * con_mod
|
|
|
|
##Run set to toggle
|
|
if run_toggle == true:
|
|
if Input.is_action_just_pressed("Run") and switch_state_crouch == false:
|
|
if !switch_state_run:
|
|
speed_mode = RUN
|
|
switch_state_run = true
|
|
elif switch_state_run:
|
|
speed_mode = WALK
|
|
switch_state_run = false
|
|
|
|
##Run set to hold
|
|
elif run_toggle == false:
|
|
if Input.is_action_pressed("Run") and switch_state_crouch == false:
|
|
speed_mode = RUN
|
|
switch_state_run = true
|
|
else:
|
|
if switch_state_crouch == false:
|
|
speed_mode = WALK
|
|
switch_state_run = false
|
|
|
|
|
|
else:
|
|
#Don't move
|
|
velocity.x = move_toward(velocity.x, 0, WALK)
|
|
velocity.z = move_toward(velocity.z, 0, WALK)
|
|
#switch_state_run = false
|
|
#if switch_state_crouch == false and (run_toggle == true and switch_state_run == false):
|
|
#speed_mode = WALK
|
|
|
|
## Top Down Movement mode
|
|
#if camera_top_down.current:
|
|
#top_down_movement()
|
|
|
|
make_head_bob()
|
|
|
|
move_and_slide()
|
|
|
|
func make_head_bob():
|
|
#Allows head bob to be disabled
|
|
if head_bob == true:
|
|
#Track if the player is moving
|
|
if self.velocity.x != 0 or self.velocity.z != 0:
|
|
#Do a head bob animation and have it play at a speed equiv to move speed
|
|
player_animation.speed_scale = speed_mode / 4
|
|
player_animation.play("head_bob")
|
|
else:
|
|
player_animation.stop()
|
|
|
|
func use_shovel():
|
|
|
|
if Input.is_action_just_pressed("UseConstruct"):
|
|
##Change this to be a shovel animation
|
|
if not con_animation.is_playing():
|
|
con_animation.play("swing")
|
|
|
|
if interactor_ray.is_colliding():
|
|
print("is colliding")
|
|
if interactor_ray.get_collider().is_in_group("snow_spot") and contains == false:
|
|
##Make sure the pile has snow
|
|
if interactor_ray.get_collider().get_parent().snow_amount > 0:
|
|
interactor_ray.get_collider().get_parent().snow_amount -= 1
|
|
contains = true
|
|
##Show the shovel as having snow
|
|
self.find_child("shovel").find_child("snow").show()
|
|
|
|
if Input.is_action_just_pressed("UseConstructAlt"):
|
|
##Change this to shovel dump
|
|
if not con_animation.is_playing():
|
|
con_animation.play("swing")
|
|
|
|
if contains:
|
|
##If dumping snow not in pile
|
|
if dumping_ray.is_colliding():
|
|
if !dumping_ray.get_collider().is_in_group("snow_spot"):
|
|
contains = false
|
|
##Hide the snow
|
|
self.find_child("shovel").find_child("snow").hide()
|
|
else:
|
|
contains = false
|
|
##Hide the snow
|
|
self.find_child("shovel").find_child("snow").hide()
|
|
|
|
##Add snow to snow spot if it is colliding
|
|
if dumping_ray.is_colliding():
|
|
if dumping_ray.get_collider().is_in_group("snow_spot"):
|
|
##Make sure the pile is not full
|
|
if dumping_ray.get_collider().get_parent().snow_amount < 3:
|
|
dumping_ray.get_collider().get_parent().snow_amount += 1
|
|
contains = false
|
|
##Hide the snow
|
|
self.find_child("shovel").find_child("snow").hide()
|
|
|
|
|
|
|
|
func use_fishing_rod(delta):
|
|
|
|
##Play the animation every time the construct is used
|
|
if Input.is_action_just_pressed("UseConstruct"):
|
|
if not con_animation.is_playing():
|
|
con_animation.play("swing")
|
|
|
|
##Use the grapple
|
|
grapple(delta)
|
|
|
|
## If the player is using the hammer play the animation and check for breakable objects
|
|
func use_hammer():
|
|
if Input.is_action_just_pressed("UseConstruct"):
|
|
if not con_animation.is_playing():
|
|
con_animation.play("swing")
|
|
if interactor_ray.is_colliding():
|
|
if interactor_ray.get_collider().is_in_group("breakable"):
|
|
interactor_ray.get_collider().stability -= 1
|
|
|
|
func use_tape():
|
|
if Input.is_action_just_pressed("UseConstruct"):
|
|
if not con_animation.is_playing():
|
|
pass ##TODO Add Construct Animation: con_animation.play("toss")
|
|
##TODO Remove this and apply it to tape!!!
|
|
if interactor_ray.get_collider().is_in_group("fixable"):
|
|
interactor_ray.get_collider().fixed = true
|
|
|
|
##If the player has the weight selected, play a lil animation when they try to use the construct
|
|
func use_weight():
|
|
if Input.is_action_just_pressed("UseConstruct"):
|
|
if not con_animation.is_playing():
|
|
con_animation.play("toss")
|
|
|
|
func use_stick():
|
|
if Input.is_action_just_pressed("UseConstruct"):
|
|
if not con_animation.is_playing():
|
|
con_animation.play("swing")
|
|
|
|
func use_time():
|
|
if Input.is_action_just_pressed("UseConstruct"):
|
|
construct.construct_mesh2.rotation += Vector3(0,deg_to_rad(-30),0)
|
|
|
|
if current_time < 24:
|
|
current_time += 1
|
|
else:
|
|
current_time = 1
|
|
|
|
#print("current_time: " + str(current_time))
|
|
|
|
func grapple(delta):
|
|
|
|
#print(Global.grap_post)
|
|
#print(Global.grappling)
|
|
|
|
##If valid grapple point in range and grapple button pressed then set grapple true and get grapple point position
|
|
if grapple_ray.is_colliding() and grapple_ray.get_collider().is_in_group("grapple_point") and Global.grappling == false:
|
|
if Input.is_action_just_pressed("UseConstruct"):
|
|
Global.grappling = true
|
|
Global.grap_post = grapple_ray.get_collider().position
|
|
|
|
##If the use item button is released stop grappling
|
|
##If the player jumps cancel the grapple
|
|
if Input.is_action_just_released("UseConstruct") or Input.is_action_just_pressed("Jump"):
|
|
Global.grappling = false
|
|
|
|
## If grappling move the player towards the target point
|
|
##TODO Make it so the player can only get so close to the grapple point?
|
|
if Global.grappling:
|
|
#for i in range(0, grapple_speed):
|
|
self.position = position.move_toward(Global.grap_post - Vector3(0,1.5,0), delta * grapple_speed)
|
|
|
|
## Test function to shift between two different areas in the same scene
|
|
## Based on time travel mechanic implementation in Dishonered 2
|
|
## Idea with this would be to allow "instance" transfer between different dreamscapes
|
|
## This test allows the player to do it with a key press but later implementations would require the right interactable prompt
|
|
func shift():
|
|
if Input.is_action_just_pressed("shift"):
|
|
if self.global_position.y > 1000:
|
|
self.translate(Vector3(0,-1002,0))
|
|
elif self.global_position.y < 1000:
|
|
self.translate(Vector3(0,1001,0))
|
|
else:
|
|
print(self.global_position)
|