extends KinematicBody
var hyperGossip : HyperGossip
# TODO : These probably should not be in player_core, though I am uncertain yet if they belong elsewhere
const EVENT_PLAYER_SNAPSHOT = 'player_snapshot'
const EVENT_PLAYER_WANTSTOJUMP = 'player_wantstojump'
const EVENT_PLAYER_DIRECTION = 'player_direction'
const EVENT_PLAYER_RESPAWNPLAYER = 'player_respawnplayer'
const EVENT_PLAYER_SHOOT_GRAPPLINGHOOK = 'player_shoot_grapplinghook'
const EVENT_PLAYER_RELEASE_GRAPPLINGHOOK = 'player_release_grapplinghook'
const EVENT_PLAYER_TOGGLE_LIGHT = 'player_toggle_light'
export var mouseSensitivity : float = 0.3
export var movementSpeed : float = 14
export var fallAcceleration : float = 27
export var movementAcceleration : float = 4
export var canJumpHeight : float = 10
export var jumpHeight : float = 15
export var turn_velocity : float = 15
export var cameraLerpAmount : float = 40
export var currentSpeed : float = 0
onready var meshNode : Spatial = $Model
onready var meshSkeletonNode : Skeleton = $Model/Armature/Skeleton
onready var meshSkeletalIKNode : SkeletonIK = $Model/Armature/Skeleton/SkeletonIK
onready var meshSkeletonHiddenHand : MeshInstance = $Model/Armature/Skeleton/player001
onready var meshHandBone : int = meshSkeletonNode.find_bone("DEF-hand.R")
onready var meshHandBonePos : Transform = meshSkeletonNode.get_bone_pose(meshHandBone)
onready var clippedCamera : Spatial = $CameraHead/CameraPivot/ClippedCamera
onready var clippedCameraHead : Spatial = $CameraHead
onready var clippedCameraPivot : Spatial = $CameraHead/CameraPivot
# onready var csgMesh : CSGMesh = $Head/CamPivot/ClippedCamera/GrappleCast/CSGMesh
onready var meshCollisionShape : CollisionShape = $CollisionShape
onready var grappleHookCast : RayCast = $CameraHead/CameraPivot/GrappleHookCast
onready var grappleVisualPoint_1 = $GrapplingHook/GrappleVisualPoint_1
# onready var grappleVisualPoint_2 = $GrapplingHook/GrappleVisualPoint_2
onready var grappleVisualPoint = grappleVisualPoint_1
onready var grappleLineHelper : Spatial = $Model/GrappleLineHelper
onready var grappleVisualLine : CSGCylinder = $Model/GrappleLineHelper/GrappleVisualLine_1
# onready var grappleVisualLine : = $Model/GrappleLineHelper/GrappleVisualLine_2
onready var grappleIKTarget : Position3D = $GrapplingHook/IKTarget
onready var grapplingHandOriginalScale : Vector3 = Vector3.ZERO
onready var omniLight : OmniLight = $OmniLight
var grapplingHook_GrapplePosition : Vector3 = Vector3.ZERO
var grapplingHook_IsHooked : bool = false
var playerWantsToShootGrapplingHook : bool = false
var playerWantsToReleaseGrapplingHook : bool = false
# TODO : Make Debug UI dynamic and not hardcoded in the core Hyper scripts.
#onready var hyperdebugui : Control = $HyperGodotDebugUI
#onready var hyperdebugui_gateway_startstop_button : Button = $HyperGodotDebugUI/HypercoreDebugPanel/HypercoreDebugContainer/GatewayStartStopButton
#onready var hyperdebugui_gossipid_list : ItemList = get_tree().get_current_scene().get_node("HyperGodot").get_node("HyperGateway")
onready var currentMap = get_tree().get_current_scene().get_node("Maps").get_child(0)
var originalOrigin : Vector3 = Vector3.ZERO
var currentSpawnLocation : Vector3 = Vector3.ZERO
var currentDirection : Vector3 = Vector3.ZERO
var moveNetworkUpdateAllowed : bool = true
var playerWantsToRespawn : bool = false
var jumpFloorDirection : Vector3 = Vector3(0,1,0)
var playerCanJump : bool = false
var playerWantsToJump : bool = false
var playerWantsNewWorldEnvironment : bool = true
var playerWantsToToggleLight : bool = false
var f_input : float
var h_input : float
var snapVector : float
var kinematicVelocity : Vector3 = Vector3.ZERO
var collisions : Dictionary = {}
var Particles_Land = preload("res://game/player/particles.tscn")
func _ready():
# Backup Origin
originalOrigin = self.translation
# Spawn into Map
currentSpawnLocation = getSpawnLocationForMapName(currentMap.map_name)
playerWantsToRespawn = true
# Get HyperGossip
hyperGossip = get_tree().get_current_scene().get_node("HyperGodot").get_node("HyperGossip")
func snapShotUpdate(_translation : Vector3, _meshDirection : Vector3, _lookingDirection : Vector3):
self.translation = _translation
self.meshNode.rotation = _meshDirection
self.currentDirection = _lookingDirection
func directionUpdate(_direction : Vector3):
self.currentDirection = _direction
func getSpawnLocationForMapName(mapName : String) -> Vector3:
# Get Map Node
var mapNode = get_tree().get_current_scene().get_node("Maps").find_node(mapName, true, false)
if(mapNode == null):
return get_tree().get_current_scene().get_node("Maps").find_node("map_test", true, false).getSpawnLocation()
else:
return mapNode.getSpawnLocation()
func _process(_delta):
if(currentDirection != Vector3.ZERO):
meshNode.rotation.y = lerp_angle(meshNode.rotation.y, atan2(-currentDirection.x, -currentDirection.z), turn_velocity * _delta)
func grapplingHook_Process():
grapplingHook_CheckActivation()
var length : float = grapplingHook_UpdatePlayerVelocityAndReturnHookLength()
grapplingHook_UpdateVisualLine(length)
# TODO : BIG Hack to prevent running on remote players
var _name = self.name
if(self.name == "PlayerLocal"):
grapplingHook_UpdateVisualPoint()
func grapplingHook_CheckActivation():
# Activate hook
if(playerWantsToShootGrapplingHook):
playerWantsToShootGrapplingHook = false
playerWantsToReleaseGrapplingHook = false
grapplingHook_IsHooked = true
grappleVisualLine.show()
$Model/Sound_Shoot_GrapplingHook_2.play()
grappleIKTarget.translation = grapplingHook_GrapplePosition
grapplingHook_DisappearHand()
elif(playerWantsToReleaseGrapplingHook):
# Stop grappling
if(grapplingHook_IsHooked):
grapplingHook_IsHooked = false
playerWantsToReleaseGrapplingHook = false
grappleVisualLine.hide()
$Model/Sound_Release_GrapplingHook.play()
grapplingHook_ReappearHand()
func grapplingHook_UpdateVisualPoint():
if grappleHookCast.is_colliding():
grappleVisualPoint.visible = true
grappleVisualPoint.translation = grappleHookCast.get_collision_point()
else:
grappleVisualPoint.visible = false
func grapplingHook_UpdateVisualLine(length : float):
if(grapplingHook_IsHooked):
grappleLineHelper.look_at(grapplingHook_GrapplePosition, Vector3.UP)
grappleVisualLine.height = length
grappleVisualLine.translation.z = length / -1.80
func grapplingHook_UpdatePlayerVelocityAndReturnHookLength() -> float:
var grapple_speed : float = 0.5
var rest_length : float = 1
var max_grapple_speed : float = 2.75
var player2hook := grapplingHook_GrapplePosition - translation # vector from player to hook
var length := player2hook.length()
if(grapplingHook_IsHooked):
# if we more than 4 away from line, don't dampen speed as much
if(length > 4):
kinematicVelocity *= .999
# Otherwise dampen speed more
else:
kinematicVelocity *= .9
# Hook's law equation
var force := grapple_speed * (length - rest_length)
# Clamp force to be less than max_grapple_speed
if abs(force) > max_grapple_speed:
force = max_grapple_speed
# Preserve direction, but scale by force
kinematicVelocity += player2hook.normalized() * force
return length
func grapplingHook_DisappearHand():
meshSkeletonHiddenHand.visible = false
#var bone = meshSkeletonNode.find_bone("DEF-hand.R")
#var bonePos = meshSkeletonNode.get_bone_pose(bone)
#bonePos = bonePos.scaled( Vector3(0.1, 0.1, 0.1) )
#meshSkeletonNode.set_bone_custom_pose(bone, bonePos)
func grapplingHook_ReappearHand():
meshSkeletonHiddenHand.visible = true
#var bone = meshSkeletonNode.find_bone("DEF-hand.R")
#var bonePos = meshSkeletonNode.get_bone_pose(bone)
#bonePos = bonePos.( Vector3(1, 1, 1) )
#meshSkeletonNode.set_bone_custom_pose(bone, bonePos)
var jumpingUp : bool
func _physics_process(_delta):
# Respawn Player here first
if(playerWantsToRespawn):
playerWantsToRespawn = false
respawnPlayer()
return
# Check for New World Environment
if(playerWantsNewWorldEnvironment):
playerWantsNewWorldEnvironment = false
currentMap.updateMapWorldEnvironmentScene()
# Check for Toggle Light
if(playerWantsToToggleLight):
playerWantsToToggleLight = false
omniLight.visible = !omniLight.visible
$Model/Sound_ToggleLight_1.play()
# Moving the character
var y_cache : float = kinematicVelocity.y
kinematicVelocity = kinematicVelocity.linear_interpolate(currentDirection * movementSpeed, movementAcceleration * _delta)
kinematicVelocity.y = y_cache
# Vertical velocity
if(!grapplingHook_IsHooked):
# Apply Gravity
kinematicVelocity.y -= fallAcceleration * _delta
# Check for a Jump
if(playerWantsToJump):
playerWantsToJump = false
if( playerCanJump() ):
kinematicVelocity.y = jumpHeight
jumpingUp = true
$Model/Sound_Jump.play()
# kinematicVelocity = move_and_slide(kinematicVelocity, Vector3.UP)
var bPrevOnFloor = is_on_floor()
y_cache = kinematicVelocity.y
kinematicVelocity = move_and_slide(kinematicVelocity, Vector3.UP, false, 4, 10.0, true)
if( !bPrevOnFloor and is_on_floor() and y_cache < -17.0):
var particles = Particles_Land.instance()
$Model.add_child(particles)
$Model/Sound_Land.play()
# Calculate Potential Jumping Animation
if( !is_on_floor() ):
if(kinematicVelocity.y > 0.1):
$AnimationTree.set("parameters/air_transition/current", 0)
$AnimationTree.set("parameters/air_blend/blend_amount", -1)
elif(kinematicVelocity.y < -0.1):
$AnimationTree.set("parameters/air_transition/current", 0)
$AnimationTree.set("parameters/air_blend/blend_amount", 0)
else:
$AnimationTree.set("parameters/air_transition/current", 1)
# Calculate Running Animation
currentSpeed = ( (abs(kinematicVelocity.x) + abs(kinematicVelocity.z) - 7) / 7)
$AnimationTree.set("parameters/iwr_blend/blend_amount", currentSpeed)
# Update Grappling Hook
grapplingHook_Process()
# Check for Hand IK from Grappling Hook
if(grapplingHook_IsHooked):
meshSkeletalIKNode.start()
else:
meshSkeletalIKNode.stop()
# self.linear_velocity.y += jumpHeight
# playerWantsToJump = false
#var y_cache = linear_velocity.y
#linear_velocity = linear_velocity.linear_interpolate(currentDirection * movementSpeed, movementAcceleration * _delta)
#linear_velocity.y = y_cache
#linear_velocity = Vector3(currentDirection.x, 0, currentDirection.z).normalized() * movementSpeed * _delta
#linear_velocity.y = y_cache
#linear_velocity.x += currentDirection.x * movementSpeed * _delta
#linear_velocity.x = clamp(linear_velocity.x, -3, 3)
#linear_velocity.z += currentDirection.z * movementSpeed * _delta
#linear_velocity.z = clamp(linear_velocity.z, -3, 3)
# Handle Jumping / Gravity
#if is_on_floor():
#if true:
# snapVector = -get_floor_normal()
# gravity_vec = Vector3.ZERO
#else:
# snap = Vector3.DOWN
# accel = ACCEL_AIR
# gravity_vec += Vector3.DOWN * gravity * delta
#if Input.is_action_just_pressed("jump") and is_on_floor():
# snap = Vector3.ZERO
# gravity_vec = Vector3.UP * jump
# Actually Movement
#velocityAmount = velocityAmount.linear_interpolate(currentDirection * movementSpeed, accelerationDefault * delta)
# finalMovement = velocityAmount + finalgravityVelociy
func respawnPlayer():
kinematicVelocity = Vector3.ZERO
grapplingHook_IsHooked = false
playerWantsToShootGrapplingHook = false
playerWantsToReleaseGrapplingHook = true
$Model/Sound_Teleport_1.play()
global_transform.origin = currentSpawnLocation
func playerCanJump() -> bool:
if( self.is_on_floor() ):
return true
else:
return false
func canJump(state : PhysicsDirectBodyState):
# Raycast from state to ground based on canJumpHeight and straight down (use self to exclude raycast from intersecting itself)
var hitDictionary : Dictionary = state.get_space_state().intersect_ray(global_transform.origin, canJumpHeight * jumpFloorDirection, [self])
# If the dictionary is empty, nothing was hit, so we can't jump
if hitDictionary.size() == 0:
return false
else:
var collider : StaticBody = hitDictionary.collider
var parent = collider.get_parent()
if(parent is MeshInstance):
if(true):
var material : SpatialMaterial = SpatialMaterial.new()
material.albedo_color = Color(0, 188, 0)
parent.material_override = material
else:
parent.material_override = null
return true
func _on_Input_player_mousemotion_event(event):
clippedCameraHead.rotate_y(deg2rad(-event.relative.x * mouseSensitivity))
clippedCameraPivot.rotate_x(deg2rad(-event.relative.y * mouseSensitivity))
clippedCameraPivot.rotation.x = clamp(clippedCameraPivot.rotation.x, deg2rad(-89), deg2rad(89))
func _on_Input_player_move(direction : Vector3):
currentDirection = direction
if(moveNetworkUpdateAllowed):
hyperGossip.broadcast_event(EVENT_PLAYER_DIRECTION, getPlayerLocalCoreNetworkData() )
moveNetworkUpdateAllowed = false
#var h_rot = clippedCameraHead.global_transform.basis.get_euler().y
# Adjust Current Direction based on Mouse Direction
#currentDirection = Vector3(direction.x, 0, direction.z).rotated(Vector3.UP, h_rot).normalized()
func _on_Input_player_restore_origin() -> void:
playerWantsToRespawn = true
var spawnLocation : Vector3 = getSpawnLocationForMapName(currentMap.map_name)
currentSpawnLocation = spawnLocation
var data : Dictionary = {
#"profile": profile,
"spawnLocation": {
"x": spawnLocation.x,
"y": spawnLocation.y,
"z": spawnLocation.z
}
}
hyperGossip.broadcast_event(EVENT_PLAYER_RESPAWNPLAYER, data)
func _on_Input_player_change_physics_mode() -> void:
self.mode += 1
if(self.mode > RigidBody.MODE_KINEMATIC):
self.mode = RigidBody.MODE_RIGID
func _on_Input_player_jump():
playerWantsToJump = true
hyperGossip.broadcast_event(EVENT_PLAYER_WANTSTOJUMP, getPlayerLocalCoreNetworkData() )
func _on_Input_player_shoot_grapplinghook():
if( Input.get_mouse_mode() != Input.MOUSE_MODE_VISIBLE ):
if( grappleHookCast.is_colliding() ):
playerWantsToShootGrapplingHook = true
grapplingHook_GrapplePosition = grappleHookCast.get_collision_point()
hyperGossip.broadcast_event(EVENT_PLAYER_SHOOT_GRAPPLINGHOOK, getPlayerLocalShootGrapplingHookData() )
func _on_Input_player_release_grapplinghook():
if( Input.get_mouse_mode() != Input.MOUSE_MODE_VISIBLE ):
if(grapplingHook_IsHooked):
playerWantsToReleaseGrapplingHook = true
hyperGossip.broadcast_event(EVENT_PLAYER_RELEASE_GRAPPLINGHOOK, getPlayerLocalCoreNetworkData() )
func _on_Input_player_toggle_light():
playerWantsToToggleLight = true
hyperGossip.broadcast_event(EVENT_PLAYER_TOGGLE_LIGHT, getPlayerLocalCoreNetworkData() )
func _checkPlayerCanJump(newBody : PhysicsBody, addedBody : bool) -> void:
# Check if this is a new body added
if(addedBody):
# If we are adding a collision, check if we already can jump
if(playerCanJump):
return
var hit = newBody.get_space_state().intersect_ray(Vector3(), canJumpHeight * -jumpFloorDirection, [self])
# Check if any surfaces intersected
if hit.size() == 0:
playerCanJump = false
else:
playerCanJump = true
func _on_Player_body_entered(body : Node) -> void:
if(!collisions.has(body.get_instance_id()) ):
collisions[body.get_instance_id()] = body.name
$CollisionUI.onNewollision(body, collisions)
func _on_Player_body_exited(body : Node) -> void:
if(collisions.has(body.get_instance_id()) ):
collisions.erase(body.get_instance_id())
$CollisionUI.onRemovedCollision(body, collisions)
func _on_MoveNetworkTimer_timeout():
moveNetworkUpdateAllowed = true
func getPlayerLocalCoreNetworkData() -> Dictionary:
# TODO : Fix finding the local player, and get it out of player_core into player_core_local
var localPlayer : KinematicBody = get_tree().get_current_scene().get_node("Players").get_node("PlayerLocal")
var translation : Vector3 = localPlayer.translation
var direction : Vector3 = localPlayer.currentDirection
var data : Dictionary = {
#"profile": profile,
"translation": {
"x": translation.x,
"y": translation.y,
"z": translation.z
},
"direction": {
"x": direction.x,
"y": direction.y,
"z": direction.z
},
"velocity": {
"x": kinematicVelocity.x,
"y": kinematicVelocity.y,
"z": kinematicVelocity.z
}
}
return data
func getPlayerLocalShootGrapplingHookData() -> Dictionary:
# TODO : Fix finding the local player, and get it out of player_core into player_core_local
var localPlayer : KinematicBody = get_tree().get_current_scene().get_node("Players").get_node("PlayerLocal")
var translation : Vector3 = localPlayer.translation
var direction : Vector3 = localPlayer.currentDirection
var data : Dictionary = {
#"profile": profile,
"translation": {
"x": translation.x,
"y": translation.y,
"z": translation.z
},
"direction": {
"x": direction.x,
"y": direction.y,
"z": direction.z
},
"velocity": {
"x": kinematicVelocity.x,
"y": kinematicVelocity.y,
"z": kinematicVelocity.z
},
"grapple_position": {
"x": grapplingHook_GrapplePosition.x,
"y": grapplingHook_GrapplePosition.y,
"z": grapplingHook_GrapplePosition.z
}
}
return data
func playerCoreNetworkDataUpdate(data : Dictionary):
self.translation = Vector3(data.translation.x, data.translation.y, data.translation.z)
self.currentDirection = Vector3(data.direction.x, data.direction.y, data.direction.z)
self.kinematicVelocity = Vector3(data.velocity.x, data.velocity.y, data.velocity.z)
func playerCoreNetworkDataUpdate_Types(_translation : Vector3, _currentDirection : Vector3, _kinematicVelocity : Vector3):
self.translation = _translation
self.currentDirection = _currentDirection
self.kinematicVelocity = _kinematicVelocity