Merge branch 'develop' into feat/cicd-tests
1
.gitignore
vendored
|
|
@ -2,7 +2,6 @@
|
||||||
.godot/
|
.godot/
|
||||||
|
|
||||||
# Godot-specific ignores
|
# Godot-specific ignores
|
||||||
*.import
|
|
||||||
export.cfg
|
export.cfg
|
||||||
export_presets.cfg
|
export_presets.cfg
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
image: $CI_REGISTRY/open-fpsz/docker-godot/godot
|
image: $CI_REGISTRY/open-fpsz/docker-godot/godot
|
||||||
|
|
||||||
|
variables:
|
||||||
|
EXPORT_NAME: open-fpsz
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- addons
|
- addons
|
||||||
- tests
|
- tests
|
||||||
|
|
@ -15,66 +18,45 @@ cache: &global_cache
|
||||||
addons:
|
addons:
|
||||||
stage: addons
|
stage: addons
|
||||||
script:
|
script:
|
||||||
- timeout 10 godot --headless --editor --verbose || true
|
- timeout 15 godot --headless --editor --verbose || true
|
||||||
- timeout 10 godot --headless --editor --verbose || true
|
- timeout 15 godot --headless --editor --verbose || true
|
||||||
only:
|
rules:
|
||||||
- main
|
- if: '$CI_COMMIT_TAG =~ /^v\d\.\d\.\d$/'
|
||||||
- develop
|
|
||||||
|
|
||||||
# run tests
|
|
||||||
tests:
|
|
||||||
stage: tests
|
|
||||||
needs: [ "addons" ]
|
|
||||||
script:
|
|
||||||
- godot --headless --path "$PWD" -s addons/gut/gut_cmdln.gd
|
|
||||||
only:
|
|
||||||
- main
|
|
||||||
- develop
|
|
||||||
|
|
||||||
# export binaries
|
# export binaries
|
||||||
.export_presets:
|
.export_presets:
|
||||||
needs: [ "tests" ]
|
needs: [ "tests" ]
|
||||||
before_script:
|
before_script:
|
||||||
- cp "$EXPORT_PRESETS" export_presets.cfg
|
- cp "$EXPORT_PRESETS" export_presets.cfg
|
||||||
only:
|
- export ZIP_ARCHIVE_NAME="$EXPORT_NAME-$CI_COMMIT_TAG-$CI_JOB_NAME.zip"
|
||||||
- main
|
rules:
|
||||||
|
- if: '$CI_COMMIT_TAG =~ /^v\d\.\d\.\d$/'
|
||||||
variables:
|
|
||||||
EXPORT_NAME: open-fpsz
|
|
||||||
|
|
||||||
linux:
|
linux:
|
||||||
stage: export
|
stage: export
|
||||||
extends: [ .export_presets ]
|
extends: [ .export_presets ]
|
||||||
when: manual
|
when: manual
|
||||||
script:
|
script:
|
||||||
- mkdir -v -p build/linux
|
- mkdir -vp build/$CI_JOB_NAME
|
||||||
- godot --headless --verbose --export-release "Linux/X11" build/linux/$EXPORT_NAME.x86_64
|
- godot --headless --verbose --export-release "Linux/X11" build/$CI_JOB_NAME/$EXPORT_NAME.x86_64
|
||||||
artifacts:
|
- cd build && zip -r $ZIP_ARCHIVE_NAME $CI_JOB_NAME/*
|
||||||
name: $EXPORT_NAME-$CI_JOB_NAME
|
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file $ZIP_ARCHIVE_NAME "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/$EXPORT_NAME/${CI_COMMIT_TAG:1}/$ZIP_ARCHIVE_NAME"'
|
||||||
paths:
|
|
||||||
- build/linux
|
|
||||||
|
|
||||||
windows:
|
windows:
|
||||||
stage: export
|
stage: export
|
||||||
extends: [ .export_presets ]
|
extends: [ .export_presets ]
|
||||||
when: manual
|
when: manual
|
||||||
script:
|
script:
|
||||||
- mkdir -v -p build/windows
|
- mkdir -vp build/$CI_JOB_NAME
|
||||||
- godot --headless --verbose --export-release "Windows Desktop" build/windows/$EXPORT_NAME.exe
|
- godot --headless --verbose --export-release "Windows Desktop" build/$CI_JOB_NAME/$EXPORT_NAME.exe
|
||||||
artifacts:
|
- cd build && zip -r $ZIP_ARCHIVE_NAME $CI_JOB_NAME/*
|
||||||
name: $EXPORT_NAME-$CI_JOB_NAME
|
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file $ZIP_ARCHIVE_NAME "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/$EXPORT_NAME/${CI_COMMIT_TAG:1}/$ZIP_ARCHIVE_NAME"'
|
||||||
paths:
|
|
||||||
- build/windows
|
|
||||||
|
|
||||||
mac:
|
mac:
|
||||||
stage: export
|
stage: export
|
||||||
extends: [ .export_presets ]
|
extends: [ .export_presets ]
|
||||||
when: manual
|
when: manual
|
||||||
script:
|
script:
|
||||||
- mkdir -v -p build/mac
|
- mkdir -vp build/$CI_JOB_NAME
|
||||||
- godot --headless --verbose --export-release "Mac OSX" build/mac/$EXPORT_NAME.zip
|
- godot --headless --verbose --export-release "macOS" build/$CI_JOB_NAME/$ZIP_ARCHIVE_NAME
|
||||||
artifacts:
|
- 'cd build/$CI_JOB_NAME && curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file $ZIP_ARCHIVE_NAME "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/$EXPORT_NAME/${CI_COMMIT_TAG:1}/$ZIP_ARCHIVE_NAME"'
|
||||||
name: $EXPORT_NAME-$CI_JOB_NAME
|
|
||||||
paths:
|
|
||||||
- build/mac
|
|
||||||
|
|
||||||
|
|
|
||||||
21
addons/smoothing/LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2019 Lawnjelly
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
7
addons/smoothing/plugin.cfg
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
[plugin]
|
||||||
|
|
||||||
|
name="Smoothing"
|
||||||
|
description="Smoothing nodes for fixed timestep interpolation."
|
||||||
|
author="Lawnjelly"
|
||||||
|
version="1.2.1"
|
||||||
|
script="smoothing_plugin.gd"
|
||||||
235
addons/smoothing/smoothing.gd
Normal file
|
|
@ -0,0 +1,235 @@
|
||||||
|
# Copyright (c) 2019 Lawnjelly
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in all
|
||||||
|
# copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
|
||||||
|
extends Node3D
|
||||||
|
|
||||||
|
@export
|
||||||
|
var target: NodePath:
|
||||||
|
get:
|
||||||
|
return target
|
||||||
|
set(v):
|
||||||
|
target = v
|
||||||
|
set_target()
|
||||||
|
|
||||||
|
|
||||||
|
var _m_Target: Node3D
|
||||||
|
|
||||||
|
var _m_trCurr: Transform3D
|
||||||
|
var _m_trPrev: Transform3D
|
||||||
|
|
||||||
|
const SF_ENABLED = 1 << 0
|
||||||
|
const SF_TRANSLATE = 1 << 1
|
||||||
|
const SF_BASIS = 1 << 2
|
||||||
|
const SF_SLERP = 1 << 3
|
||||||
|
const SF_INVISIBLE = 1 << 4
|
||||||
|
|
||||||
|
@export_flags("enabled", "translate", "basis", "slerp") var flags: int = SF_ENABLED | SF_TRANSLATE | SF_BASIS:
|
||||||
|
set(v):
|
||||||
|
flags = v
|
||||||
|
# we may have enabled or disabled
|
||||||
|
_SetProcessing()
|
||||||
|
get:
|
||||||
|
return flags
|
||||||
|
|
||||||
|
|
||||||
|
##########################################################################################
|
||||||
|
# USER FUNCS
|
||||||
|
|
||||||
|
|
||||||
|
# call this checked e.g. starting a level, AFTER moving the target
|
||||||
|
# so we can update both the previous and current values
|
||||||
|
func teleport():
|
||||||
|
var temp_flags = flags
|
||||||
|
_SetFlags(SF_TRANSLATE | SF_BASIS)
|
||||||
|
|
||||||
|
_RefreshTransform()
|
||||||
|
_m_trPrev = _m_trCurr
|
||||||
|
|
||||||
|
# do one frame update to make sure all components are updated
|
||||||
|
_process(0)
|
||||||
|
|
||||||
|
# resume old flags
|
||||||
|
flags = temp_flags
|
||||||
|
|
||||||
|
|
||||||
|
func set_enabled(bEnable: bool):
|
||||||
|
_ChangeFlags(SF_ENABLED, bEnable)
|
||||||
|
_SetProcessing()
|
||||||
|
|
||||||
|
|
||||||
|
func is_enabled():
|
||||||
|
return _TestFlags(SF_ENABLED)
|
||||||
|
|
||||||
|
|
||||||
|
##########################################################################################
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
_m_trCurr = Transform3D()
|
||||||
|
_m_trPrev = Transform3D()
|
||||||
|
set_process_priority(100)
|
||||||
|
set_as_top_level(true)
|
||||||
|
Engine.set_physics_jitter_fix(0.0)
|
||||||
|
|
||||||
|
|
||||||
|
func set_target():
|
||||||
|
if is_inside_tree():
|
||||||
|
_FindTarget()
|
||||||
|
|
||||||
|
|
||||||
|
func _set_flags(new_value):
|
||||||
|
flags = new_value
|
||||||
|
# we may have enabled or disabled
|
||||||
|
_SetProcessing()
|
||||||
|
|
||||||
|
|
||||||
|
func _get_flags():
|
||||||
|
return flags
|
||||||
|
|
||||||
|
|
||||||
|
func _SetProcessing():
|
||||||
|
var bEnable = _TestFlags(SF_ENABLED)
|
||||||
|
if _TestFlags(SF_INVISIBLE):
|
||||||
|
bEnable = false
|
||||||
|
|
||||||
|
set_process(bEnable)
|
||||||
|
set_physics_process(bEnable)
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
func _enter_tree():
|
||||||
|
# might have been moved
|
||||||
|
_FindTarget()
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
func _notification(what):
|
||||||
|
match what:
|
||||||
|
# invisible turns unchecked processing
|
||||||
|
NOTIFICATION_VISIBILITY_CHANGED:
|
||||||
|
_ChangeFlags(SF_INVISIBLE, is_visible_in_tree() == false)
|
||||||
|
_SetProcessing()
|
||||||
|
|
||||||
|
|
||||||
|
func _RefreshTransform():
|
||||||
|
if _HasTarget() == false:
|
||||||
|
return
|
||||||
|
|
||||||
|
_m_trPrev = _m_trCurr
|
||||||
|
_m_trCurr = _m_Target.global_transform
|
||||||
|
|
||||||
|
func _FindTarget():
|
||||||
|
_m_Target = null
|
||||||
|
|
||||||
|
# If no target has been assigned in the property,
|
||||||
|
# default to using the parent as the target.
|
||||||
|
if target.is_empty():
|
||||||
|
var parent = get_parent_node_3d()
|
||||||
|
if parent:
|
||||||
|
_m_Target = parent
|
||||||
|
return
|
||||||
|
|
||||||
|
var targ = get_node(target)
|
||||||
|
|
||||||
|
if ! targ:
|
||||||
|
printerr("ERROR SmoothingNode : Target " + str(target) + " not found")
|
||||||
|
return
|
||||||
|
|
||||||
|
if not targ is Node3D:
|
||||||
|
printerr("ERROR SmoothingNode : Target " + str(target) + " is not node 3D")
|
||||||
|
target = ""
|
||||||
|
return
|
||||||
|
|
||||||
|
# if we got to here targ is a spatial
|
||||||
|
_m_Target = targ
|
||||||
|
|
||||||
|
# certain targets are disallowed
|
||||||
|
if _m_Target == self:
|
||||||
|
var msg = str(_m_Target.get_name()) + " assigned to " + str(self.get_name()) + "]"
|
||||||
|
printerr("ERROR SmoothingNode : Target should not be self [", msg)
|
||||||
|
|
||||||
|
# error message
|
||||||
|
#OS.alert("Target cannot be a parent or grandparent in the scene tree.", "SmoothingNode")
|
||||||
|
_m_Target = null
|
||||||
|
target = ""
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
func _HasTarget() -> bool:
|
||||||
|
if _m_Target == null:
|
||||||
|
return false
|
||||||
|
|
||||||
|
# has not been deleted?
|
||||||
|
if is_instance_valid(_m_Target):
|
||||||
|
return true
|
||||||
|
|
||||||
|
_m_Target = null
|
||||||
|
return false
|
||||||
|
|
||||||
|
|
||||||
|
func _process(_delta):
|
||||||
|
|
||||||
|
var f = Engine.get_physics_interpolation_fraction()
|
||||||
|
var tr: Transform3D = Transform3D()
|
||||||
|
|
||||||
|
# translate
|
||||||
|
if _TestFlags(SF_TRANSLATE):
|
||||||
|
var ptDiff = _m_trCurr.origin - _m_trPrev.origin
|
||||||
|
tr.origin = _m_trPrev.origin + (ptDiff * f)
|
||||||
|
|
||||||
|
# rotate
|
||||||
|
if _TestFlags(SF_BASIS):
|
||||||
|
if _TestFlags(SF_SLERP):
|
||||||
|
tr.basis = _m_trPrev.basis.slerp(_m_trCurr.basis, f)
|
||||||
|
else:
|
||||||
|
tr.basis = _LerpBasis(_m_trPrev.basis, _m_trCurr.basis, f)
|
||||||
|
|
||||||
|
transform = tr
|
||||||
|
|
||||||
|
|
||||||
|
func _physics_process(_delta):
|
||||||
|
_RefreshTransform()
|
||||||
|
|
||||||
|
|
||||||
|
func _LerpBasis(from: Basis, to: Basis, f: float) -> Basis:
|
||||||
|
var res: Basis = Basis()
|
||||||
|
res.x = from.x.lerp(to.x, f)
|
||||||
|
res.y = from.y.lerp(to.y, f)
|
||||||
|
res.z = from.z.lerp(to.z, f)
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
func _SetFlags(f):
|
||||||
|
flags |= f
|
||||||
|
|
||||||
|
|
||||||
|
func _ClearFlags(f):
|
||||||
|
flags &= ~f
|
||||||
|
|
||||||
|
|
||||||
|
func _TestFlags(f):
|
||||||
|
return (flags & f) == f
|
||||||
|
|
||||||
|
|
||||||
|
func _ChangeFlags(f, bSet):
|
||||||
|
if bSet:
|
||||||
|
_SetFlags(f)
|
||||||
|
else:
|
||||||
|
_ClearFlags(f)
|
||||||
BIN
addons/smoothing/smoothing.png
Normal file
|
After Width: | Height: | Size: 343 B |
|
|
@ -2,16 +2,16 @@
|
||||||
|
|
||||||
importer="texture"
|
importer="texture"
|
||||||
type="CompressedTexture2D"
|
type="CompressedTexture2D"
|
||||||
uid="uid://b30y3pq4u5r0h"
|
uid="uid://bm44ebnxqc82"
|
||||||
path="res://.godot/imported/albedo0.png-8dedb9e51f95ee8e69f9a00bccf9fb16.ctex"
|
path="res://.godot/imported/smoothing.png-6b454a779e636eaa20b6c6ac618bf82a.ctex"
|
||||||
metadata={
|
metadata={
|
||||||
"vram_texture": false
|
"vram_texture": false
|
||||||
}
|
}
|
||||||
|
|
||||||
[deps]
|
[deps]
|
||||||
|
|
||||||
source_file="res://weapons/space_gun/assets/textures/albedo0.png"
|
source_file="res://addons/smoothing/smoothing.png"
|
||||||
dest_files=["res://.godot/imported/albedo0.png-8dedb9e51f95ee8e69f9a00bccf9fb16.ctex"]
|
dest_files=["res://.godot/imported/smoothing.png-6b454a779e636eaa20b6c6ac618bf82a.ctex"]
|
||||||
|
|
||||||
[params]
|
[params]
|
||||||
|
|
||||||
212
addons/smoothing/smoothing_2d.gd
Normal file
|
|
@ -0,0 +1,212 @@
|
||||||
|
# Copyright (c) 2019 Lawnjelly
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in all
|
||||||
|
# copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
|
||||||
|
extends Node2D
|
||||||
|
|
||||||
|
|
||||||
|
@export
|
||||||
|
var target: NodePath:
|
||||||
|
get:
|
||||||
|
return target
|
||||||
|
set(v):
|
||||||
|
target = v
|
||||||
|
if is_inside_tree():
|
||||||
|
_FindTarget()
|
||||||
|
|
||||||
|
var _m_Target: Node2D
|
||||||
|
var _m_Flip:bool = false
|
||||||
|
|
||||||
|
var _m_Trans_curr: Transform2D = Transform2D()
|
||||||
|
var _m_Trans_prev: Transform2D = Transform2D()
|
||||||
|
|
||||||
|
const SF_ENABLED = 1 << 0
|
||||||
|
const SF_GLOBAL_IN = 1 << 1
|
||||||
|
const SF_GLOBAL_OUT = 1 << 2
|
||||||
|
const SF_TOP_LEVEL = 1 << 3
|
||||||
|
const SF_INVISIBLE = 1 << 4
|
||||||
|
|
||||||
|
@export_flags("enabled", "global in", "global out", "top level") var flags: int = SF_ENABLED | SF_GLOBAL_IN | SF_GLOBAL_OUT:
|
||||||
|
set(v):
|
||||||
|
flags = v
|
||||||
|
# we may have enabled or disabled
|
||||||
|
_SetProcessing()
|
||||||
|
get:
|
||||||
|
return flags
|
||||||
|
|
||||||
|
##########################################################################################
|
||||||
|
# USER FUNCS
|
||||||
|
|
||||||
|
|
||||||
|
# call this checked e.g. starting a level, AFTER moving the target
|
||||||
|
# so we can update both the previous and current values
|
||||||
|
func teleport():
|
||||||
|
_RefreshTransform()
|
||||||
|
_m_Trans_prev = _m_Trans_curr
|
||||||
|
|
||||||
|
# call frame upate to make sure all components of the node are set
|
||||||
|
_process(0)
|
||||||
|
|
||||||
|
|
||||||
|
func set_enabled(bEnable: bool):
|
||||||
|
_ChangeFlags(SF_ENABLED, bEnable)
|
||||||
|
_SetProcessing()
|
||||||
|
|
||||||
|
|
||||||
|
func is_enabled():
|
||||||
|
return _TestFlags(SF_ENABLED)
|
||||||
|
|
||||||
|
|
||||||
|
##########################################################################################
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
set_process_priority(100)
|
||||||
|
Engine.set_physics_jitter_fix(0.0)
|
||||||
|
set_as_top_level(_TestFlags(SF_TOP_LEVEL))
|
||||||
|
|
||||||
|
|
||||||
|
func _SetProcessing():
|
||||||
|
var bEnable = _TestFlags(SF_ENABLED)
|
||||||
|
if _TestFlags(SF_INVISIBLE):
|
||||||
|
bEnable = false
|
||||||
|
|
||||||
|
set_process(bEnable)
|
||||||
|
set_physics_process(bEnable)
|
||||||
|
set_as_top_level(_TestFlags(SF_TOP_LEVEL))
|
||||||
|
|
||||||
|
|
||||||
|
func _enter_tree():
|
||||||
|
# might have been moved
|
||||||
|
_FindTarget()
|
||||||
|
|
||||||
|
|
||||||
|
func _notification(what):
|
||||||
|
match what:
|
||||||
|
# invisible turns unchecked processing
|
||||||
|
NOTIFICATION_VISIBILITY_CHANGED:
|
||||||
|
_ChangeFlags(SF_INVISIBLE, is_visible_in_tree() == false)
|
||||||
|
_SetProcessing()
|
||||||
|
|
||||||
|
|
||||||
|
func _RefreshTransform():
|
||||||
|
|
||||||
|
if _HasTarget() == false:
|
||||||
|
return
|
||||||
|
|
||||||
|
_m_Trans_prev = _m_Trans_curr
|
||||||
|
|
||||||
|
if _TestFlags(SF_GLOBAL_IN):
|
||||||
|
_m_Trans_curr = _m_Target.get_global_transform()
|
||||||
|
else:
|
||||||
|
_m_Trans_curr = _m_Target.get_transform()
|
||||||
|
|
||||||
|
_m_Flip = false
|
||||||
|
# Ideally we would use determinant core function, as in commented line below, but we
|
||||||
|
# need to workaround for backward compat.
|
||||||
|
# if (_m_Trans_prev.determinant() < 0) != (_m_Trans_curr.determinant() < 0):
|
||||||
|
|
||||||
|
if (_Determinant_Sign(_m_Trans_prev) != _Determinant_Sign(_m_Trans_curr)):
|
||||||
|
_m_Flip = true
|
||||||
|
|
||||||
|
func _Determinant_Sign(t:Transform2D)->bool:
|
||||||
|
# Workaround Transform2D determinant function not being available
|
||||||
|
# until 3.6 / 4.1.
|
||||||
|
# We calculate determinant manually, slower but compatible to lower
|
||||||
|
# godot versions.
|
||||||
|
var d = (t.x.x * t.y.y) - (t.x.y * t.y.x)
|
||||||
|
return d >= 0.0
|
||||||
|
|
||||||
|
|
||||||
|
func _FindTarget():
|
||||||
|
_m_Target = null
|
||||||
|
|
||||||
|
# If no target has been assigned in the property,
|
||||||
|
# default to using the parent as the target.
|
||||||
|
if target.is_empty():
|
||||||
|
var parent = get_parent()
|
||||||
|
if parent and (parent is Node2D):
|
||||||
|
_m_Target = parent
|
||||||
|
return
|
||||||
|
|
||||||
|
var targ = get_node(target)
|
||||||
|
|
||||||
|
if ! targ:
|
||||||
|
printerr("ERROR SmoothingNode2D : Target " + str(target) + " not found")
|
||||||
|
return
|
||||||
|
|
||||||
|
if not targ is Node2D:
|
||||||
|
printerr("ERROR SmoothingNode2D : Target " + str(target) + " is not Node2D")
|
||||||
|
target = ""
|
||||||
|
return
|
||||||
|
|
||||||
|
# if we got to here targ is correct type
|
||||||
|
_m_Target = targ
|
||||||
|
|
||||||
|
func _HasTarget() -> bool:
|
||||||
|
if _m_Target == null:
|
||||||
|
return false
|
||||||
|
|
||||||
|
# has not been deleted?
|
||||||
|
if is_instance_valid(_m_Target):
|
||||||
|
return true
|
||||||
|
|
||||||
|
_m_Target = null
|
||||||
|
return false
|
||||||
|
|
||||||
|
|
||||||
|
func _process(_delta):
|
||||||
|
var f = Engine.get_physics_interpolation_fraction()
|
||||||
|
|
||||||
|
var tr = Transform2D()
|
||||||
|
tr.origin = lerp(_m_Trans_prev.origin, _m_Trans_curr.origin, f)
|
||||||
|
tr.x = lerp(_m_Trans_prev.x, _m_Trans_curr.x, f)
|
||||||
|
tr.y = lerp(_m_Trans_prev.y, _m_Trans_curr.y, f)
|
||||||
|
|
||||||
|
# When a sprite flip is detected, turn off interpolation for that tick.
|
||||||
|
if _m_Flip:
|
||||||
|
tr = _m_Trans_curr
|
||||||
|
|
||||||
|
if _TestFlags(SF_GLOBAL_OUT) and not _TestFlags(SF_TOP_LEVEL):
|
||||||
|
set_global_transform(tr)
|
||||||
|
else:
|
||||||
|
set_transform(tr)
|
||||||
|
|
||||||
|
|
||||||
|
func _physics_process(_delta):
|
||||||
|
_RefreshTransform()
|
||||||
|
|
||||||
|
|
||||||
|
func _SetFlags(f):
|
||||||
|
flags |= f
|
||||||
|
|
||||||
|
|
||||||
|
func _ClearFlags(f):
|
||||||
|
flags &= ~f
|
||||||
|
|
||||||
|
|
||||||
|
func _TestFlags(f):
|
||||||
|
return (flags & f) == f
|
||||||
|
|
||||||
|
|
||||||
|
func _ChangeFlags(f, bSet):
|
||||||
|
if bSet:
|
||||||
|
_SetFlags(f)
|
||||||
|
else:
|
||||||
|
_ClearFlags(f)
|
||||||
BIN
addons/smoothing/smoothing_2d.png
Normal file
|
After Width: | Height: | Size: 343 B |
34
addons/smoothing/smoothing_2d.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://i3h8ng5fyd1m"
|
||||||
|
path="res://.godot/imported/smoothing_2d.png-4942c58db397caab18506104d957cac1.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://addons/smoothing/smoothing_2d.png"
|
||||||
|
dest_files=["res://.godot/imported/smoothing_2d.png-4942c58db397caab18506104d957cac1.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
17
addons/smoothing/smoothing_plugin.gd
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
@tool
|
||||||
|
extends EditorPlugin
|
||||||
|
|
||||||
|
|
||||||
|
func _enter_tree():
|
||||||
|
# Initialization of the plugin goes here
|
||||||
|
# Add the new type with a name, a parent type, a script and an icon
|
||||||
|
add_custom_type("Smoothing", "Node3D", preload("smoothing.gd"), preload("smoothing.png"))
|
||||||
|
add_custom_type("Smoothing2D", "Node2D", preload("smoothing_2d.gd"), preload("smoothing_2d.png"))
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
func _exit_tree():
|
||||||
|
# Clean-up of the plugin goes here
|
||||||
|
# Always remember to remove_at it from the engine when deactivated
|
||||||
|
remove_custom_type("Smoothing")
|
||||||
|
remove_custom_type("Smoothing2D")
|
||||||
|
|
@ -1,30 +1,32 @@
|
||||||
# This file is part of open-fpsz.
|
# This file is part of open-fpsz.
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
# (at your option) any later version.
|
# (at your option) any later version.
|
||||||
#
|
#
|
||||||
# This program is distributed in the hope that it will be useful,
|
# This program is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
class_name ExplosiveDamageComponent extends Area3D
|
class_name ExplosiveDamageComponent extends Area3D
|
||||||
|
|
||||||
@export var damage : int = 100
|
@export var damage : int = 100
|
||||||
@export var impulse_force : int = 1000
|
@export var impulse_force : int = 1000
|
||||||
|
var damage_dealer : Player
|
||||||
|
|
||||||
func _physics_process(_delta):
|
func _physics_process(_delta : float) -> void:
|
||||||
for body in get_overlapping_bodies():
|
for body in get_overlapping_bodies():
|
||||||
if body is RigidBody3D:
|
if body is RigidBody3D:
|
||||||
var direction = (body.global_position - global_position).normalized()
|
var center_of_mass_global_position : Vector3 = body.center_of_mass + body.global_position
|
||||||
|
var direction : Vector3 = ( center_of_mass_global_position - global_position).normalized()
|
||||||
body.apply_central_impulse(direction * impulse_force)
|
body.apply_central_impulse(direction * impulse_force)
|
||||||
|
|
||||||
for area in get_overlapping_areas():
|
for area in get_overlapping_areas():
|
||||||
if area is HealthComponent and is_multiplayer_authority():
|
if area is HealthComponent and is_multiplayer_authority():
|
||||||
area.damage.rpc(damage)
|
area.damage.rpc(damage, damage_dealer.player_id)
|
||||||
|
|
||||||
set_physics_process(false)
|
set_physics_process(false)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,6 @@
|
||||||
|
|
||||||
[node name="ExplosiveDamage" type="Area3D"]
|
[node name="ExplosiveDamage" type="Area3D"]
|
||||||
collision_layer = 0
|
collision_layer = 0
|
||||||
collision_mask = 5
|
collision_mask = 13
|
||||||
monitorable = false
|
monitorable = false
|
||||||
script = ExtResource("1_2uehk")
|
script = ExtResource("1_2uehk")
|
||||||
|
|
|
||||||
60
components/flag_carry_component.gd
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
# This file is part of open-fpsz.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
class_name FlagCarryComponent extends Node
|
||||||
|
## This component allows its entity to grab, carry and throw flags
|
||||||
|
##
|
||||||
|
## To work correctly the owner MUST set an attachment point for carried flags
|
||||||
|
## and a sensor to detect when flags are within grab range
|
||||||
|
|
||||||
|
@export var max_throw_speed : float = 10.0
|
||||||
|
@export var attachment : Node3D
|
||||||
|
@export var sensor : Area3D
|
||||||
|
|
||||||
|
var _carried_flag : Flag
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
sensor.body_entered.connect(_sensor_on_body_entered)
|
||||||
|
|
||||||
|
func _process(_delta : float) -> void:
|
||||||
|
if _is_carrying():
|
||||||
|
_carried_flag.global_position = attachment.global_position
|
||||||
|
_carried_flag.global_rotation = attachment.global_rotation
|
||||||
|
|
||||||
|
func _grab(flag : Flag) -> void:
|
||||||
|
if not _is_carrying():
|
||||||
|
flag.grab()
|
||||||
|
_carried_flag = flag
|
||||||
|
|
||||||
|
func _release(inherited_velocity : Vector3, throw_speed : float) -> void:
|
||||||
|
if _is_carrying():
|
||||||
|
_carried_flag.drop()
|
||||||
|
_carried_flag.rotation_degrees.x = 0.0
|
||||||
|
_carried_flag.linear_velocity = inherited_velocity + (attachment.global_basis.z * throw_speed)
|
||||||
|
# Throw the flag from some distance in front of the player to avoid regrabbing mid-air
|
||||||
|
_carried_flag.global_position = _carried_flag.global_position + (attachment.global_basis.z * 1.5)
|
||||||
|
_carried_flag = null
|
||||||
|
|
||||||
|
func _is_carrying() -> bool:
|
||||||
|
return _carried_flag != null
|
||||||
|
|
||||||
|
func _sensor_on_body_entered(collider : Flag) -> void:
|
||||||
|
if collider is Flag:
|
||||||
|
_grab(collider)
|
||||||
|
|
||||||
|
func drop() -> void:
|
||||||
|
_release(Vector3.ZERO, 0.0)
|
||||||
|
|
||||||
|
func throw(inherited_velocity : Vector3) -> void:
|
||||||
|
_release(inherited_velocity, max_throw_speed)
|
||||||
6
components/flag_carry_component.tscn
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
[gd_scene load_steps=2 format=3 uid="uid://2t8ql8pkxv6c"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://components/flag_carry_component.gd" id="1_b6ee8"]
|
||||||
|
|
||||||
|
[node name="FlagCarryComponent" type="Node"]
|
||||||
|
script = ExtResource("1_b6ee8")
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
# This file is part of open-fpsz.
|
# This file is part of open-fpsz.
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
# (at your option) any later version.
|
# (at your option) any later version.
|
||||||
#
|
#
|
||||||
# This program is distributed in the hope that it will be useful,
|
# This program is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
class_name HealthComponent extends Area3D
|
class_name HealthComponent extends Area3D
|
||||||
|
|
@ -20,23 +20,23 @@ class_name HealthComponent extends Area3D
|
||||||
health = value
|
health = value
|
||||||
health_changed.emit(value)
|
health_changed.emit(value)
|
||||||
|
|
||||||
signal health_zeroed
|
signal health_zeroed(killer_id : int)
|
||||||
signal health_changed(value : int)
|
signal health_changed(value : float)
|
||||||
|
|
||||||
func _ready():
|
func _ready() -> void:
|
||||||
heal_full()
|
heal_full()
|
||||||
|
|
||||||
@rpc("call_local")
|
@rpc("call_local")
|
||||||
func damage(amount : int) -> void:
|
func damage(amount : float, damage_dealer_id : int) -> void:
|
||||||
health = clampf(health - amount, 0.0, max_health)
|
health = clampf(health - amount, 0.0, max_health)
|
||||||
if health == 0.0:
|
if health == 0.0:
|
||||||
health_zeroed.emit()
|
health_zeroed.emit(damage_dealer_id)
|
||||||
|
|
||||||
@rpc("call_local")
|
@rpc("call_local")
|
||||||
func _heal(amount : int):
|
func _heal(amount : float) -> void:
|
||||||
health = clampf(health + amount, 0.0, max_health)
|
health = clampf(health + amount, 0.0, max_health)
|
||||||
|
|
||||||
func heal_full():
|
func heal_full() -> void:
|
||||||
if not is_multiplayer_authority():
|
if not is_multiplayer_authority():
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,8 @@
|
||||||
[gd_scene load_steps=3 format=3 uid="uid://bof3mg7wgxrmn"]
|
[gd_scene load_steps=2 format=3 uid="uid://bof3mg7wgxrmn"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://components/health_component.gd" id="1_00xis"]
|
[ext_resource type="Script" path="res://components/health_component.gd" id="1_00xis"]
|
||||||
[ext_resource type="Shape3D" uid="uid://dkwljsgaflf31" path="res://entities/player/collision_shape.res" id="2_sgbmt"]
|
|
||||||
|
|
||||||
[node name="HealthComponent" type="Area3D"]
|
[node name="HealthComponent" type="Area3D"]
|
||||||
collision_layer = 4
|
collision_layer = 4
|
||||||
collision_mask = 0
|
collision_mask = 0
|
||||||
script = ExtResource("1_00xis")
|
script = ExtResource("1_00xis")
|
||||||
|
|
||||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
|
||||||
shape = ExtResource("2_sgbmt")
|
|
||||||
|
|
|
||||||
BIN
entities/flag/assets/flag.glb
Normal file
|
|
@ -3,13 +3,13 @@
|
||||||
importer="scene"
|
importer="scene"
|
||||||
importer_version=1
|
importer_version=1
|
||||||
type="PackedScene"
|
type="PackedScene"
|
||||||
uid="uid://clq4uym4arpv3"
|
uid="uid://d3l7fvbdg6m5g"
|
||||||
path="res://.godot/imported/SpaceGun.glb-ee1e940c9dd77150eaf36c6537feefef.scn"
|
path="res://.godot/imported/flag.glb-0a51d316969707bbb012f3287265227f.scn"
|
||||||
|
|
||||||
[deps]
|
[deps]
|
||||||
|
|
||||||
source_file="res://weapons/space_gun/assets/SpaceGun.glb"
|
source_file="res://entities/flag/assets/flag.glb"
|
||||||
dest_files=["res://.godot/imported/SpaceGun.glb-ee1e940c9dd77150eaf36c6537feefef.scn"]
|
dest_files=["res://.godot/imported/flag.glb-0a51d316969707bbb012f3287265227f.scn"]
|
||||||
|
|
||||||
[params]
|
[params]
|
||||||
|
|
||||||
|
|
@ -29,17 +29,6 @@ animation/fps=30
|
||||||
animation/trimming=false
|
animation/trimming=false
|
||||||
animation/remove_immutable_tracks=true
|
animation/remove_immutable_tracks=true
|
||||||
import_script/path=""
|
import_script/path=""
|
||||||
_subresources={
|
_subresources={}
|
||||||
"materials": {
|
|
||||||
"_defaultMat": {
|
|
||||||
"use_external/enabled": true,
|
|
||||||
"use_external/path": ""
|
|
||||||
},
|
|
||||||
"dark": {
|
|
||||||
"use_external/enabled": true,
|
|
||||||
"use_external/path": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gltf/naming_version=1
|
gltf/naming_version=1
|
||||||
gltf/embedded_image_handling=2
|
gltf/embedded_image_handling=1
|
||||||
17
entities/flag/flag.gd
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
class_name Flag extends Node3D
|
||||||
|
|
||||||
|
enum FlagState { FLAG_STATE_ON_STAND, FLAG_STATE_DROPPED, FLAG_STATE_TAKEN }
|
||||||
|
|
||||||
|
@export var flag_state : FlagState = FlagState.FLAG_STATE_ON_STAND
|
||||||
|
|
||||||
|
func can_be_grabbed() -> bool:
|
||||||
|
return flag_state != FlagState.FLAG_STATE_TAKEN
|
||||||
|
|
||||||
|
func grab() -> void:
|
||||||
|
if flag_state != FlagState.FLAG_STATE_TAKEN:
|
||||||
|
flag_state = FlagState.FLAG_STATE_TAKEN
|
||||||
|
|
||||||
|
func drop() -> void:
|
||||||
|
if flag_state == FlagState.FLAG_STATE_TAKEN:
|
||||||
|
flag_state = FlagState.FLAG_STATE_DROPPED
|
||||||
|
|
||||||
51
entities/flag/flag.tscn
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
[gd_scene load_steps=7 format=3 uid="uid://c88l3h0ph00c7"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://entities/flag/flag.gd" id="1_y7d3d"]
|
||||||
|
[ext_resource type="PackedScene" path="res://entities/flag/assets/flag.glb" id="2_i78em"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://bcgkc5fhhyauv" path="res://entities/flag/waypoint.tscn" id="3_tu6jg"]
|
||||||
|
|
||||||
|
[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_4ymrw"]
|
||||||
|
bounce = 0.5
|
||||||
|
|
||||||
|
[sub_resource type="BoxShape3D" id="BoxShape3D_fkf1k"]
|
||||||
|
size = Vector3(0.5, 2, 0.1)
|
||||||
|
|
||||||
|
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_lpijf"]
|
||||||
|
properties/0/path = NodePath(".:position")
|
||||||
|
properties/0/spawn = true
|
||||||
|
properties/0/replication_mode = 1
|
||||||
|
properties/1/path = NodePath(".:linear_velocity")
|
||||||
|
properties/1/spawn = true
|
||||||
|
properties/1/replication_mode = 1
|
||||||
|
properties/2/path = NodePath(".:flag_state")
|
||||||
|
properties/2/spawn = true
|
||||||
|
properties/2/replication_mode = 2
|
||||||
|
|
||||||
|
[node name="Flag" type="RigidBody3D"]
|
||||||
|
collision_layer = 8
|
||||||
|
collision_mask = 2147483656
|
||||||
|
axis_lock_angular_x = true
|
||||||
|
axis_lock_angular_y = true
|
||||||
|
axis_lock_angular_z = true
|
||||||
|
mass = 40.0
|
||||||
|
physics_material_override = SubResource("PhysicsMaterial_4ymrw")
|
||||||
|
center_of_mass_mode = 1
|
||||||
|
center_of_mass = Vector3(0, 0.5, 0)
|
||||||
|
continuous_cd = true
|
||||||
|
script = ExtResource("1_y7d3d")
|
||||||
|
|
||||||
|
[node name="Mesh" parent="." instance=ExtResource("2_i78em")]
|
||||||
|
transform = Transform3D(0.33, 0, 0, 0, 0.421029, 0, 0, 0, 0.33, 0, 0.0744106, 0)
|
||||||
|
|
||||||
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
|
||||||
|
shape = SubResource("BoxShape3D_fkf1k")
|
||||||
|
|
||||||
|
[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."]
|
||||||
|
replication_config = SubResource("SceneReplicationConfig_lpijf")
|
||||||
|
|
||||||
|
[node name="WaypointAttachment" type="Marker3D" parent="."]
|
||||||
|
|
||||||
|
[node name="Waypoint" parent="WaypointAttachment" node_paths=PackedStringArray("attach_point", "flag") instance=ExtResource("3_tu6jg")]
|
||||||
|
attach_point = NodePath("..")
|
||||||
|
flag = NodePath("../..")
|
||||||
49
entities/flag/waypoint.gd
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
# This file is part of open-fpsz.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
extends Control
|
||||||
|
|
||||||
|
@export var attach_point : Node3D
|
||||||
|
@export var flag : Flag
|
||||||
|
|
||||||
|
@onready var _iff_container : Control = $IFFContainer
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
attach_point.transform = attach_point.transform.translated(
|
||||||
|
Vector3(0, flag.get_node("CollisionShape3D").shape.size.y, 0))
|
||||||
|
|
||||||
|
func _process(_delta : float) -> void:
|
||||||
|
var camera : Camera3D = get_viewport().get_camera_3d()
|
||||||
|
var viewport_rect : Rect2 = get_viewport_rect()
|
||||||
|
# if the player is NOT infront of the camera or camera does NOT have LOS to player
|
||||||
|
if camera.is_position_behind(attach_point.global_position):
|
||||||
|
_iff_container.hide() # hide the IFF and exit function
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
_iff_container.show() # display the IFF
|
||||||
|
|
||||||
|
# get the screen location of the players head
|
||||||
|
var new_iff_position : Vector2 = camera.unproject_position(attach_point.global_position)
|
||||||
|
|
||||||
|
# check if the unprojected point lies inside the viewport
|
||||||
|
if !Rect2(Vector2(0, 0), viewport_rect.size).has_point(new_iff_position):
|
||||||
|
_iff_container.hide() # hide the IFF and exit function
|
||||||
|
return
|
||||||
|
|
||||||
|
# move the IFF up so the bottom of it is at the players head
|
||||||
|
new_iff_position.y -= _iff_container.size.y
|
||||||
|
# move the IFF left so it's centered horizontally above players head
|
||||||
|
new_iff_position.x -= _iff_container.size.x / 2
|
||||||
|
# set the position of the IFF
|
||||||
|
position = new_iff_position
|
||||||
27
entities/flag/waypoint.tscn
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
[gd_scene load_steps=2 format=3 uid="uid://bcgkc5fhhyauv"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://entities/flag/waypoint.gd" id="1_gmnl6"]
|
||||||
|
|
||||||
|
[node name="IFF" type="Control"]
|
||||||
|
layout_mode = 3
|
||||||
|
anchors_preset = 0
|
||||||
|
script = ExtResource("1_gmnl6")
|
||||||
|
|
||||||
|
[node name="IFFContainer" type="MarginContainer" parent="."]
|
||||||
|
layout_mode = 0
|
||||||
|
offset_right = 11.0
|
||||||
|
offset_bottom = 20.0
|
||||||
|
mouse_filter = 2
|
||||||
|
|
||||||
|
[node name="Chevron" type="Label" parent="IFFContainer"]
|
||||||
|
layout_direction = 2
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 1
|
||||||
|
theme_override_colors/font_color = Color(0, 1, 1, 0.784314)
|
||||||
|
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||||
|
theme_override_constants/outline_size = 3
|
||||||
|
theme_override_constants/line_spacing = -20
|
||||||
|
theme_override_font_sizes/font_size = 14
|
||||||
|
text = "▼"
|
||||||
|
horizontal_alignment = 1
|
||||||
|
vertical_alignment = 2
|
||||||
|
|
@ -3,23 +3,23 @@ class_name Vanguard extends Node
|
||||||
@export var spine_ik_target_attachment : Node3D
|
@export var spine_ik_target_attachment : Node3D
|
||||||
|
|
||||||
@onready var animation_tree : AnimationTree = $AnimationTree
|
@onready var animation_tree : AnimationTree = $AnimationTree
|
||||||
@onready var spine_ik = $Node/Skeleton3D/SpineIK
|
@onready var spine_ik : SkeletonIK3D = $Node/Skeleton3D/SpineIK
|
||||||
@onready var spine_ik_target = $SpineIKTarget
|
@onready var spine_ik_target : Node3D = $SpineIKTarget
|
||||||
|
|
||||||
enum GroundState { GROUND_STATE_GROUNDED, GROUND_STATE_MID_AIR, GROUND_STATE_DEAD }
|
enum GroundState { GROUND_STATE_GROUNDED, GROUND_STATE_MID_AIR, GROUND_STATE_DEAD }
|
||||||
|
|
||||||
func _ready():
|
func _ready() -> void:
|
||||||
spine_ik.start()
|
spine_ik.start()
|
||||||
|
|
||||||
func _process(_delta):
|
func _process(_delta : float) -> void:
|
||||||
spine_ik_target.global_transform = spine_ik_target_attachment.global_transform
|
spine_ik_target.global_transform = spine_ik_target_attachment.global_transform
|
||||||
|
|
||||||
func set_locomotion(locomotion : Vector2, ground_speed_factor : float) -> void:
|
func set_locomotion(locomotion : Vector2, ground_speed_factor : float) -> void:
|
||||||
animation_tree.set("parameters/Locomotion/blend_position", locomotion)
|
animation_tree.set("parameters/Locomotion/blend_position", locomotion)
|
||||||
animation_tree.set("parameters/GroundSpeed/scale", ground_speed_factor)
|
animation_tree.set("parameters/GroundSpeed/scale", ground_speed_factor)
|
||||||
|
|
||||||
func set_ground_state(ground_state : GroundState):
|
func set_ground_state(ground_state : GroundState) -> void:
|
||||||
var transition_name = "grounded"
|
var transition_name : String = "grounded"
|
||||||
if ground_state == GroundState.GROUND_STATE_MID_AIR:
|
if ground_state == GroundState.GROUND_STATE_MID_AIR:
|
||||||
transition_name = "mid_air"
|
transition_name = "mid_air"
|
||||||
if ground_state == GroundState.GROUND_STATE_DEAD:
|
if ground_state == GroundState.GROUND_STATE_DEAD:
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
importer="texture"
|
importer="texture"
|
||||||
type="CompressedTexture2D"
|
type="CompressedTexture2D"
|
||||||
uid="uid://ia3bdpe4rm1m"
|
uid="uid://ia3bdpe4rm1m"
|
||||||
path.s3tc="res://.godot/imported/vanguard_0.png-601f36bc664114e126d425d5f45085ef.s3tc.ctex"
|
path.bptc="res://.godot/imported/vanguard_0.png-601f36bc664114e126d425d5f45085ef.bptc.ctex"
|
||||||
metadata={
|
metadata={
|
||||||
"imported_formats": ["s3tc_bptc"],
|
"imported_formats": ["s3tc_bptc"],
|
||||||
"vram_texture": true
|
"vram_texture": true
|
||||||
|
|
@ -13,12 +13,12 @@ generator_parameters={}
|
||||||
[deps]
|
[deps]
|
||||||
|
|
||||||
source_file="res://entities/player/assets/vanguard_0.png"
|
source_file="res://entities/player/assets/vanguard_0.png"
|
||||||
dest_files=["res://.godot/imported/vanguard_0.png-601f36bc664114e126d425d5f45085ef.s3tc.ctex"]
|
dest_files=["res://.godot/imported/vanguard_0.png-601f36bc664114e126d425d5f45085ef.bptc.ctex"]
|
||||||
|
|
||||||
[params]
|
[params]
|
||||||
|
|
||||||
compress/mode=2
|
compress/mode=2
|
||||||
compress/high_quality=false
|
compress/high_quality=true
|
||||||
compress/lossy_quality=0.7
|
compress/lossy_quality=0.7
|
||||||
compress/hdr_compression=1
|
compress/hdr_compression=1
|
||||||
compress/normal_map=0
|
compress/normal_map=0
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
importer="texture"
|
importer="texture"
|
||||||
type="CompressedTexture2D"
|
type="CompressedTexture2D"
|
||||||
uid="uid://bvgfmpb2l1juf"
|
uid="uid://bvgfmpb2l1juf"
|
||||||
path.s3tc="res://.godot/imported/vanguard_1.png-39b5712c4c4119a42b3540a159f8b3f2.s3tc.ctex"
|
path.bptc="res://.godot/imported/vanguard_1.png-39b5712c4c4119a42b3540a159f8b3f2.bptc.ctex"
|
||||||
metadata={
|
metadata={
|
||||||
"imported_formats": ["s3tc_bptc"],
|
"imported_formats": ["s3tc_bptc"],
|
||||||
"vram_texture": true
|
"vram_texture": true
|
||||||
|
|
@ -13,12 +13,12 @@ generator_parameters={}
|
||||||
[deps]
|
[deps]
|
||||||
|
|
||||||
source_file="res://entities/player/assets/vanguard_1.png"
|
source_file="res://entities/player/assets/vanguard_1.png"
|
||||||
dest_files=["res://.godot/imported/vanguard_1.png-39b5712c4c4119a42b3540a159f8b3f2.s3tc.ctex"]
|
dest_files=["res://.godot/imported/vanguard_1.png-39b5712c4c4119a42b3540a159f8b3f2.bptc.ctex"]
|
||||||
|
|
||||||
[params]
|
[params]
|
||||||
|
|
||||||
compress/mode=2
|
compress/mode=2
|
||||||
compress/high_quality=false
|
compress/high_quality=true
|
||||||
compress/lossy_quality=0.7
|
compress/lossy_quality=0.7
|
||||||
compress/hdr_compression=1
|
compress/hdr_compression=1
|
||||||
compress/normal_map=1
|
compress/normal_map=1
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
importer="texture"
|
importer="texture"
|
||||||
type="CompressedTexture2D"
|
type="CompressedTexture2D"
|
||||||
uid="uid://vtrbc3eja3df"
|
uid="uid://vtrbc3eja3df"
|
||||||
path.s3tc="res://.godot/imported/vanguard_2.png-986e3665904b0d4758f584d5d3b7b726.s3tc.ctex"
|
path.bptc="res://.godot/imported/vanguard_2.png-986e3665904b0d4758f584d5d3b7b726.bptc.ctex"
|
||||||
metadata={
|
metadata={
|
||||||
"imported_formats": ["s3tc_bptc"],
|
"imported_formats": ["s3tc_bptc"],
|
||||||
"vram_texture": true
|
"vram_texture": true
|
||||||
|
|
@ -13,12 +13,12 @@ generator_parameters={}
|
||||||
[deps]
|
[deps]
|
||||||
|
|
||||||
source_file="res://entities/player/assets/vanguard_2.png"
|
source_file="res://entities/player/assets/vanguard_2.png"
|
||||||
dest_files=["res://.godot/imported/vanguard_2.png-986e3665904b0d4758f584d5d3b7b726.s3tc.ctex"]
|
dest_files=["res://.godot/imported/vanguard_2.png-986e3665904b0d4758f584d5d3b7b726.bptc.ctex"]
|
||||||
|
|
||||||
[params]
|
[params]
|
||||||
|
|
||||||
compress/mode=2
|
compress/mode=2
|
||||||
compress/high_quality=false
|
compress/high_quality=true
|
||||||
compress/lossy_quality=0.7
|
compress/lossy_quality=0.7
|
||||||
compress/hdr_compression=1
|
compress/hdr_compression=1
|
||||||
compress/normal_map=1
|
compress/normal_map=1
|
||||||
|
|
|
||||||
4
entities/player/collision_shape.tres
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
[gd_resource type="CapsuleShape3D" format=3 uid="uid://cb8esdlnottdn"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
radius = 0.25
|
||||||
|
|
@ -1,24 +1,27 @@
|
||||||
# This file is part of open-fpsz.
|
# This file is part of open-fpsz.
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
# (at your option) any later version.
|
# (at your option) any later version.
|
||||||
#
|
#
|
||||||
# This program is distributed in the hope that it will be useful,
|
# This program is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
class_name Player extends RigidBody3D
|
class_name Player extends RigidBody3D
|
||||||
|
|
||||||
enum PlayerState { PLAYER_ALIVE, PLAYER_DEAD }
|
enum PlayerState { PLAYER_ALIVE, PLAYER_DEAD }
|
||||||
|
|
||||||
|
@export var iff : Control
|
||||||
|
|
||||||
@export_category("Parameters")
|
@export_category("Parameters")
|
||||||
@export var ground_speed : float = 48 / 3.6 # m/s
|
@export var ground_speed : float = 48 / 3.6 # m/s
|
||||||
@export var aerial_control_force : int = 400
|
@export var aerial_control_force : int = 400
|
||||||
|
@export var jump_height : float = 2.0
|
||||||
@export var max_floor_angle : float = 60
|
@export var max_floor_angle : float = 60
|
||||||
|
|
||||||
@export_group("Jetpack")
|
@export_group("Jetpack")
|
||||||
|
|
@ -31,97 +34,130 @@ enum PlayerState { PLAYER_ALIVE, PLAYER_DEAD }
|
||||||
@export var jetpack_vertical_force : float = 800
|
@export var jetpack_vertical_force : float = 800
|
||||||
|
|
||||||
@export_group("State")
|
@export_group("State")
|
||||||
@export var player_state = PlayerState.PLAYER_ALIVE
|
@export var player_state : PlayerState = PlayerState.PLAYER_ALIVE
|
||||||
@export var player_id = 1:
|
@export var player_id : int = 1:
|
||||||
set(id):
|
set(id):
|
||||||
player_id = id
|
player_id = id
|
||||||
$PlayerInput.set_multiplayer_authority(id)
|
$PlayerInput.set_multiplayer_authority(id)
|
||||||
|
@export var nickname : String
|
||||||
|
|
||||||
@onready var input : PlayerInput = $PlayerInput
|
@onready var input : PlayerInput = $PlayerInput
|
||||||
@onready var camera = $SpringArm3D/Camera3D
|
@onready var camera : Camera3D = $Smoothing/SpringArm3D/Camera3D
|
||||||
@onready var hud = $HUD
|
@onready var hud : CanvasLayer = $HUD
|
||||||
@onready var iff = $ThirdPerson/IFF
|
@onready var shape_cast : ShapeCast3D = $ShapeCast3D
|
||||||
@onready var shape_cast = $ShapeCast3D
|
@onready var weapon : Node3D = $Smoothing/SpringArm3D/Inventory/SpaceGun
|
||||||
@onready var weapon = $SpringArm3D/Inventory/SpaceGun
|
|
||||||
@onready var animation_player : AnimationPlayer = $AnimationPlayer
|
@onready var animation_player : AnimationPlayer = $AnimationPlayer
|
||||||
@onready var health_component = $HealthComponent
|
@onready var health_component : Area3D = $HealthComponent
|
||||||
@onready var spring_arm_height = $SpringArm3D.position.y
|
@onready var collision_shape : CollisionShape3D = $CollisionShape3D
|
||||||
|
@onready var flag_carry_component : FlagCarryComponent = $FlagCarryComponent
|
||||||
|
@onready var spring_arm_height : float = $Smoothing/SpringArm3D.position.y
|
||||||
@onready var _original_weapon_transform : Transform3D = weapon.transform
|
@onready var _original_weapon_transform : Transform3D = weapon.transform
|
||||||
|
@onready var flag_carry_attachment : Node3D = $Smoothing/SpringArm3D/FlagCarryAttachment
|
||||||
|
@onready var _game_settings : Settings = get_node("/root/GlobalSettings")
|
||||||
|
|
||||||
signal died(player)
|
signal died(player : Player, killer_id : int)
|
||||||
signal energy_changed(energy)
|
signal energy_changed(energy : float)
|
||||||
|
|
||||||
var g : float = ProjectSettings.get_setting("physics/3d/default_gravity") # in m/s²
|
var g : float = ProjectSettings.get_setting("physics/3d/default_gravity") # in m/s²
|
||||||
var gravity : Vector3 = g * ProjectSettings.get_setting("physics/3d/default_gravity_vector")
|
var gravity : Vector3 = g * ProjectSettings.get_setting("physics/3d/default_gravity_vector")
|
||||||
var _jumping = false
|
var _jumping : bool = false
|
||||||
|
|
||||||
func _ready():
|
@rpc("call_local")
|
||||||
|
func set_nickname(value : String) -> void:
|
||||||
|
nickname = value
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
energy_changed.connect(hud._on_energy_changed)
|
energy_changed.connect(hud._on_energy_changed)
|
||||||
health_component.health_changed.connect(hud._on_health_changed)
|
health_component.health_changed.connect(hud._on_health_changed)
|
||||||
health_component.health_changed.connect(iff._on_health_changed)
|
health_component.health_changed.connect(iff._on_health_changed)
|
||||||
health_component.health_changed.emit(health_component.health)
|
health_component.health_changed.emit(health_component.health)
|
||||||
health_component.health_zeroed.connect(_die)
|
health_component.health_zeroed.connect(die)
|
||||||
if _is_first_person():
|
|
||||||
camera.current = true
|
|
||||||
remove_child($ThirdPerson)
|
|
||||||
else:
|
|
||||||
remove_child($HUD)
|
|
||||||
weapon.hide()
|
|
||||||
input.fired_primary.connect(_fire_primary)
|
input.fired_primary.connect(_fire_primary)
|
||||||
input.jumped.connect(_jump)
|
input.jumped.connect(_jump)
|
||||||
|
input.throwed_flag.connect(_throw_flag)
|
||||||
|
|
||||||
func _is_first_person():
|
input.MOUSE_SENSITIVITY = _game_settings.mouse_sensitivity
|
||||||
|
input.inverted_y_axis = _game_settings.inverted_y_axis
|
||||||
|
|
||||||
|
if _is_pawn():
|
||||||
|
camera.current = true
|
||||||
|
camera.fov = _game_settings.fov
|
||||||
|
# set the spring arm translation to be about head height level
|
||||||
|
$Smoothing/SpringArm3D.transform = Transform3D().translated(Vector3(0, collision_shape.shape.height / 2, 0) * 0.9)
|
||||||
|
flag_carry_attachment.hide()
|
||||||
|
|
||||||
|
$Smoothing.remove_child($Smoothing/ThirdPerson)
|
||||||
|
else:
|
||||||
|
# set the iff attachment translation to be about head height level
|
||||||
|
$Smoothing/ThirdPerson/IFFAttachment.transform = Transform3D().translated(Vector3(0, collision_shape.shape.height / 2, 0) * 0.9)
|
||||||
|
remove_child(hud)
|
||||||
|
weapon.hide()
|
||||||
|
|
||||||
|
func _is_pawn() -> bool:
|
||||||
return player_id == multiplayer.get_unique_id()
|
return player_id == multiplayer.get_unique_id()
|
||||||
|
|
||||||
func _fire_primary():
|
func _fire_primary() -> void:
|
||||||
if _is_player_dead():
|
if _is_player_dead():
|
||||||
return
|
return
|
||||||
if not weapon.can_fire():
|
if not weapon.can_fire():
|
||||||
return
|
return
|
||||||
var current_weapon_transform = weapon.transform
|
var current_weapon_transform : Transform3D = weapon.transform
|
||||||
weapon.transform = _original_weapon_transform
|
weapon.transform = _original_weapon_transform
|
||||||
weapon.fire_primary()
|
weapon.fire_primary()
|
||||||
weapon.transform = current_weapon_transform
|
weapon.transform = current_weapon_transform
|
||||||
if _is_first_person():
|
if _is_pawn():
|
||||||
animation_player.stop()
|
animation_player.stop()
|
||||||
animation_player.play("shoot")
|
animation_player.play("shoot")
|
||||||
|
|
||||||
func _jump():
|
func _jump() -> void:
|
||||||
if _is_player_dead():
|
if _is_player_dead():
|
||||||
return
|
return
|
||||||
_jumping = true
|
_jumping = true
|
||||||
|
|
||||||
|
func _throw_flag() -> void:
|
||||||
|
flag_carry_component.throw(linear_velocity)
|
||||||
|
|
||||||
func is_on_floor() -> bool:
|
func is_on_floor() -> bool:
|
||||||
return shape_cast.is_colliding()
|
if shape_cast.is_colliding():
|
||||||
|
for i in shape_cast.get_collision_count():
|
||||||
|
var collider : Object = shape_cast.get_collider(i)
|
||||||
|
if collider is Terrain3D:
|
||||||
|
return true
|
||||||
|
return false
|
||||||
|
|
||||||
func _is_skiing() -> bool:
|
func _is_skiing() -> bool:
|
||||||
return input.skiing
|
return input.skiing
|
||||||
|
|
||||||
func _handle_aerial_control(delta, direction):
|
func _handle_aerial_control(direction : Vector3) -> void:
|
||||||
if not input.jetting and not is_on_floor():
|
if not input.jetting and not is_on_floor():
|
||||||
apply_force(direction * aerial_control_force)
|
apply_force(direction * aerial_control_force)
|
||||||
|
|
||||||
func _handle_jetpack(delta, direction):
|
func _handle_jetpack(direction : Vector3) -> void:
|
||||||
if input.jetting:
|
if input.jetting:
|
||||||
if energy > 0:
|
if energy > 0:
|
||||||
var up_vector = Vector3.UP * jetpack_vertical_force * jetpack_force_factor
|
var up_vector : Vector3 = Vector3.UP * jetpack_vertical_force * jetpack_force_factor
|
||||||
var side_vector = direction * jetpack_horizontal_force * jetpack_force_factor
|
var side_vector : Vector3 = direction * jetpack_horizontal_force * jetpack_force_factor
|
||||||
apply_force(up_vector + side_vector)
|
apply_force(up_vector + side_vector)
|
||||||
energy -= energy_drain_rate * delta
|
|
||||||
|
func _update_jetpack_energy(delta : float) -> void:
|
||||||
|
if input.jetting:
|
||||||
|
if energy > 0:
|
||||||
|
energy -= energy_drain_rate * delta
|
||||||
else:
|
else:
|
||||||
energy += energy_charge_rate * delta
|
energy += energy_charge_rate * delta
|
||||||
|
|
||||||
energy = clamp(energy, 0, energy_max)
|
energy = clamp(energy, 0, energy_max)
|
||||||
energy_changed.emit(energy)
|
energy_changed.emit(energy)
|
||||||
|
|
||||||
func _process(_delta):
|
func _process(_delta : float) -> void:
|
||||||
if _is_player_dead():
|
if _is_player_dead():
|
||||||
iff.hide()
|
iff.hide()
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
iff.show()
|
iff.show()
|
||||||
if not _is_first_person():
|
if not _is_pawn():
|
||||||
$ThirdPerson/PlayerMesh.global_transform.basis = Basis.from_euler(Vector3(0.0, input.camera_rotation.x + PI, 0.0))
|
$Smoothing/ThirdPerson/PlayerMesh.global_transform.basis = Basis.from_euler(Vector3(0.0, input.camera_rotation.x + PI, 0.0))
|
||||||
else:
|
else:
|
||||||
if animation_player.current_animation == "shoot":
|
if animation_player.current_animation == "shoot":
|
||||||
pass
|
pass
|
||||||
|
|
@ -129,21 +165,25 @@ func _process(_delta):
|
||||||
animation_player.play("idle")
|
animation_player.play("idle")
|
||||||
%SpringArm3D.global_transform.basis = Basis.from_euler(Vector3(input.camera_rotation.y, input.camera_rotation.x, 0.0))
|
%SpringArm3D.global_transform.basis = Basis.from_euler(Vector3(input.camera_rotation.y, input.camera_rotation.x, 0.0))
|
||||||
|
|
||||||
func _physics_process(delta):
|
func _physics_process(delta : float) -> void:
|
||||||
|
_update_jetpack_energy(delta)
|
||||||
|
|
||||||
|
func _handle_movement() -> void:
|
||||||
# retrieve user's direction vector
|
# retrieve user's direction vector
|
||||||
var _input_dir = input.direction
|
var _input_dir : Vector2 = input.direction
|
||||||
# compute direction in local space
|
# compute direction in local space
|
||||||
var _direction = (transform.basis * Vector3(_input_dir.x, 0, _input_dir.y)).normalized()
|
var _direction : Vector3 = (transform.basis * Vector3(_input_dir.x, 0, _input_dir.y)).normalized()
|
||||||
|
|
||||||
_update_third_person_animations()
|
_update_third_person_animations()
|
||||||
|
|
||||||
if _is_player_dead():
|
if _is_player_dead():
|
||||||
return
|
return
|
||||||
|
|
||||||
# adjust direction based on spring arm rotation
|
# adjust direction based on spring arm rotation
|
||||||
_direction = _direction.rotated(Vector3.UP, $SpringArm3D.rotation.y)
|
_direction = _direction.rotated(Vector3.UP, $Smoothing/SpringArm3D.rotation.y)
|
||||||
|
|
||||||
_handle_aerial_control(delta, _direction)
|
_handle_aerial_control(_direction)
|
||||||
_handle_jetpack(delta, _direction)
|
_handle_jetpack(_direction)
|
||||||
|
|
||||||
# handle ski
|
# handle ski
|
||||||
if _is_skiing():
|
if _is_skiing():
|
||||||
|
|
@ -154,9 +194,9 @@ func _physics_process(delta):
|
||||||
if is_on_floor():
|
if is_on_floor():
|
||||||
if not _direction.is_zero_approx() and not _is_skiing():
|
if not _direction.is_zero_approx() and not _is_skiing():
|
||||||
# retrieve collision normal
|
# retrieve collision normal
|
||||||
var normal = shape_cast.get_collision_normal(0)
|
var normal : Vector3 = shape_cast.get_collision_normal(0)
|
||||||
# calculate the angle between the ground normal and the up vector
|
# calculate the angle between the ground normal and the up vector
|
||||||
var slope_angle = rad_to_deg(acos(normal.dot(Vector3.UP)))
|
var slope_angle : float = rad_to_deg(acos(normal.dot(Vector3.UP)))
|
||||||
# check if the slope angle exceeds the maximum slope angle
|
# check if the slope angle exceeds the maximum slope angle
|
||||||
if slope_angle <= max_floor_angle:
|
if slope_angle <= max_floor_angle:
|
||||||
# adjust direction based on the floor normal to align with the slope
|
# adjust direction based on the floor normal to align with the slope
|
||||||
|
|
@ -165,15 +205,19 @@ func _physics_process(delta):
|
||||||
linear_velocity = lerp(linear_velocity, _direction * ground_speed, .1)
|
linear_velocity = lerp(linear_velocity, _direction * ground_speed, .1)
|
||||||
|
|
||||||
if _jumping:
|
if _jumping:
|
||||||
linear_velocity.y = sqrt(2 * abs((mass * gravity * delta).y) * 1)
|
var v : float = sqrt(2 * g * jump_height)
|
||||||
|
apply_central_impulse(Vector3(0, mass * v, 0))
|
||||||
|
|
||||||
_jumping = false
|
_jumping = false
|
||||||
|
|
||||||
func _update_third_person_animations():
|
func _integrate_forces(_state : PhysicsDirectBodyState3D) -> void:
|
||||||
if _is_first_person():
|
_handle_movement()
|
||||||
|
|
||||||
|
func _update_third_person_animations() -> void:
|
||||||
|
if _is_pawn():
|
||||||
return
|
return
|
||||||
|
|
||||||
var tp_player : Vanguard = $ThirdPerson/PlayerMesh
|
var tp_player : Vanguard = $Smoothing/ThirdPerson/PlayerMesh
|
||||||
|
|
||||||
if _is_player_dead():
|
if _is_player_dead():
|
||||||
tp_player.set_ground_state(Vanguard.GroundState.GROUND_STATE_DEAD)
|
tp_player.set_ground_state(Vanguard.GroundState.GROUND_STATE_DEAD)
|
||||||
|
|
@ -183,28 +227,22 @@ func _update_third_person_animations():
|
||||||
tp_player.set_ground_state(Vanguard.GroundState.GROUND_STATE_GROUNDED)
|
tp_player.set_ground_state(Vanguard.GroundState.GROUND_STATE_GROUNDED)
|
||||||
else:
|
else:
|
||||||
tp_player.set_ground_state(Vanguard.GroundState.GROUND_STATE_MID_AIR)
|
tp_player.set_ground_state(Vanguard.GroundState.GROUND_STATE_MID_AIR)
|
||||||
var local_velocity = (tp_player.global_basis.inverse() * linear_velocity)
|
var local_velocity : Vector3 = (tp_player.global_basis.inverse() * linear_velocity)
|
||||||
const bias : float = 1.2 # Basically match feet speed with ground speed
|
const bias : float = 1.2 # Basically match feet speed with ground speed
|
||||||
tp_player.set_locomotion(Vector2(local_velocity.x, local_velocity.z), bias)
|
tp_player.set_locomotion(Vector2(local_velocity.x, local_velocity.z), bias)
|
||||||
|
|
||||||
func _is_player_dead():
|
func _is_player_dead() -> bool:
|
||||||
return player_state == PlayerState.PLAYER_DEAD
|
return player_state != PlayerState.PLAYER_ALIVE
|
||||||
|
|
||||||
func _die():
|
func die(killer_id : int) -> void:
|
||||||
|
flag_carry_component.drop()
|
||||||
player_state = PlayerState.PLAYER_DEAD
|
player_state = PlayerState.PLAYER_DEAD
|
||||||
if _is_first_person():
|
if _is_pawn():
|
||||||
animation_player.stop()
|
|
||||||
animation_player.play("death")
|
animation_player.play("death")
|
||||||
var tween = create_tween()
|
died.emit(self, killer_id)
|
||||||
tween.tween_interval(4)
|
|
||||||
tween.tween_callback(func():
|
|
||||||
died.emit(self)
|
|
||||||
if _is_first_person():
|
|
||||||
animation_player.stop()
|
|
||||||
)
|
|
||||||
|
|
||||||
func respawn(location):
|
func respawn(location : Vector3) -> void:
|
||||||
|
player_state = PlayerState.PLAYER_ALIVE
|
||||||
linear_velocity = Vector3()
|
linear_velocity = Vector3()
|
||||||
health_component.heal_full()
|
health_component.heal_full()
|
||||||
position = location
|
position = location
|
||||||
player_state = PlayerState.PLAYER_ALIVE
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,15 @@
|
||||||
[gd_scene load_steps=20 format=3 uid="uid://cbhx1xme0sb7k"]
|
[gd_scene load_steps=21 format=3 uid="uid://cbhx1xme0sb7k"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://entities/player/player.gd" id="1_mk68k"]
|
[ext_resource type="Script" path="res://entities/player/player.gd" id="1_mk68k"]
|
||||||
[ext_resource type="Shape3D" uid="uid://dkwljsgaflf31" path="res://entities/player/collision_shape.res" id="2_8rtw3"]
|
|
||||||
[ext_resource type="PackedScene" uid="uid://drbefw6akui2v" path="res://entities/player/assets/vanguard.tscn" id="2_beyex"]
|
[ext_resource type="PackedScene" uid="uid://drbefw6akui2v" path="res://entities/player/assets/vanguard.tscn" id="2_beyex"]
|
||||||
|
[ext_resource type="Shape3D" uid="uid://cb8esdlnottdn" path="res://entities/player/collision_shape.tres" id="2_vjqny"]
|
||||||
[ext_resource type="PackedScene" uid="uid://bcv81ku26xo" path="res://interfaces/hud/hud.tscn" id="3_ccety"]
|
[ext_resource type="PackedScene" uid="uid://bcv81ku26xo" path="res://interfaces/hud/hud.tscn" id="3_ccety"]
|
||||||
[ext_resource type="PackedScene" uid="uid://c8co0qa2omjmh" path="res://weapons/space_gun/space_gun.tscn" id="4_lhn5w"]
|
[ext_resource type="PackedScene" uid="uid://c8co0qa2omjmh" path="res://entities/weapons/space_gun/space_gun.tscn" id="4_6jh57"]
|
||||||
[ext_resource type="PackedScene" uid="uid://dn1tcakam5egs" path="res://weapons/space_gun/projectile.tscn" id="5_lvaut"]
|
|
||||||
[ext_resource type="PackedScene" uid="uid://bof3mg7wgxrmn" path="res://components/health_component.tscn" id="5_t6i6e"]
|
[ext_resource type="PackedScene" uid="uid://bof3mg7wgxrmn" path="res://components/health_component.tscn" id="5_t6i6e"]
|
||||||
[ext_resource type="Script" path="res://entities/player/player_input.gd" id="6_ymcrr"]
|
[ext_resource type="Script" path="res://entities/player/player_input.gd" id="6_ymcrr"]
|
||||||
[ext_resource type="PackedScene" uid="uid://dsysi2rd3bu76" path="res://interfaces/hud/iff.tscn" id="7_8hc80"]
|
[ext_resource type="PackedScene" uid="uid://dsysi2rd3bu76" path="res://interfaces/hud/iffs/iff.tscn" id="7_8hc80"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://2t8ql8pkxv6c" path="res://components/flag_carry_component.tscn" id="7_e7s1a"]
|
||||||
|
[ext_resource type="Script" path="res://addons/smoothing/smoothing.gd" id="11_k330l"]
|
||||||
|
|
||||||
[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_clur0"]
|
[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_clur0"]
|
||||||
resource_local_to_scene = true
|
resource_local_to_scene = true
|
||||||
|
|
@ -26,50 +27,50 @@ length = 0.001
|
||||||
tracks/0/type = "value"
|
tracks/0/type = "value"
|
||||||
tracks/0/imported = false
|
tracks/0/imported = false
|
||||||
tracks/0/enabled = true
|
tracks/0/enabled = true
|
||||||
tracks/0/path = NodePath("SpringArm3D/Inventory/SpaceGun:position")
|
tracks/0/path = NodePath("Smoothing/SpringArm3D:position")
|
||||||
tracks/0/interp = 1
|
tracks/0/interp = 1
|
||||||
tracks/0/loop_wrap = true
|
tracks/0/loop_wrap = true
|
||||||
tracks/0/keys = {
|
tracks/0/keys = {
|
||||||
"times": PackedFloat32Array(0),
|
"times": PackedFloat32Array(0, 0.0001),
|
||||||
"transitions": PackedFloat32Array(1),
|
"transitions": PackedFloat32Array(1, 1),
|
||||||
"update": 0,
|
"update": 0,
|
||||||
"values": [Vector3(0.244668, -0.229311, -0.30332)]
|
"values": [Vector3(0, 0.5, 0), Vector3(0, 0.5, 0)]
|
||||||
}
|
}
|
||||||
tracks/1/type = "value"
|
tracks/1/type = "value"
|
||||||
tracks/1/imported = false
|
tracks/1/imported = false
|
||||||
tracks/1/enabled = true
|
tracks/1/enabled = true
|
||||||
tracks/1/path = NodePath("SpringArm3D/Inventory/SpaceGun:rotation")
|
tracks/1/path = NodePath("Smoothing/SpringArm3D:rotation")
|
||||||
tracks/1/interp = 1
|
tracks/1/interp = 1
|
||||||
tracks/1/loop_wrap = true
|
tracks/1/loop_wrap = true
|
||||||
tracks/1/keys = {
|
tracks/1/keys = {
|
||||||
"times": PackedFloat32Array(0),
|
"times": PackedFloat32Array(0),
|
||||||
"transitions": PackedFloat32Array(1),
|
"transitions": PackedFloat32Array(1),
|
||||||
"update": 0,
|
"update": 0,
|
||||||
"values": [Vector3(0, 3.14159, 0)]
|
"values": [Vector3(0, 0, 0)]
|
||||||
}
|
}
|
||||||
tracks/2/type = "value"
|
tracks/2/type = "value"
|
||||||
tracks/2/imported = false
|
tracks/2/imported = false
|
||||||
tracks/2/enabled = true
|
tracks/2/enabled = true
|
||||||
tracks/2/path = NodePath("SpringArm3D:position")
|
tracks/2/path = NodePath("Smoothing/SpringArm3D/Inventory/SpaceGun:position")
|
||||||
tracks/2/interp = 1
|
tracks/2/interp = 1
|
||||||
tracks/2/loop_wrap = true
|
tracks/2/loop_wrap = true
|
||||||
tracks/2/keys = {
|
tracks/2/keys = {
|
||||||
"times": PackedFloat32Array(0),
|
"times": PackedFloat32Array(0),
|
||||||
"transitions": PackedFloat32Array(1),
|
"transitions": PackedFloat32Array(1),
|
||||||
"update": 0,
|
"update": 0,
|
||||||
"values": [Vector3(0, 0.5, 0)]
|
"values": [Vector3(0.15, -0.3, -0.2)]
|
||||||
}
|
}
|
||||||
tracks/3/type = "value"
|
tracks/3/type = "value"
|
||||||
tracks/3/imported = false
|
tracks/3/imported = false
|
||||||
tracks/3/enabled = true
|
tracks/3/enabled = true
|
||||||
tracks/3/path = NodePath("SpringArm3D:rotation")
|
tracks/3/path = NodePath("Smoothing/SpringArm3D/Inventory/SpaceGun:rotation")
|
||||||
tracks/3/interp = 1
|
tracks/3/interp = 1
|
||||||
tracks/3/loop_wrap = true
|
tracks/3/loop_wrap = true
|
||||||
tracks/3/keys = {
|
tracks/3/keys = {
|
||||||
"times": PackedFloat32Array(0),
|
"times": PackedFloat32Array(0),
|
||||||
"transitions": PackedFloat32Array(1),
|
"transitions": PackedFloat32Array(1),
|
||||||
"update": 0,
|
"update": 0,
|
||||||
"values": [Vector3(0, 0, 0)]
|
"values": [Vector3(0, 3.14159, 0)]
|
||||||
}
|
}
|
||||||
|
|
||||||
[sub_resource type="Animation" id="Animation_yqgrk"]
|
[sub_resource type="Animation" id="Animation_yqgrk"]
|
||||||
|
|
@ -77,7 +78,7 @@ resource_name = "death"
|
||||||
tracks/0/type = "value"
|
tracks/0/type = "value"
|
||||||
tracks/0/imported = false
|
tracks/0/imported = false
|
||||||
tracks/0/enabled = true
|
tracks/0/enabled = true
|
||||||
tracks/0/path = NodePath("SpringArm3D:position")
|
tracks/0/path = NodePath("Smoothing/SpringArm3D:position")
|
||||||
tracks/0/interp = 1
|
tracks/0/interp = 1
|
||||||
tracks/0/loop_wrap = true
|
tracks/0/loop_wrap = true
|
||||||
tracks/0/keys = {
|
tracks/0/keys = {
|
||||||
|
|
@ -89,7 +90,7 @@ tracks/0/keys = {
|
||||||
tracks/1/type = "value"
|
tracks/1/type = "value"
|
||||||
tracks/1/imported = false
|
tracks/1/imported = false
|
||||||
tracks/1/enabled = true
|
tracks/1/enabled = true
|
||||||
tracks/1/path = NodePath("SpringArm3D:rotation")
|
tracks/1/path = NodePath("Smoothing/SpringArm3D:rotation")
|
||||||
tracks/1/interp = 1
|
tracks/1/interp = 1
|
||||||
tracks/1/loop_wrap = true
|
tracks/1/loop_wrap = true
|
||||||
tracks/1/keys = {
|
tracks/1/keys = {
|
||||||
|
|
@ -106,26 +107,26 @@ loop_mode = 1
|
||||||
tracks/0/type = "value"
|
tracks/0/type = "value"
|
||||||
tracks/0/imported = false
|
tracks/0/imported = false
|
||||||
tracks/0/enabled = true
|
tracks/0/enabled = true
|
||||||
tracks/0/path = NodePath("SpringArm3D/Inventory/SpaceGun:position")
|
tracks/0/path = NodePath("Smoothing/SpringArm3D/Inventory/SpaceGun:position")
|
||||||
tracks/0/interp = 1
|
tracks/0/interp = 1
|
||||||
tracks/0/loop_wrap = true
|
tracks/0/loop_wrap = true
|
||||||
tracks/0/keys = {
|
tracks/0/keys = {
|
||||||
"times": PackedFloat32Array(0, 1.5),
|
"times": PackedFloat32Array(0, 1.5),
|
||||||
"transitions": PackedFloat32Array(-2, -2),
|
"transitions": PackedFloat32Array(-2, -2),
|
||||||
"update": 0,
|
"update": 0,
|
||||||
"values": [Vector3(0.244668, -0.229311, -0.30332), Vector3(0.244668, -0.26057, -0.30332)]
|
"values": [Vector3(0.15, -0.3, -0.2), Vector3(0.15, -0.3, -0.2)]
|
||||||
}
|
}
|
||||||
tracks/1/type = "value"
|
tracks/1/type = "value"
|
||||||
tracks/1/imported = false
|
tracks/1/imported = false
|
||||||
tracks/1/enabled = true
|
tracks/1/enabled = true
|
||||||
tracks/1/path = NodePath("SpringArm3D/Inventory/SpaceGun:rotation")
|
tracks/1/path = NodePath("Smoothing/SpringArm3D/Inventory/SpaceGun:rotation")
|
||||||
tracks/1/interp = 1
|
tracks/1/interp = 1
|
||||||
tracks/1/loop_wrap = true
|
tracks/1/loop_wrap = true
|
||||||
tracks/1/keys = {
|
tracks/1/keys = {
|
||||||
"times": PackedFloat32Array(0, 1.5),
|
"times": PackedFloat32Array(0, 1.5),
|
||||||
"transitions": PackedFloat32Array(-2, -2),
|
"transitions": PackedFloat32Array(-2, -2),
|
||||||
"update": 0,
|
"update": 0,
|
||||||
"values": [Vector3(0, 3.14159, 0), Vector3(0.114371, 3.14159, -1.73453e-08)]
|
"values": [Vector3(0, 3.14159, 0), Vector3(0.0698132, 3.14159, 0)]
|
||||||
}
|
}
|
||||||
|
|
||||||
[sub_resource type="Animation" id="Animation_p84l0"]
|
[sub_resource type="Animation" id="Animation_p84l0"]
|
||||||
|
|
@ -133,19 +134,19 @@ resource_name = "shoot"
|
||||||
tracks/0/type = "value"
|
tracks/0/type = "value"
|
||||||
tracks/0/imported = false
|
tracks/0/imported = false
|
||||||
tracks/0/enabled = true
|
tracks/0/enabled = true
|
||||||
tracks/0/path = NodePath("SpringArm3D/Inventory/SpaceGun:position")
|
tracks/0/path = NodePath("Smoothing/SpringArm3D/Inventory/SpaceGun:position")
|
||||||
tracks/0/interp = 1
|
tracks/0/interp = 1
|
||||||
tracks/0/loop_wrap = true
|
tracks/0/loop_wrap = true
|
||||||
tracks/0/keys = {
|
tracks/0/keys = {
|
||||||
"times": PackedFloat32Array(0, 1),
|
"times": PackedFloat32Array(0, 1),
|
||||||
"transitions": PackedFloat32Array(0.5, 1),
|
"transitions": PackedFloat32Array(0.5, 1),
|
||||||
"update": 0,
|
"update": 0,
|
||||||
"values": [Vector3(0.244668, -0.204488, -0.268482), Vector3(0.244668, -0.229311, -0.30332)]
|
"values": [Vector3(0.15, -0.3, -0.2), Vector3(0.15, -0.3, -0.2)]
|
||||||
}
|
}
|
||||||
tracks/1/type = "value"
|
tracks/1/type = "value"
|
||||||
tracks/1/imported = false
|
tracks/1/imported = false
|
||||||
tracks/1/enabled = true
|
tracks/1/enabled = true
|
||||||
tracks/1/path = NodePath("SpringArm3D/Inventory/SpaceGun:rotation")
|
tracks/1/path = NodePath("Smoothing/SpringArm3D/Inventory/SpaceGun:rotation")
|
||||||
tracks/1/interp = 1
|
tracks/1/interp = 1
|
||||||
tracks/1/loop_wrap = true
|
tracks/1/loop_wrap = true
|
||||||
tracks/1/keys = {
|
tracks/1/keys = {
|
||||||
|
|
@ -179,6 +180,9 @@ properties/3/replication_mode = 2
|
||||||
properties/4/path = NodePath(".:player_state")
|
properties/4/path = NodePath(".:player_state")
|
||||||
properties/4/spawn = true
|
properties/4/spawn = true
|
||||||
properties/4/replication_mode = 2
|
properties/4/replication_mode = 2
|
||||||
|
properties/5/path = NodePath(".:nickname")
|
||||||
|
properties/5/spawn = true
|
||||||
|
properties/5/replication_mode = 2
|
||||||
|
|
||||||
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_5j4ew"]
|
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_5j4ew"]
|
||||||
properties/0/path = NodePath(".:direction")
|
properties/0/path = NodePath(".:direction")
|
||||||
|
|
@ -194,55 +198,57 @@ properties/3/path = NodePath(".:skiing")
|
||||||
properties/3/spawn = false
|
properties/3/spawn = false
|
||||||
properties/3/replication_mode = 2
|
properties/3/replication_mode = 2
|
||||||
|
|
||||||
[node name="Player" type="RigidBody3D"]
|
[node name="Player" type="RigidBody3D" node_paths=PackedStringArray("iff")]
|
||||||
|
collision_mask = 2147483649
|
||||||
axis_lock_angular_x = true
|
axis_lock_angular_x = true
|
||||||
axis_lock_angular_y = true
|
axis_lock_angular_y = true
|
||||||
axis_lock_angular_z = true
|
axis_lock_angular_z = true
|
||||||
mass = 75.0
|
mass = 75.0
|
||||||
physics_material_override = SubResource("PhysicsMaterial_clur0")
|
physics_material_override = SubResource("PhysicsMaterial_clur0")
|
||||||
|
can_sleep = false
|
||||||
continuous_cd = true
|
continuous_cd = true
|
||||||
script = ExtResource("1_mk68k")
|
script = ExtResource("1_mk68k")
|
||||||
|
iff = NodePath("Smoothing/ThirdPerson/IFF")
|
||||||
|
jump_height = 1.5
|
||||||
|
|
||||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
|
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
|
||||||
visible = false
|
visible = false
|
||||||
mesh = SubResource("CapsuleMesh_vmqfq")
|
mesh = SubResource("CapsuleMesh_vmqfq")
|
||||||
|
|
||||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||||
shape = ExtResource("2_8rtw3")
|
shape = ExtResource("2_vjqny")
|
||||||
|
|
||||||
[node name="ShapeCast3D" type="ShapeCast3D" parent="."]
|
[node name="ShapeCast3D" type="ShapeCast3D" parent="."]
|
||||||
transform = Transform3D(1.05, 0, 0, 0, 1.05, 0, 0, 0, 1.05, 0, 0, 0)
|
transform = Transform3D(1.05, 0, 0, 0, 1.05, 0, 0, 0, 1.05, 0, 0, 0)
|
||||||
shape = ExtResource("2_8rtw3")
|
shape = ExtResource("2_vjqny")
|
||||||
target_position = Vector3(0, 0, 0)
|
target_position = Vector3(0, 0, 0)
|
||||||
|
collision_mask = 2147483648
|
||||||
collide_with_areas = true
|
collide_with_areas = true
|
||||||
|
|
||||||
|
[node name="Sensor" type="Area3D" parent="."]
|
||||||
|
collision_layer = 0
|
||||||
|
collision_mask = 8
|
||||||
|
monitorable = false
|
||||||
|
|
||||||
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="Sensor"]
|
||||||
|
shape = ExtResource("2_vjqny")
|
||||||
|
|
||||||
[node name="HUD" parent="." instance=ExtResource("3_ccety")]
|
[node name="HUD" parent="." instance=ExtResource("3_ccety")]
|
||||||
|
|
||||||
[node name="SpringArm3D" type="SpringArm3D" parent="."]
|
|
||||||
unique_name_in_owner = true
|
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0)
|
|
||||||
spring_length = 0.0
|
|
||||||
|
|
||||||
[node name="Camera3D" type="Camera3D" parent="SpringArm3D"]
|
|
||||||
fov = 100.0
|
|
||||||
near = 0.1
|
|
||||||
|
|
||||||
[node name="Inventory" type="Node3D" parent="SpringArm3D"]
|
|
||||||
|
|
||||||
[node name="SpaceGun" parent="SpringArm3D/Inventory" instance=ExtResource("4_lhn5w")]
|
|
||||||
transform = Transform3D(-1, 0, 2.53518e-06, 0, 1, 0, -2.53518e-06, 0, -1, 0.244668, -0.229311, -0.30332)
|
|
||||||
PROJECTILE = ExtResource("5_lvaut")
|
|
||||||
|
|
||||||
[node name="SpineIKTarget" type="Node3D" parent="SpringArm3D"]
|
|
||||||
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0, 0)
|
|
||||||
|
|
||||||
[node name="HealthComponent" parent="." instance=ExtResource("5_t6i6e")]
|
[node name="HealthComponent" parent="." instance=ExtResource("5_t6i6e")]
|
||||||
|
|
||||||
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="HealthComponent"]
|
||||||
|
shape = ExtResource("2_vjqny")
|
||||||
|
|
||||||
|
[node name="FlagCarryComponent" parent="." node_paths=PackedStringArray("attachment", "sensor") instance=ExtResource("7_e7s1a")]
|
||||||
|
attachment = NodePath("../Smoothing/SpringArm3D/FlagCarryAttachment")
|
||||||
|
sensor = NodePath("../Sensor")
|
||||||
|
|
||||||
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
|
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
|
||||||
libraries = {
|
libraries = {
|
||||||
"": SubResource("AnimationLibrary_hg307")
|
"": SubResource("AnimationLibrary_hg307")
|
||||||
}
|
}
|
||||||
autoplay = "idle"
|
autoplay = "shoot"
|
||||||
playback_default_blend_time = 0.05
|
playback_default_blend_time = 0.05
|
||||||
|
|
||||||
[node name="ServerSynchronizer" type="MultiplayerSynchronizer" parent="."]
|
[node name="ServerSynchronizer" type="MultiplayerSynchronizer" parent="."]
|
||||||
|
|
@ -253,15 +259,41 @@ root_path = NodePath(".")
|
||||||
replication_config = SubResource("SceneReplicationConfig_5j4ew")
|
replication_config = SubResource("SceneReplicationConfig_5j4ew")
|
||||||
script = ExtResource("6_ymcrr")
|
script = ExtResource("6_ymcrr")
|
||||||
|
|
||||||
[node name="ThirdPerson" type="Node3D" parent="."]
|
[node name="Smoothing" type="Node3D" parent="."]
|
||||||
|
script = ExtResource("11_k330l")
|
||||||
|
target = NodePath("..")
|
||||||
|
flags = 3
|
||||||
|
|
||||||
[node name="PlayerMesh" parent="ThirdPerson" node_paths=PackedStringArray("spine_ik_target_attachment") instance=ExtResource("2_beyex")]
|
[node name="SpringArm3D" type="SpringArm3D" parent="Smoothing"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0)
|
||||||
|
spring_length = 0.0
|
||||||
|
|
||||||
|
[node name="Camera3D" type="Camera3D" parent="Smoothing/SpringArm3D"]
|
||||||
|
fov = 90.0
|
||||||
|
near = 0.1
|
||||||
|
|
||||||
|
[node name="Inventory" type="Node3D" parent="Smoothing/SpringArm3D"]
|
||||||
|
|
||||||
|
[node name="SpaceGun" parent="Smoothing/SpringArm3D/Inventory" node_paths=PackedStringArray("holder") instance=ExtResource("4_6jh57")]
|
||||||
|
transform = Transform3D(-1, 0, 2.53518e-06, 0, 1, 0, -2.53518e-06, 0, -1, 0.15, -0.3, -0.2)
|
||||||
|
holder = NodePath("../../../..")
|
||||||
|
|
||||||
|
[node name="SpineIKTarget" type="Node3D" parent="Smoothing/SpringArm3D"]
|
||||||
|
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0, 0)
|
||||||
|
|
||||||
|
[node name="FlagCarryAttachment" type="Node3D" parent="Smoothing/SpringArm3D"]
|
||||||
|
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, -0.620994, -0.287925)
|
||||||
|
|
||||||
|
[node name="ThirdPerson" type="Node3D" parent="Smoothing"]
|
||||||
|
|
||||||
|
[node name="PlayerMesh" parent="Smoothing/ThirdPerson" node_paths=PackedStringArray("spine_ik_target_attachment") instance=ExtResource("2_beyex")]
|
||||||
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0, 0)
|
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0, 0)
|
||||||
spine_ik_target_attachment = NodePath("../../SpringArm3D/SpineIKTarget")
|
spine_ik_target_attachment = NodePath("../../SpringArm3D/SpineIKTarget")
|
||||||
|
|
||||||
[node name="IFFAttachment" type="Node3D" parent="ThirdPerson"]
|
[node name="IFFAttachment" type="Marker3D" parent="Smoothing/ThirdPerson"]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.27457, 0)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.27457, 0)
|
||||||
|
|
||||||
[node name="IFF" parent="ThirdPerson" node_paths=PackedStringArray("attach_point", "player") instance=ExtResource("7_8hc80")]
|
[node name="IFF" parent="Smoothing/ThirdPerson" node_paths=PackedStringArray("player", "attach_point") instance=ExtResource("7_8hc80")]
|
||||||
|
player = NodePath("../../..")
|
||||||
attach_point = NodePath("../IFFAttachment")
|
attach_point = NodePath("../IFFAttachment")
|
||||||
player = NodePath("../..")
|
|
||||||
|
|
|
||||||
|
|
@ -1,71 +1,73 @@
|
||||||
# This file is part of open-fpsz.
|
# This file is part of open-fpsz.
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
# (at your option) any later version.
|
# (at your option) any later version.
|
||||||
#
|
#
|
||||||
# This program is distributed in the hope that it will be useful,
|
# This program is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
class_name PlayerInput extends MultiplayerSynchronizer
|
class_name PlayerInput extends MultiplayerSynchronizer
|
||||||
|
|
||||||
@export var jetting = false
|
@export var jetting : bool = false
|
||||||
@export var skiing = false
|
@export var skiing : bool = false
|
||||||
@export var direction = Vector2.ZERO
|
@export var direction : Vector2 = Vector2.ZERO
|
||||||
@export var camera_rotation : Vector2
|
@export var camera_rotation : Vector2
|
||||||
@export var MOUSE_SENSITIVITY : float = .6
|
@export var MOUSE_SENSITIVITY : float = .6
|
||||||
|
@export var inverted_y_axis : bool = false
|
||||||
|
|
||||||
signal jumped
|
signal jumped
|
||||||
signal fired_primary
|
signal fired_primary
|
||||||
|
signal throwed_flag
|
||||||
|
|
||||||
var _mouse_position: Vector2
|
func _ready() -> void:
|
||||||
|
var has_authority : bool = is_multiplayer_authority()
|
||||||
func _ready():
|
|
||||||
var has_authority = is_multiplayer_authority()
|
|
||||||
set_process(has_authority)
|
set_process(has_authority)
|
||||||
set_process_unhandled_input(has_authority)
|
set_process_unhandled_input(has_authority)
|
||||||
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
|
||||||
|
|
||||||
func _unhandled_input(event: InputEvent) -> void:
|
func _unhandled_input(event: InputEvent) -> void:
|
||||||
var mouse_mode = Input.get_mouse_mode()
|
var mouse_mode : Input.MouseMode = Input.get_mouse_mode()
|
||||||
|
|
||||||
# isolate mouse events
|
# isolate mouse events
|
||||||
if event is InputEventMouseMotion:
|
if event is InputEventMouseMotion:
|
||||||
if mouse_mode == Input.MOUSE_MODE_CAPTURED:
|
if mouse_mode == Input.MOUSE_MODE_CAPTURED:
|
||||||
# retrieve mouse position relative to last frame
|
# retrieve mouse position relative to last frame
|
||||||
_mouse_position = event.relative * MOUSE_SENSITIVITY
|
_update_camera(event.relative)
|
||||||
|
|
||||||
func _process(delta):
|
func _update_camera(relative_motion : Vector2) -> void:
|
||||||
|
# clamp vertical rotation (head motion)
|
||||||
|
if inverted_y_axis:
|
||||||
|
relative_motion.y *= -1.0
|
||||||
|
camera_rotation.y -= relative_motion.y * MOUSE_SENSITIVITY / 100
|
||||||
|
camera_rotation.y = clamp(camera_rotation.y, deg_to_rad(-90.0),deg_to_rad(90.0))
|
||||||
|
# wrap horizontal rotation (to prevent accumulation)
|
||||||
|
camera_rotation.x -= relative_motion.x * MOUSE_SENSITIVITY / 100
|
||||||
|
camera_rotation.x = wrapf(camera_rotation.x, deg_to_rad(0.0),deg_to_rad(360.0))
|
||||||
|
|
||||||
|
func _process(_delta : float) -> void:
|
||||||
direction = Input.get_vector("left", "right", "forward", "backward")
|
direction = Input.get_vector("left", "right", "forward", "backward")
|
||||||
if Input.is_action_just_pressed("jump_and_jet"):
|
if Input.is_action_just_pressed("jump_and_jet"):
|
||||||
_jump.rpc()
|
_jump.rpc()
|
||||||
if Input.is_action_just_pressed("fire_primary"):
|
if Input.is_action_just_pressed("fire_primary"):
|
||||||
_fire_primary.rpc()
|
_fire_primary.rpc()
|
||||||
|
if Input.is_action_just_pressed("throw_flag"):
|
||||||
|
_throw_flag.rpc()
|
||||||
jetting = Input.is_action_pressed("jump_and_jet")
|
jetting = Input.is_action_pressed("jump_and_jet")
|
||||||
skiing = Input.is_action_pressed("ski")
|
skiing = Input.is_action_pressed("ski")
|
||||||
|
|
||||||
func _physics_process(delta):
|
|
||||||
_update_camera(delta)
|
|
||||||
|
|
||||||
@rpc("call_local")
|
@rpc("call_local")
|
||||||
func _jump():
|
func _jump() -> void:
|
||||||
jumped.emit()
|
jumped.emit()
|
||||||
|
|
||||||
@rpc("call_local")
|
@rpc("call_local")
|
||||||
func _fire_primary():
|
func _fire_primary() -> void:
|
||||||
fired_primary.emit()
|
fired_primary.emit()
|
||||||
|
|
||||||
func _update_camera(delta):
|
@rpc("call_local")
|
||||||
# clamp vertical rotation (head motion)
|
func _throw_flag() -> void:
|
||||||
camera_rotation.y -= _mouse_position.y * delta
|
throwed_flag.emit()
|
||||||
camera_rotation.y = clamp(camera_rotation.y, deg_to_rad(-90.0),deg_to_rad(90.0))
|
|
||||||
# wrap horizontal rotation (to prevent accumulation)
|
|
||||||
camera_rotation.x -= _mouse_position.x * delta
|
|
||||||
camera_rotation.x = wrapf(camera_rotation.x, deg_to_rad(0.0),deg_to_rad(360.0))
|
|
||||||
# reset mouse motion until next input event
|
|
||||||
_mouse_position = Vector2.ZERO
|
|
||||||
|
|
|
||||||
0
entities/target_dummy/assets/models/.gdignore
Normal file
|
|
@ -1,50 +0,0 @@
|
||||||
[remap]
|
|
||||||
|
|
||||||
importer="scene"
|
|
||||||
importer_version=1
|
|
||||||
type="PackedScene"
|
|
||||||
uid="uid://b83leo1ca47d7"
|
|
||||||
path="res://.godot/imported/player_mesh.blend-b5697f48af9161c855a7a3326936546b.scn"
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://entities/target_dummy/assets/player_mesh.blend"
|
|
||||||
dest_files=["res://.godot/imported/player_mesh.blend-b5697f48af9161c855a7a3326936546b.scn"]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
nodes/root_type=""
|
|
||||||
nodes/root_name=""
|
|
||||||
nodes/apply_root_scale=true
|
|
||||||
nodes/root_scale=1.0
|
|
||||||
meshes/ensure_tangents=true
|
|
||||||
meshes/generate_lods=false
|
|
||||||
meshes/create_shadow_meshes=true
|
|
||||||
meshes/light_baking=1
|
|
||||||
meshes/lightmap_texel_size=0.2
|
|
||||||
meshes/force_disable_compression=false
|
|
||||||
skins/use_named_skins=true
|
|
||||||
animation/import=true
|
|
||||||
animation/fps=30
|
|
||||||
animation/trimming=false
|
|
||||||
animation/remove_immutable_tracks=true
|
|
||||||
import_script/path=""
|
|
||||||
_subresources={}
|
|
||||||
gltf/naming_version=1
|
|
||||||
gltf/embedded_image_handling=1
|
|
||||||
blender/nodes/visible=0
|
|
||||||
blender/nodes/punctual_lights=true
|
|
||||||
blender/nodes/cameras=true
|
|
||||||
blender/nodes/custom_properties=true
|
|
||||||
blender/nodes/modifiers=1
|
|
||||||
blender/meshes/colors=false
|
|
||||||
blender/meshes/uvs=true
|
|
||||||
blender/meshes/normals=true
|
|
||||||
blender/meshes/tangents=true
|
|
||||||
blender/meshes/skins=2
|
|
||||||
blender/meshes/export_bones_deforming_mesh_only=false
|
|
||||||
blender/materials/unpack_enabled=true
|
|
||||||
blender/materials/export_materials=1
|
|
||||||
blender/animation/limit_playback=true
|
|
||||||
blender/animation/always_sample=true
|
|
||||||
blender/animation/group_tracks=true
|
|
||||||
BIN
entities/target_dummy/assets/player_mesh.glb
Normal file
34
entities/target_dummy/assets/player_mesh.glb.import
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="scene"
|
||||||
|
importer_version=1
|
||||||
|
type="PackedScene"
|
||||||
|
uid="uid://chuein4frnvwt"
|
||||||
|
path="res://.godot/imported/player_mesh.glb-a0e04e00b0469c9659174448aceb10a7.scn"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://entities/target_dummy/assets/player_mesh.glb"
|
||||||
|
dest_files=["res://.godot/imported/player_mesh.glb-a0e04e00b0469c9659174448aceb10a7.scn"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
nodes/root_type=""
|
||||||
|
nodes/root_name=""
|
||||||
|
nodes/apply_root_scale=true
|
||||||
|
nodes/root_scale=1.0
|
||||||
|
meshes/ensure_tangents=true
|
||||||
|
meshes/generate_lods=true
|
||||||
|
meshes/create_shadow_meshes=true
|
||||||
|
meshes/light_baking=1
|
||||||
|
meshes/lightmap_texel_size=0.2
|
||||||
|
meshes/force_disable_compression=false
|
||||||
|
skins/use_named_skins=true
|
||||||
|
animation/import=true
|
||||||
|
animation/fps=30
|
||||||
|
animation/trimming=false
|
||||||
|
animation/remove_immutable_tracks=true
|
||||||
|
import_script/path=""
|
||||||
|
_subresources={}
|
||||||
|
gltf/naming_version=1
|
||||||
|
gltf/embedded_image_handling=1
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
# This file is part of open-fpsz.
|
# This file is part of open-fpsz.
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
# (at your option) any later version.
|
# (at your option) any later version.
|
||||||
#
|
#
|
||||||
# This program is distributed in the hope that it will be useful,
|
# This program is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
class_name DummyTarget extends RigidBody3D
|
class_name DummyTarget extends RigidBody3D
|
||||||
|
|
@ -24,8 +24,9 @@ var start_pos : Vector3
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
health_component.health_zeroed.connect(spawn)
|
health_component.health_zeroed.connect(spawn)
|
||||||
start_pos = global_position
|
start_pos = global_position
|
||||||
|
$TargetMesh/AnimationPlayer.play("gunTwoHanded")
|
||||||
|
|
||||||
func spawn():
|
func spawn(_killer_id : int) -> void:
|
||||||
hide()
|
hide()
|
||||||
collision_shape_3d.disabled = true
|
collision_shape_3d.disabled = true
|
||||||
await get_tree().create_timer(respawn_time).timeout
|
await get_tree().create_timer(respawn_time).timeout
|
||||||
|
|
|
||||||
|
|
@ -1,103 +1,25 @@
|
||||||
[gd_scene load_steps=5 format=3 uid="uid://dpnu1lvfncx6q"]
|
[gd_scene load_steps=5 format=3 uid="uid://dpnu1lvfncx6q"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://entities/target_dummy/target_dummy.gd" id="1_r02ch"]
|
[ext_resource type="Script" path="res://entities/target_dummy/target_dummy.gd" id="1_iup5v"]
|
||||||
[ext_resource type="PackedScene" uid="uid://b83leo1ca47d7" path="res://entities/target_dummy/assets/player_mesh.blend" id="2_x73k8"]
|
[ext_resource type="Shape3D" uid="uid://cb8esdlnottdn" path="res://entities/player/collision_shape.tres" id="2_i5k5j"]
|
||||||
[ext_resource type="PackedScene" uid="uid://bof3mg7wgxrmn" path="res://components/health_component.tscn" id="3_g1ap4"]
|
[ext_resource type="PackedScene" uid="uid://chuein4frnvwt" path="res://entities/target_dummy/assets/player_mesh.glb" id="4_fuync"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://bof3mg7wgxrmn" path="res://components/health_component.tscn" id="4_l1exy"]
|
||||||
|
|
||||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_rk1ox"]
|
[node name="DummyTarget" type="RigidBody3D"]
|
||||||
radius = 0.3
|
collision_layer = 2147483649
|
||||||
|
collision_mask = 2147483649
|
||||||
[node name="TargetDummy" type="RigidBody3D"]
|
|
||||||
axis_lock_angular_x = true
|
axis_lock_angular_x = true
|
||||||
axis_lock_angular_y = true
|
axis_lock_angular_y = true
|
||||||
axis_lock_angular_z = true
|
axis_lock_angular_z = true
|
||||||
mass = 75.0
|
mass = 75.0
|
||||||
continuous_cd = true
|
continuous_cd = true
|
||||||
script = ExtResource("1_r02ch")
|
script = ExtResource("1_iup5v")
|
||||||
|
|
||||||
[node name="PlayerMesh" parent="." instance=ExtResource("2_x73k8")]
|
|
||||||
transform = Transform3D(0.75, 0, 0, 0, 0.75, 0, 0, 0, 0.75, 0, -0.916438, 0)
|
|
||||||
|
|
||||||
[node name="Skeleton3D" parent="PlayerMesh/playerrig" index="0"]
|
|
||||||
bones/0/rotation = Quaternion(0.12582, -1.79059e-15, -1.33409e-23, 0.992053)
|
|
||||||
bones/0/scale = Vector3(1, 1, 1)
|
|
||||||
bones/1/rotation = Quaternion(-0.0644764, 1.78006e-15, -6.67523e-16, 0.997919)
|
|
||||||
bones/2/rotation = Quaternion(-0.0774641, 0, 0, 0.996995)
|
|
||||||
bones/4/rotation = Quaternion(0.201738, -3.62729e-15, 4.53412e-16, 0.97944)
|
|
||||||
bones/6/rotation = Quaternion(-0.605155, -0.345862, -0.356135, 0.622363)
|
|
||||||
bones/7/rotation = Quaternion(-0.0464025, 0.68865, -0.38959, 0.609777)
|
|
||||||
bones/7/scale = Vector3(1, 1, 1)
|
|
||||||
bones/8/rotation = Quaternion(0.185291, 0.0266179, 0.00595018, 0.982305)
|
|
||||||
bones/8/scale = Vector3(1, 1, 1)
|
|
||||||
bones/9/rotation = Quaternion(0.126866, -0.0346058, -0.00662176, 0.991294)
|
|
||||||
bones/9/scale = Vector3(1, 1, 1)
|
|
||||||
bones/10/rotation = Quaternion(0.0557877, -0.312038, -0.196665, 0.927816)
|
|
||||||
bones/11/rotation = Quaternion(-0.0630718, -0.16283, 0.0971492, 0.979832)
|
|
||||||
bones/13/rotation = Quaternion(0.0299552, -0.545663, -0.00259936, 0.837465)
|
|
||||||
bones/13/scale = Vector3(1, 1, 1)
|
|
||||||
bones/14/rotation = Quaternion(-0.0636278, -0.0624373, 0.0299354, 0.995569)
|
|
||||||
bones/15/rotation = Quaternion(0.01399, 0.0251671, 0.0278526, 0.999197)
|
|
||||||
bones/16/rotation = Quaternion(-0.1, -0.561252, 0.0324573, 0.82094)
|
|
||||||
bones/17/rotation = Quaternion(0.0486079, -0.0407852, 0.014286, 0.997883)
|
|
||||||
bones/19/rotation = Quaternion(-0.12453, -0.526036, 0.129609, 0.831252)
|
|
||||||
bones/20/rotation = Quaternion(-0.0225172, -0.0668488, 0.0231689, 0.99724)
|
|
||||||
bones/20/scale = Vector3(1, 1, 1)
|
|
||||||
bones/21/rotation = Quaternion(-0.00114936, 0.0252308, -0.0174874, 0.999528)
|
|
||||||
bones/21/scale = Vector3(1, 1, 1)
|
|
||||||
bones/22/rotation = Quaternion(-0.192536, -0.535774, 0.0761884, 0.818579)
|
|
||||||
bones/23/rotation = Quaternion(0.0104723, -0.0704384, 0.0293146, 0.99703)
|
|
||||||
bones/23/scale = Vector3(1, 1, 1)
|
|
||||||
bones/24/rotation = Quaternion(0.0334518, 0.0259883, -0.0178538, 0.998943)
|
|
||||||
bones/25/rotation = Quaternion(-0.605155, 0.345863, 0.356135, 0.622363)
|
|
||||||
bones/25/scale = Vector3(1, 1, 1)
|
|
||||||
bones/26/rotation = Quaternion(-0.0464025, -0.68865, 0.38959, 0.609777)
|
|
||||||
bones/26/scale = Vector3(1, 1, 1)
|
|
||||||
bones/27/rotation = Quaternion(0.185291, -0.0266179, -0.00595018, 0.982305)
|
|
||||||
bones/27/scale = Vector3(1, 1, 1)
|
|
||||||
bones/28/rotation = Quaternion(-0.144176, 0.0367847, -0.00247504, 0.988865)
|
|
||||||
bones/28/scale = Vector3(1, 1, 1)
|
|
||||||
bones/30/rotation = Quaternion(-0.0630717, 0.16283, -0.0971492, 0.979832)
|
|
||||||
bones/30/scale = Vector3(1, 1, 1)
|
|
||||||
bones/31/rotation = Quaternion(0.0237032, 0.0123211, -0.0433656, 0.998702)
|
|
||||||
bones/31/scale = Vector3(1, 1, 1)
|
|
||||||
bones/32/rotation = Quaternion(0.243143, 0.523041, 0.164477, 0.800161)
|
|
||||||
bones/32/scale = Vector3(1, 1, 1)
|
|
||||||
bones/33/rotation = Quaternion(-0.0636278, 0.0624373, -0.0299354, 0.995569)
|
|
||||||
bones/34/rotation = Quaternion(0.0139901, -0.0251671, -0.0278526, 0.999197)
|
|
||||||
bones/35/rotation = Quaternion(0.113348, 0.545076, 0.134205, 0.819776)
|
|
||||||
bones/36/rotation = Quaternion(0.0486079, 0.0407853, -0.0142859, 0.997883)
|
|
||||||
bones/38/rotation = Quaternion(0.0934222, 0.536709, 0.031309, 0.837995)
|
|
||||||
bones/39/rotation = Quaternion(-0.0225172, 0.0668488, -0.023169, 0.99724)
|
|
||||||
bones/40/rotation = Quaternion(-0.00114935, -0.0252307, 0.0174875, 0.999528)
|
|
||||||
bones/40/scale = Vector3(1, 1, 1)
|
|
||||||
bones/41/rotation = Quaternion(0.0241847, 0.530538, 0.0849425, 0.843048)
|
|
||||||
bones/41/scale = Vector3(1, 1, 1)
|
|
||||||
bones/42/rotation = Quaternion(0.0104724, 0.0704385, -0.0293146, 0.99703)
|
|
||||||
bones/43/rotation = Quaternion(0.0334518, -0.0259883, 0.0178538, 0.998943)
|
|
||||||
bones/44/rotation = Quaternion(0.986515, -3.3762e-16, 5.03093e-24, 0.163672)
|
|
||||||
bones/44/scale = Vector3(1, 1, 0.999997)
|
|
||||||
bones/45/rotation = Quaternion(0.143207, -4.28623e-07, 5.19845e-06, 0.989693)
|
|
||||||
bones/45/scale = Vector3(1, 1, 1)
|
|
||||||
bones/46/rotation = Quaternion(-0.574131, 2.92207e-06, -4.58343e-06, 0.818763)
|
|
||||||
bones/47/rotation = Quaternion(1.99048e-05, 0.961249, -0.27568, 4.3124e-06)
|
|
||||||
bones/47/scale = Vector3(1, 1, 1)
|
|
||||||
bones/48/rotation = Quaternion(0.679706, 0.679706, -0.194936, 0.194936)
|
|
||||||
bones/49/rotation = Quaternion(0.986515, -3.3762e-16, 5.03093e-24, 0.163672)
|
|
||||||
bones/49/scale = Vector3(1, 1, 0.999997)
|
|
||||||
bones/50/rotation = Quaternion(0.143207, 4.28623e-07, -5.19845e-06, 0.989693)
|
|
||||||
bones/50/scale = Vector3(1, 1, 1)
|
|
||||||
bones/51/rotation = Quaternion(-0.574131, -2.92207e-06, 4.58343e-06, 0.818763)
|
|
||||||
bones/52/rotation = Quaternion(-1.99048e-05, 0.961249, -0.27568, -4.3124e-06)
|
|
||||||
bones/52/scale = Vector3(1, 1, 1)
|
|
||||||
bones/53/rotation = Quaternion(0.679706, -0.679706, 0.194936, 0.194936)
|
|
||||||
|
|
||||||
[node name="AnimationPlayer" parent="PlayerMesh" index="4"]
|
|
||||||
autoplay = "gunOneHanded"
|
|
||||||
|
|
||||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||||
shape = SubResource("CapsuleShape3D_rk1ox")
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
|
||||||
|
shape = ExtResource("2_i5k5j")
|
||||||
|
|
||||||
[node name="HealthComponent" parent="." instance=ExtResource("3_g1ap4")]
|
[node name="HealthComponent" parent="." instance=ExtResource("4_l1exy")]
|
||||||
max_health = 300
|
|
||||||
|
|
||||||
[editable path="PlayerMesh"]
|
[node name="TargetMesh" parent="." instance=ExtResource("4_fuync")]
|
||||||
|
transform = Transform3D(0.75, 0, 0, 0, 0.75, 0, 0, 0, 0.75, 0, 0, 0)
|
||||||
|
|
|
||||||
BIN
entities/weapons/space_gun/assets/disclauncher.glb
Normal file
34
entities/weapons/space_gun/assets/disclauncher.glb.import
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="scene"
|
||||||
|
importer_version=1
|
||||||
|
type="PackedScene"
|
||||||
|
uid="uid://bjcn37ops3bro"
|
||||||
|
path="res://.godot/imported/disclauncher.glb-e58edebbe444fad4554f8c76e8b18f06.scn"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://entities/weapons/space_gun/assets/disclauncher.glb"
|
||||||
|
dest_files=["res://.godot/imported/disclauncher.glb-e58edebbe444fad4554f8c76e8b18f06.scn"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
nodes/root_type=""
|
||||||
|
nodes/root_name=""
|
||||||
|
nodes/apply_root_scale=true
|
||||||
|
nodes/root_scale=1.0
|
||||||
|
meshes/ensure_tangents=true
|
||||||
|
meshes/generate_lods=true
|
||||||
|
meshes/create_shadow_meshes=true
|
||||||
|
meshes/light_baking=1
|
||||||
|
meshes/lightmap_texel_size=0.2
|
||||||
|
meshes/force_disable_compression=false
|
||||||
|
skins/use_named_skins=true
|
||||||
|
animation/import=true
|
||||||
|
animation/fps=30
|
||||||
|
animation/trimming=false
|
||||||
|
animation/remove_immutable_tracks=true
|
||||||
|
import_script/path=""
|
||||||
|
_subresources={}
|
||||||
|
gltf/naming_version=1
|
||||||
|
gltf/embedded_image_handling=1
|
||||||
0
entities/weapons/space_gun/assets/models/.gdignore
Normal file
BIN
entities/weapons/space_gun/assets/models/disclauncher.blend
Normal file
|
|
@ -1,15 +1,15 @@
|
||||||
# This file is part of open-fpsz.
|
# This file is part of open-fpsz.
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
# (at your option) any later version.
|
# (at your option) any later version.
|
||||||
#
|
#
|
||||||
# This program is distributed in the hope that it will be useful,
|
# This program is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
class_name Projectile extends Node3D
|
class_name Projectile extends Node3D
|
||||||
|
|
@ -19,32 +19,34 @@ class_name Projectile extends Node3D
|
||||||
@export var speed : float = 78.4 # m/s
|
@export var speed : float = 78.4 # m/s
|
||||||
@export var lifespan : float = 5.0 # in seconds
|
@export var lifespan : float = 5.0 # in seconds
|
||||||
|
|
||||||
@onready var shape_cast = $ShapeCast3D
|
@onready var shape_cast : ShapeCast3D = $ShapeCast3D
|
||||||
@onready var game = get_tree().get_current_scene()
|
@onready var game : Node3D = get_tree().get_current_scene()
|
||||||
|
|
||||||
var velocity : Vector3 = Vector3.ZERO
|
var velocity : Vector3 = Vector3.ZERO
|
||||||
|
var shooter : Player
|
||||||
|
|
||||||
func _ready():
|
func _ready() -> void:
|
||||||
var lifespan_timer = Timer.new()
|
var lifespan_timer : Timer = Timer.new()
|
||||||
lifespan_timer.wait_time = lifespan
|
lifespan_timer.wait_time = lifespan
|
||||||
lifespan_timer.one_shot = true
|
lifespan_timer.one_shot = true
|
||||||
lifespan_timer.autostart = true
|
lifespan_timer.autostart = true
|
||||||
lifespan_timer.timeout.connect(self_destruct)
|
lifespan_timer.timeout.connect(self_destruct)
|
||||||
add_child(lifespan_timer)
|
add_child(lifespan_timer)
|
||||||
|
|
||||||
func self_destruct():
|
func self_destruct() -> void:
|
||||||
explode(position)
|
explode(position)
|
||||||
|
|
||||||
func explode(spawn_location):
|
func explode(spawn_location : Vector3) -> void:
|
||||||
var spawned_explosion = EXPLOSION.instantiate()
|
var spawned_explosion : Node = EXPLOSION.instantiate()
|
||||||
spawned_explosion.position = spawn_location
|
spawned_explosion.position = spawn_location
|
||||||
|
spawned_explosion.shooter = shooter
|
||||||
game.add_child(spawned_explosion)
|
game.add_child(spawned_explosion)
|
||||||
queue_free()
|
queue_free()
|
||||||
|
|
||||||
func _physics_process(delta):
|
func _physics_process(delta : float) -> void:
|
||||||
var previous_position = global_position
|
var previous_position : Vector3 = global_position
|
||||||
global_position += velocity * delta
|
global_position += velocity * delta
|
||||||
shape_cast.target_position = to_local(previous_position)
|
shape_cast.target_position = to_local(previous_position)
|
||||||
if shape_cast.is_colliding():
|
if shape_cast.is_colliding():
|
||||||
var contact_point = shape_cast.collision_result[0].point
|
var contact_point : Vector3 = shape_cast.collision_result[0].point
|
||||||
explode(contact_point)
|
explode(contact_point)
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
[gd_scene load_steps=7 format=3 uid="uid://dn1tcakam5egs"]
|
[gd_scene load_steps=7 format=3 uid="uid://dn1tcakam5egs"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://weapons/space_gun/projectile.gd" id="1_4j1dp"]
|
[ext_resource type="Script" path="res://entities/weapons/space_gun/projectile.gd" id="1_4j1dp"]
|
||||||
[ext_resource type="PackedScene" uid="uid://8atq41j7wd55" path="res://weapons/space_gun/projectile_explosion.tscn" id="2_llml6"]
|
[ext_resource type="PackedScene" uid="uid://8atq41j7wd55" path="res://entities/weapons/space_gun/projectile_explosion.tscn" id="2_llml6"]
|
||||||
[ext_resource type="Script" path="res://weapons/space_gun/projectile_trail.gd" id="3_ygqbh"]
|
[ext_resource type="Script" path="res://entities/weapons/space_gun/projectile_trail.gd" id="3_ygqbh"]
|
||||||
|
|
||||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_4a265"]
|
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_4a265"]
|
||||||
transparency = 1
|
transparency = 1
|
||||||
|
|
@ -45,4 +45,5 @@ shape = SubResource("SphereShape3D_umtte")
|
||||||
target_position = Vector3(0, 0, 0)
|
target_position = Vector3(0, 0, 0)
|
||||||
margin = 0.1
|
margin = 0.1
|
||||||
max_results = 1
|
max_results = 1
|
||||||
|
collision_mask = 2147483649
|
||||||
debug_shape_custom_color = Color(1, 0, 0, 1)
|
debug_shape_custom_color = Color(1, 0, 0, 1)
|
||||||
|
|
@ -1,23 +1,26 @@
|
||||||
# This file is part of open-fpsz.
|
# This file is part of open-fpsz.
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
# (at your option) any later version.
|
# (at your option) any later version.
|
||||||
#
|
#
|
||||||
# This program is distributed in the hope that it will be useful,
|
# This program is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
extends Node3D
|
extends Node3D
|
||||||
|
|
||||||
@onready var fire = $Fire
|
var shooter : Player
|
||||||
|
|
||||||
|
@onready var fire : GPUParticles3D = $Fire
|
||||||
@onready var explosive_damage : ExplosiveDamageComponent = $ExplosiveDamageComponent
|
@onready var explosive_damage : ExplosiveDamageComponent = $ExplosiveDamageComponent
|
||||||
var explosion_effect_pending : bool = false
|
var explosion_effect_pending : bool = false
|
||||||
|
|
||||||
func _ready():
|
func _ready() -> void:
|
||||||
|
explosive_damage.damage_dealer = shooter
|
||||||
fire.emitting = true
|
fire.emitting = true
|
||||||
fire.finished.connect(func(): queue_free())
|
fire.finished.connect(func() -> void: queue_free())
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[gd_scene load_steps=9 format=3 uid="uid://8atq41j7wd55"]
|
[gd_scene load_steps=9 format=3 uid="uid://8atq41j7wd55"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://weapons/space_gun/projectile_explosion.gd" id="1_fp5td"]
|
[ext_resource type="Script" path="res://entities/weapons/space_gun/projectile_explosion.gd" id="1_fp5td"]
|
||||||
[ext_resource type="PackedScene" uid="uid://ds1hekx1dq1bg" path="res://components/explosive_damage_component.tscn" id="2_d4sf4"]
|
[ext_resource type="PackedScene" uid="uid://ds1hekx1dq1bg" path="res://components/explosive_damage_component.tscn" id="2_d4sf4"]
|
||||||
|
|
||||||
[sub_resource type="Curve" id="Curve_rg204"]
|
[sub_resource type="Curve" id="Curve_rg204"]
|
||||||
|
|
@ -1,22 +1,22 @@
|
||||||
# This file is part of open-fpsz.
|
# This file is part of open-fpsz.
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
# (at your option) any later version.
|
# (at your option) any later version.
|
||||||
#
|
#
|
||||||
# This program is distributed in the hope that it will be useful,
|
# This program is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
class_name Trail3D extends MeshInstance3D
|
class_name Trail3D extends MeshInstance3D
|
||||||
|
|
||||||
var _points = [] # 3D points of trail
|
var _points : Array = [] # 3D points of trail
|
||||||
var _widths = [] # Calculated widths of trail
|
var _widths : Array = [] # Calculated widths of trail
|
||||||
var _lifespans = [] # Trail point lifespans
|
var _lifespans : Array = [] # Trail point lifespans
|
||||||
|
|
||||||
@export var _trail_enabled : bool = true # Is trail shown?
|
@export var _trail_enabled : bool = true # Is trail shown?
|
||||||
|
|
||||||
|
|
@ -33,7 +33,7 @@ var _lifespans = [] # Trail point lifespans
|
||||||
|
|
||||||
var _old_pos : Vector3 # Previous pos
|
var _old_pos : Vector3 # Previous pos
|
||||||
|
|
||||||
func _append_point():
|
func _append_point() -> void:
|
||||||
_points.append(get_global_transform().origin)
|
_points.append(get_global_transform().origin)
|
||||||
_widths.append([
|
_widths.append([
|
||||||
get_global_transform().basis.x * _from_width,
|
get_global_transform().basis.x * _from_width,
|
||||||
|
|
@ -41,52 +41,52 @@ func _append_point():
|
||||||
])
|
])
|
||||||
_lifespans.append(0.0)
|
_lifespans.append(0.0)
|
||||||
|
|
||||||
func _remove_point(i):
|
func _remove_point(i : int) -> void:
|
||||||
_points.remove_at(i)
|
_points.remove_at(i)
|
||||||
_widths.remove_at(i)
|
_widths.remove_at(i)
|
||||||
_lifespans.remove_at(i)
|
_lifespans.remove_at(i)
|
||||||
|
|
||||||
func _ready():
|
func _ready() -> void:
|
||||||
_old_pos = get_global_transform().origin
|
_old_pos = get_global_transform().origin
|
||||||
mesh = ImmediateMesh.new()
|
mesh = ImmediateMesh.new()
|
||||||
|
|
||||||
func _process(delta):
|
func _process(delta : float) -> void:
|
||||||
if(_old_pos - get_global_transform().origin).length() > _motion_delta and _trail_enabled:
|
if(_old_pos - get_global_transform().origin).length() > _motion_delta and _trail_enabled:
|
||||||
_append_point() # Create new point
|
_append_point() # Create new point
|
||||||
_old_pos = get_global_transform().origin # Update previous position to current position coordinates
|
_old_pos = get_global_transform().origin # Update previous position to current position coordinates
|
||||||
|
|
||||||
# Update the lifespan
|
# Update the lifespan
|
||||||
var p = 0
|
var p : int = 0
|
||||||
var max_points = _points.size()
|
var max_points : int = _points.size()
|
||||||
while p < max_points:
|
while p < max_points:
|
||||||
_lifespans[p] += delta
|
_lifespans[p] += delta
|
||||||
if _lifespans[p] > _lifespan:
|
if _lifespans[p] > _lifespan:
|
||||||
_remove_point(p)
|
_remove_point(p)
|
||||||
p -= 1
|
p -= 1
|
||||||
if (p < 0): p = 0
|
if (p < 0): p = 0
|
||||||
|
|
||||||
max_points = _points.size()
|
max_points = _points.size()
|
||||||
p += 1
|
p += 1
|
||||||
|
|
||||||
mesh.clear_surfaces()
|
mesh.clear_surfaces()
|
||||||
|
|
||||||
# If less than 2 points, stop rendering trail
|
# If less than 2 points, stop rendering trail
|
||||||
if _points.size() < 2:
|
if _points.size() < 2:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Render new mesh for each point
|
# Render new mesh for each point
|
||||||
mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLE_STRIP)
|
mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLE_STRIP)
|
||||||
|
|
||||||
for i in range(_points.size()):
|
for i in range(_points.size()):
|
||||||
var t = float(i) / (_points.size() - 1.0)
|
var t : float = float(i) / (_points.size() - 1.0)
|
||||||
var curr_color = _start_color.lerp(_end_color, 1 - t)
|
var curr_color : Color = _start_color.lerp(_end_color, 1 - t)
|
||||||
mesh.surface_set_color(curr_color)
|
mesh.surface_set_color(curr_color)
|
||||||
|
|
||||||
var curr_width = _widths[i][0] - pow(1 - t, _scale_acceleration) * _widths[i][1]
|
var curr_width : Vector3 = _widths[i][0] - pow(1 - t, _scale_acceleration) * _widths[i][1]
|
||||||
|
|
||||||
var t0 = i / _points.size()
|
var t0 : float = i / _points.size()
|
||||||
var t1 = t
|
var t1 : float = t
|
||||||
|
|
||||||
mesh.surface_set_uv(Vector2(t0, 0))
|
mesh.surface_set_uv(Vector2(t0, 0))
|
||||||
mesh.surface_add_vertex(to_local(_points[i] + curr_width))
|
mesh.surface_add_vertex(to_local(_points[i] + curr_width))
|
||||||
mesh.surface_set_uv(Vector2(t1, 1))
|
mesh.surface_set_uv(Vector2(t1, 1))
|
||||||
|
|
@ -1,24 +1,25 @@
|
||||||
# This file is part of open-fpsz.
|
# This file is part of open-fpsz.
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
# (at your option) any later version.
|
# (at your option) any later version.
|
||||||
#
|
#
|
||||||
# This program is distributed in the hope that it will be useful,
|
# This program is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
extends Node3D
|
extends Node3D
|
||||||
class_name SpaceGun
|
class_name SpaceGun
|
||||||
|
|
||||||
@export var PROJECTILE : PackedScene
|
@export var PROJECTILE : PackedScene
|
||||||
|
@export var holder : Player
|
||||||
|
|
||||||
@onready var nozzle = $Nozzle
|
@onready var nozzle : Node3D = $Nozzle
|
||||||
@onready var inventory = get_parent()
|
@onready var inventory : Node3D = get_parent()
|
||||||
|
|
||||||
enum WeaponState { WEAPON_READY, WEAPON_RELOADING }
|
enum WeaponState { WEAPON_READY, WEAPON_RELOADING }
|
||||||
|
|
||||||
|
|
@ -27,20 +28,21 @@ var weapon_state : WeaponState = WeaponState.WEAPON_READY
|
||||||
const inheritance : float = .5 # ratio
|
const inheritance : float = .5 # ratio
|
||||||
const reload_time : float = 1. # seconds
|
const reload_time : float = 1. # seconds
|
||||||
|
|
||||||
func can_fire():
|
func can_fire() -> bool:
|
||||||
return weapon_state == WeaponState.WEAPON_READY
|
return weapon_state == WeaponState.WEAPON_READY
|
||||||
|
|
||||||
func fire_primary():
|
func fire_primary() -> void:
|
||||||
if not can_fire():
|
if not can_fire():
|
||||||
return
|
return
|
||||||
|
|
||||||
var projectile = PROJECTILE.instantiate()
|
var projectile : Node = PROJECTILE.instantiate()
|
||||||
projectile.transform = nozzle.global_transform
|
projectile.transform = nozzle.global_transform
|
||||||
projectile.velocity = nozzle.global_basis.z.normalized() * projectile.speed
|
projectile.velocity = nozzle.global_basis.z.normalized() * projectile.speed
|
||||||
var inheritance_factor = clamp(inheritance, 0., 1.)
|
projectile.shooter = holder
|
||||||
|
var inheritance_factor : float = clamp(inheritance, 0., 1.)
|
||||||
projectile.velocity += (inventory.owner.linear_velocity * inheritance_factor)
|
projectile.velocity += (inventory.owner.linear_velocity * inheritance_factor)
|
||||||
inventory.owner.add_sibling(projectile)
|
inventory.owner.add_sibling(projectile)
|
||||||
var collider = projectile.shape_cast
|
var collider : ShapeCast3D = projectile.shape_cast
|
||||||
collider.add_exception(inventory.owner)
|
collider.add_exception(inventory.owner)
|
||||||
weapon_state = WeaponState.WEAPON_RELOADING
|
weapon_state = WeaponState.WEAPON_RELOADING
|
||||||
await get_tree().create_timer(reload_time).timeout
|
await get_tree().create_timer(reload_time).timeout
|
||||||
14
entities/weapons/space_gun/space_gun.tscn
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
[gd_scene load_steps=4 format=3 uid="uid://c8co0qa2omjmh"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://entities/weapons/space_gun/space_gun.gd" id="1_6sm4s"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://dn1tcakam5egs" path="res://entities/weapons/space_gun/projectile.tscn" id="2_wvneg"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://bjcn37ops3bro" path="res://entities/weapons/space_gun/assets/disclauncher.glb" id="3_5k2xm"]
|
||||||
|
|
||||||
|
[node name="SpaceGun" type="Node3D"]
|
||||||
|
script = ExtResource("1_6sm4s")
|
||||||
|
PROJECTILE = ExtResource("2_wvneg")
|
||||||
|
|
||||||
|
[node name="disclauncher" parent="." instance=ExtResource("3_5k2xm")]
|
||||||
|
|
||||||
|
[node name="Nozzle" type="Node3D" parent="."]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.111355, 0.540839)
|
||||||
41
environments/default.tres
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
[gd_resource type="Environment" load_steps=4 format=3 uid="uid://d2ahijqqspw5f"]
|
||||||
|
|
||||||
|
[ext_resource type="Texture2D" uid="uid://btdbu0qbe1646" path="res://environments/skyboxes/kloppenheim_06_puresky_2k.exr" id="1_k44rf"]
|
||||||
|
|
||||||
|
[sub_resource type="PanoramaSkyMaterial" id="PanoramaSkyMaterial_7tawh"]
|
||||||
|
panorama = ExtResource("1_k44rf")
|
||||||
|
|
||||||
|
[sub_resource type="Sky" id="Sky_iloxd"]
|
||||||
|
sky_material = SubResource("PanoramaSkyMaterial_7tawh")
|
||||||
|
process_mode = 1
|
||||||
|
radiance_size = 4
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
background_mode = 2
|
||||||
|
background_energy_multiplier = 0.2
|
||||||
|
sky = SubResource("Sky_iloxd")
|
||||||
|
ambient_light_source = 3
|
||||||
|
tonemap_mode = 3
|
||||||
|
tonemap_exposure = 0.6
|
||||||
|
tonemap_white = 0.6
|
||||||
|
ssr_enabled = true
|
||||||
|
ssao_intensity = 5.0
|
||||||
|
ssil_enabled = true
|
||||||
|
ssil_intensity = 5.0
|
||||||
|
ssil_sharpness = 0.7
|
||||||
|
sdfgi_cascades = 6
|
||||||
|
sdfgi_max_distance = 819.2
|
||||||
|
sdfgi_y_scale = 0
|
||||||
|
glow_normalized = true
|
||||||
|
glow_intensity = 2.0
|
||||||
|
glow_strength = 0.96
|
||||||
|
fog_enabled = true
|
||||||
|
fog_light_color = Color(1, 1, 1, 1)
|
||||||
|
fog_light_energy = 0.15
|
||||||
|
fog_density = 0.0025
|
||||||
|
fog_sky_affect = 0.3
|
||||||
|
volumetric_fog_density = 0.003
|
||||||
|
volumetric_fog_albedo = Color(1, 0.380392, 0.380392, 1)
|
||||||
|
volumetric_fog_emission_energy = 192.23
|
||||||
|
volumetric_fog_length = 551.32
|
||||||
|
volumetric_fog_ambient_inject = 0.37
|
||||||
20
environments/desert.tres
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
[gd_resource type="Environment" load_steps=3 format=3 uid="uid://nw62ce5cglvs"]
|
||||||
|
|
||||||
|
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_8mbvu"]
|
||||||
|
sky_top_color = Color(0, 0.584314, 0.670588, 1)
|
||||||
|
sky_horizon_color = Color(0.819608, 0.592157, 0.556863, 1)
|
||||||
|
sky_curve = 0.235375
|
||||||
|
ground_bottom_color = Color(0.819608, 0.592157, 0.556863, 1)
|
||||||
|
ground_horizon_color = Color(0.819608, 0.592157, 0.556863, 1)
|
||||||
|
ground_curve = 0.02
|
||||||
|
|
||||||
|
[sub_resource type="Sky" id="Sky_mobku"]
|
||||||
|
sky_material = SubResource("ProceduralSkyMaterial_8mbvu")
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
background_mode = 2
|
||||||
|
sky = SubResource("Sky_mobku")
|
||||||
|
tonemap_mode = 3
|
||||||
|
tonemap_exposure = 0.85
|
||||||
|
volumetric_fog_density = 0.005
|
||||||
|
adjustment_brightness = 0.85
|
||||||
BIN
environments/skyboxes/kloppenheim_06_puresky_2k.exr
Normal file
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
importer="texture"
|
importer="texture"
|
||||||
type="CompressedTexture2D"
|
type="CompressedTexture2D"
|
||||||
uid="uid://cvtqt0k2ewd07"
|
uid="uid://btdbu0qbe1646"
|
||||||
path.s3tc="res://.godot/imported/albedo.png-7f543d432ab75668956abd5bcc51a13b.s3tc.ctex"
|
path.bptc="res://.godot/imported/kloppenheim_06_puresky_2k.exr-ec828ffc9b05b2c03fb35e84cd230d2d.bptc.ctex"
|
||||||
metadata={
|
metadata={
|
||||||
"imported_formats": ["s3tc_bptc"],
|
"imported_formats": ["s3tc_bptc"],
|
||||||
"vram_texture": true
|
"vram_texture": true
|
||||||
|
|
@ -11,18 +11,18 @@ metadata={
|
||||||
|
|
||||||
[deps]
|
[deps]
|
||||||
|
|
||||||
source_file="res://weapons/space_gun/assets/albedo.png"
|
source_file="res://environments/skyboxes/kloppenheim_06_puresky_2k.exr"
|
||||||
dest_files=["res://.godot/imported/albedo.png-7f543d432ab75668956abd5bcc51a13b.s3tc.ctex"]
|
dest_files=["res://.godot/imported/kloppenheim_06_puresky_2k.exr-ec828ffc9b05b2c03fb35e84cd230d2d.bptc.ctex"]
|
||||||
|
|
||||||
[params]
|
[params]
|
||||||
|
|
||||||
compress/mode=2
|
compress/mode=2
|
||||||
compress/high_quality=false
|
compress/high_quality=true
|
||||||
compress/lossy_quality=0.7
|
compress/lossy_quality=0.7
|
||||||
compress/hdr_compression=1
|
compress/hdr_compression=1
|
||||||
compress/normal_map=0
|
compress/normal_map=0
|
||||||
compress/channel_pack=0
|
compress/channel_pack=0
|
||||||
mipmaps/generate=true
|
mipmaps/generate=false
|
||||||
mipmaps/limit=-1
|
mipmaps/limit=-1
|
||||||
roughness/mode=0
|
roughness/mode=0
|
||||||
roughness/src_normal=""
|
roughness/src_normal=""
|
||||||
37
icon.svg.import
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://detphn5aabvf3"
|
||||||
|
path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://icon.svg"
|
||||||
|
dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
|
svg/scale=1.0
|
||||||
|
editor/scale_with_editor_scale=false
|
||||||
|
editor/convert_colors_with_editor_theme=false
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
[gd_resource type="StyleBoxFlat" format=3 uid="uid://cl7dmo2bg4153"]
|
|
||||||
|
|
||||||
[resource]
|
|
||||||
bg_color = Color(1, 0.356863, 0.145098, 1)
|
|
||||||
|
|
@ -1,124 +1,145 @@
|
||||||
[gd_scene load_steps=6 format=3 uid="uid://bcv81ku26xo"]
|
[gd_scene load_steps=8 format=3 uid="uid://bcv81ku26xo"]
|
||||||
|
|
||||||
[ext_resource type="StyleBox" uid="uid://cl7dmo2bg4153" path="res://interfaces/hud/healthbar_fill_style.tres" id="1_gh51l"]
|
[ext_resource type="StyleBox" uid="uid://dcn1ll2ra4lwn" path="res://interfaces/hud/vitals/background.tres" id="1_gmv44"]
|
||||||
|
[ext_resource type="StyleBox" uid="uid://bq7rjpm38pao7" path="res://interfaces/hud/vitals/health_foreground.tres" id="2_6ejsl"]
|
||||||
|
|
||||||
[sub_resource type="GDScript" id="GDScript_2vxif"]
|
[sub_resource type="GDScript" id="GDScript_2vxif"]
|
||||||
script/source = "extends CanvasLayer
|
script/source = "class_name HUD extends CanvasLayer
|
||||||
class_name HUD
|
|
||||||
|
|
||||||
@onready var _health_bar = $HealthBar
|
@export_category(\"Vitals\")
|
||||||
@onready var _energy_bar = $EnergyBar
|
@export var _health_bar : ProgressBar
|
||||||
|
@export var _energy_bar : ProgressBar
|
||||||
|
|
||||||
func _ready():
|
func _ready() -> void:
|
||||||
_update_health_bar(100)
|
_update_health_bar(100.)
|
||||||
_update_energy_bar(100)
|
_update_energy_bar(100.)
|
||||||
|
|
||||||
func _update_energy_bar(energy) -> void:
|
func _update_energy_bar(energy : float) -> void:
|
||||||
_energy_bar.value = energy
|
_energy_bar.value = energy
|
||||||
|
|
||||||
func _on_energy_changed(new_energy) -> void:
|
func _on_energy_changed(new_energy : float) -> void:
|
||||||
_update_energy_bar(new_energy)
|
_update_energy_bar(new_energy)
|
||||||
|
|
||||||
func _update_health_bar(health) -> void:
|
func _update_health_bar(health : float) -> void:
|
||||||
_health_bar.value = health
|
_health_bar.value = health
|
||||||
|
|
||||||
func _on_health_changed(new_health) -> void:
|
func _on_health_changed(new_health : float) -> void:
|
||||||
_update_health_bar(new_health)
|
_update_health_bar(new_health)
|
||||||
"
|
"
|
||||||
|
|
||||||
[sub_resource type="Theme" id="Theme_irfqb"]
|
|
||||||
|
|
||||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_f23s3"]
|
|
||||||
bg_color = Color(0, 0.454902, 0.992157, 1)
|
|
||||||
|
|
||||||
[sub_resource type="GDScript" id="GDScript_w8l21"]
|
[sub_resource type="GDScript" id="GDScript_w8l21"]
|
||||||
script/source = "extends Label
|
script/source = "extends Label
|
||||||
|
|
||||||
@onready var player = get_parent().owner
|
@onready var player : Player = get_parent().owner
|
||||||
|
|
||||||
# Called when the node enters the scene tree for the first time.
|
# Called when the node enters the scene tree for the first time.
|
||||||
func _ready():
|
func _ready() -> void:
|
||||||
pass # Replace with function body.
|
if not OS.is_debug_build():
|
||||||
|
queue_free()
|
||||||
|
|
||||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
func _process(_delta):
|
func _process(_delta : float) -> void:
|
||||||
text = \"\"
|
text = \"\"
|
||||||
text += \"fps: %s\\n\" % str(Engine.get_frames_per_second())
|
text += \"fps: %s\\n\" % str(Engine.get_frames_per_second())
|
||||||
text += \"position: %d, %d, %d\\n\" % [player.position.x, player.position.y, player.position.z]
|
text += \"position: %d, %d, %d\\n\" % [player.position.x, player.position.y, player.position.z]
|
||||||
text += \"speed: %d km/h\\n\" % (player.linear_velocity.length() * 3.6)
|
text += \"speed: %d km/h\\n\" % (player.linear_velocity.length() * 3.6)
|
||||||
"
|
"
|
||||||
|
|
||||||
[node name="HUD" type="CanvasLayer"]
|
[sub_resource type="Shader" id="Shader_gaah5"]
|
||||||
|
code = "shader_type canvas_item;
|
||||||
|
|
||||||
|
uniform vec4 color : source_color;
|
||||||
|
|
||||||
|
float circle(vec2 pos, float radius, float feather) {
|
||||||
|
return smoothstep(radius, radius - feather, length(pos - vec2(.5)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void fragment() {
|
||||||
|
// draw reticle
|
||||||
|
float alpha = circle(UV, .5, .04);
|
||||||
|
COLOR = vec4(texture(TEXTURE, UV).rgb, alpha);
|
||||||
|
}"
|
||||||
|
|
||||||
|
[sub_resource type="ShaderMaterial" id="ShaderMaterial_7blp5"]
|
||||||
|
shader = SubResource("Shader_gaah5")
|
||||||
|
shader_parameter/color = Color(1, 1, 1, 1)
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_f23s3"]
|
||||||
|
bg_color = Color(0.0901961, 0.87451, 0.760784, 0.65098)
|
||||||
|
corner_radius_top_left = 3
|
||||||
|
corner_radius_top_right = 3
|
||||||
|
corner_radius_bottom_right = 3
|
||||||
|
corner_radius_bottom_left = 3
|
||||||
|
anti_aliasing = false
|
||||||
|
|
||||||
|
[node name="HUD" type="CanvasLayer" node_paths=PackedStringArray("_health_bar", "_energy_bar")]
|
||||||
script = SubResource("GDScript_2vxif")
|
script = SubResource("GDScript_2vxif")
|
||||||
|
_health_bar = NodePath("MarginContainer/HBoxContainer/VBoxContainer/HealthBar")
|
||||||
[node name="HealthBar" type="ProgressBar" parent="."]
|
_energy_bar = NodePath("MarginContainer/HBoxContainer/VBoxContainer/EnergyBar")
|
||||||
offset_left = 32.0
|
|
||||||
offset_top = 32.0
|
|
||||||
offset_right = 288.0
|
|
||||||
offset_bottom = 40.0
|
|
||||||
size_flags_horizontal = 0
|
|
||||||
mouse_filter = 2
|
|
||||||
theme = SubResource("Theme_irfqb")
|
|
||||||
theme_override_styles/fill = ExtResource("1_gh51l")
|
|
||||||
value = 60.0
|
|
||||||
show_percentage = false
|
|
||||||
|
|
||||||
[node name="EnergyBar" type="ProgressBar" parent="."]
|
|
||||||
offset_left = 32.0
|
|
||||||
offset_top = 48.0
|
|
||||||
offset_right = 288.0
|
|
||||||
offset_bottom = 56.0
|
|
||||||
size_flags_horizontal = 0
|
|
||||||
mouse_filter = 2
|
|
||||||
theme = SubResource("Theme_irfqb")
|
|
||||||
theme_override_styles/fill = SubResource("StyleBoxFlat_f23s3")
|
|
||||||
value = 60.0
|
|
||||||
show_percentage = false
|
|
||||||
|
|
||||||
[node name="DebugLabel" type="Label" parent="."]
|
[node name="DebugLabel" type="Label" parent="."]
|
||||||
anchors_preset = 2
|
|
||||||
anchor_top = 1.0
|
|
||||||
anchor_bottom = 1.0
|
|
||||||
offset_left = 20.0
|
offset_left = 20.0
|
||||||
offset_top = -33.0
|
offset_top = 20.0
|
||||||
offset_right = 21.0
|
offset_right = 21.0
|
||||||
offset_bottom = -10.0
|
offset_bottom = 43.0
|
||||||
grow_vertical = 0
|
|
||||||
script = SubResource("GDScript_w8l21")
|
script = SubResource("GDScript_w8l21")
|
||||||
|
|
||||||
[node name="Reticle" type="Control" parent="."]
|
[node name="Reticle" type="ColorRect" parent="."]
|
||||||
layout_mode = 3
|
material = SubResource("ShaderMaterial_7blp5")
|
||||||
anchors_preset = 8
|
anchors_preset = 8
|
||||||
anchor_left = 0.5
|
anchor_left = 0.5
|
||||||
anchor_top = 0.5
|
anchor_top = 0.5
|
||||||
anchor_right = 0.5
|
anchor_right = 0.5
|
||||||
anchor_bottom = 0.5
|
anchor_bottom = 0.5
|
||||||
offset_left = -20.0
|
offset_left = -1.5
|
||||||
offset_top = -20.0
|
offset_top = -1.5
|
||||||
offset_right = 20.0
|
offset_right = 1.5
|
||||||
offset_bottom = 20.0
|
offset_bottom = 1.5
|
||||||
grow_horizontal = 2
|
grow_horizontal = 2
|
||||||
grow_vertical = 2
|
grow_vertical = 2
|
||||||
mouse_filter = 2
|
mouse_filter = 2
|
||||||
|
|
||||||
[node name="LineBottom" type="Line2D" parent="Reticle"]
|
[node name="MarginContainer" type="MarginContainer" parent="."]
|
||||||
position = Vector2(13, 4)
|
anchors_preset = 12
|
||||||
points = PackedVector2Array(7, 19, 7, 31)
|
anchor_top = 1.0
|
||||||
width = 2.0
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_top = -42.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 0
|
||||||
|
theme_override_constants/margin_left = 20
|
||||||
|
theme_override_constants/margin_right = 20
|
||||||
|
theme_override_constants/margin_bottom = 20
|
||||||
|
|
||||||
[node name="LineLeft" type="Line2D" parent="Reticle"]
|
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer"]
|
||||||
position = Vector2(36, 13)
|
layout_mode = 2
|
||||||
rotation = 1.5708
|
size_flags_horizontal = 3
|
||||||
points = PackedVector2Array(7, 19, 7, 31)
|
|
||||||
width = 2.0
|
|
||||||
|
|
||||||
[node name="LineTop" type="Line2D" parent="Reticle"]
|
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/HBoxContainer"]
|
||||||
position = Vector2(13, -14)
|
layout_mode = 2
|
||||||
points = PackedVector2Array(7, 19, 7, 31)
|
size_flags_horizontal = 3
|
||||||
width = 2.0
|
size_flags_stretch_ratio = 0.2
|
||||||
|
theme_override_constants/separation = 6
|
||||||
|
|
||||||
[node name="LineRight" type="Line2D" parent="Reticle"]
|
[node name="HealthBar" type="ProgressBar" parent="MarginContainer/HBoxContainer/VBoxContainer"]
|
||||||
position = Vector2(54, 13)
|
custom_minimum_size = Vector2(0, 8)
|
||||||
rotation = 1.5708
|
layout_mode = 2
|
||||||
points = PackedVector2Array(7, 19, 7, 31)
|
mouse_filter = 2
|
||||||
width = 2.0
|
theme_override_styles/background = ExtResource("1_gmv44")
|
||||||
|
theme_override_styles/fill = ExtResource("2_6ejsl")
|
||||||
|
value = 60.0
|
||||||
|
show_percentage = false
|
||||||
|
|
||||||
|
[node name="EnergyBar" type="ProgressBar" parent="MarginContainer/HBoxContainer/VBoxContainer"]
|
||||||
|
custom_minimum_size = Vector2(0, 8)
|
||||||
|
layout_mode = 2
|
||||||
|
mouse_filter = 2
|
||||||
|
theme_override_styles/background = ExtResource("1_gmv44")
|
||||||
|
theme_override_styles/fill = SubResource("StyleBoxFlat_f23s3")
|
||||||
|
value = 60.0
|
||||||
|
show_percentage = false
|
||||||
|
|
||||||
|
[node name="Spacer" type="Control" parent="MarginContainer/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_stretch_ratio = 0.8
|
||||||
|
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
# This file is part of open-fpsz.
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
extends Node2D
|
|
||||||
|
|
||||||
@export var attach_point : Node3D
|
|
||||||
@export var player : Player
|
|
||||||
|
|
||||||
@onready var _player_name_label = $Offset/VBoxContainer/PlayerNameLabel
|
|
||||||
@onready var _health_bar = $Offset/VBoxContainer/HealthBar
|
|
||||||
@onready var _v_box_container = $Offset/VBoxContainer
|
|
||||||
|
|
||||||
func _process(_delta):
|
|
||||||
var camera : Camera3D = get_viewport().get_camera_3d()
|
|
||||||
if camera.is_position_behind(attach_point.global_position):
|
|
||||||
_v_box_container.hide()
|
|
||||||
else:
|
|
||||||
_v_box_container.show()
|
|
||||||
|
|
||||||
_player_name_label.text = player.name
|
|
||||||
position = camera.unproject_position(attach_point.global_position)
|
|
||||||
var viewport_size : Vector2 = get_viewport_rect().size
|
|
||||||
position.x = clampf(position.x, 0, viewport_size.x - _v_box_container.size.x)
|
|
||||||
position.y = clampf(position.y, _v_box_container.size.y, viewport_size.y)
|
|
||||||
|
|
||||||
func _update_health_bar(health) -> void:
|
|
||||||
_health_bar.value = health
|
|
||||||
|
|
||||||
func _on_health_changed(new_health) -> void:
|
|
||||||
_update_health_bar(new_health)
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
[gd_scene load_steps=3 format=3 uid="uid://dsysi2rd3bu76"]
|
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://interfaces/hud/iff.gd" id="1_75yi1"]
|
|
||||||
[ext_resource type="StyleBox" uid="uid://cl7dmo2bg4153" path="res://interfaces/hud/healthbar_fill_style.tres" id="2_x7k8o"]
|
|
||||||
|
|
||||||
[node name="IFF" type="Node2D"]
|
|
||||||
script = ExtResource("1_75yi1")
|
|
||||||
|
|
||||||
[node name="Offset" type="Node2D" parent="."]
|
|
||||||
position = Vector2(0, -32)
|
|
||||||
|
|
||||||
[node name="VBoxContainer" type="VBoxContainer" parent="Offset"]
|
|
||||||
offset_right = 100.0
|
|
||||||
offset_bottom = 40.0
|
|
||||||
mouse_filter = 2
|
|
||||||
|
|
||||||
[node name="PlayerNameLabel" type="Label" parent="Offset/VBoxContainer"]
|
|
||||||
layout_mode = 2
|
|
||||||
metadata/_edit_use_anchors_ = true
|
|
||||||
|
|
||||||
[node name="HealthBar" type="ProgressBar" parent="Offset/VBoxContainer"]
|
|
||||||
layout_mode = 2
|
|
||||||
mouse_filter = 2
|
|
||||||
theme_override_styles/fill = ExtResource("2_x7k8o")
|
|
||||||
value = 60.0
|
|
||||||
show_percentage = false
|
|
||||||
9
interfaces/hud/iffs/health_foreground.tres
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
[gd_resource type="StyleBoxFlat" format=3 uid="uid://cgv081wfih7la"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
bg_color = Color(1, 0, 0, 0.25)
|
||||||
|
corner_radius_top_left = 3
|
||||||
|
corner_radius_top_right = 3
|
||||||
|
corner_radius_bottom_right = 3
|
||||||
|
corner_radius_bottom_left = 3
|
||||||
|
anti_aliasing = false
|
||||||
91
interfaces/hud/iffs/iff.gd
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
# This file is part of open-fpsz.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
extends Control
|
||||||
|
|
||||||
|
@export var player : Player
|
||||||
|
@export var attach_point : Marker3D
|
||||||
|
@export var healthbar_low_health_color : Color = Color(1 ,0 ,0, 0.78)
|
||||||
|
@export var healthbar_mid_health_color : Color = Color(1, 1, 0, 0.78)
|
||||||
|
@export var healthbar_high_health_color : Color = Color(0, 1, 0, 0.78)
|
||||||
|
@export var iff_in_range_radius_ratio : float = 0.05
|
||||||
|
|
||||||
|
@onready var _iff_container : Control = $IFFContainer
|
||||||
|
@onready var _iff_in_range_container : Control = $IFFContainer/IFFInRangeContainer
|
||||||
|
@onready var _player_name_label : Control = $IFFContainer/IFFInRangeContainer/PlayerNameLabel
|
||||||
|
@onready var _health_bar : ProgressBar = $IFFContainer/IFFInRangeContainer/HealthBar
|
||||||
|
@onready var is_within_los : bool = false
|
||||||
|
@onready var healthbar_fill_stylebox : StyleBoxFlat = _health_bar.get_theme_stylebox("fill")
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
_player_name_label.text = player.name
|
||||||
|
|
||||||
|
func _process(_delta : float) -> void:
|
||||||
|
# retrieve camera for current viewport
|
||||||
|
var camera : Camera3D = get_viewport().get_camera_3d()
|
||||||
|
|
||||||
|
# if the player is NOT infront of the camera or camera does NOT have LOS to player
|
||||||
|
if camera.is_position_behind(attach_point.global_position) or !is_within_los:
|
||||||
|
_iff_container.hide() # hide the IFF and exit function
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
_iff_container.show() # display the IFF
|
||||||
|
|
||||||
|
func _physics_process(_delta : float) -> void:
|
||||||
|
# https://docs.godotengine.org/en/stable/tutorials/physics/ray-casting.html
|
||||||
|
var camera : Camera3D = get_viewport().get_camera_3d()
|
||||||
|
is_within_los = false # always initialise trace_success as false
|
||||||
|
var space_state : PhysicsDirectSpaceState3D = camera.get_world_3d().direct_space_state
|
||||||
|
# do a trace check from camera to towards the player
|
||||||
|
var query : PhysicsRayQueryParameters3D = PhysicsRayQueryParameters3D.create(camera.global_position, attach_point.global_position)
|
||||||
|
# exclude the camera owner nodes from intersecting with the trace check
|
||||||
|
query.exclude = [camera.owner]
|
||||||
|
# do trace check and store result
|
||||||
|
var result : Dictionary = space_state.intersect_ray(query)
|
||||||
|
# if a result was returned and the hit result is the player
|
||||||
|
if result and result["collider"] == player:
|
||||||
|
# the player is in camera LOS
|
||||||
|
is_within_los = true
|
||||||
|
|
||||||
|
var new_iff_position : Vector2 = camera.unproject_position(attach_point.global_position) # get the screen location of the players head
|
||||||
|
var viewport_size : Vector2 = get_viewport_rect().size
|
||||||
|
|
||||||
|
# check if the unprojected point lies inside the viewport
|
||||||
|
if !Rect2(Vector2(0, 0), viewport_size).has_point(new_iff_position):
|
||||||
|
_iff_container.hide() # hide the IFF and exit function
|
||||||
|
return
|
||||||
|
|
||||||
|
# if player is NOT in range to have its healthbar and name drawn
|
||||||
|
if (new_iff_position - viewport_size / 2).length() > iff_in_range_radius_ratio * viewport_size.length():
|
||||||
|
_iff_in_range_container.hide() # hide the in range IFF
|
||||||
|
else:
|
||||||
|
_iff_in_range_container.show()
|
||||||
|
|
||||||
|
new_iff_position.y -= _iff_container.size.y # move the IFF up so the bottom of it is at the players head
|
||||||
|
new_iff_position.x -= _iff_container.size.x / 2 # move the IFF left so it's centered horizontally above players head
|
||||||
|
|
||||||
|
position = new_iff_position # set the position of the IFF
|
||||||
|
|
||||||
|
func _update_health_bar(health : float) -> void:
|
||||||
|
_health_bar.value = health
|
||||||
|
# modify health_box stylebox depending health value
|
||||||
|
if health < 75 and health > 40:
|
||||||
|
healthbar_fill_stylebox.bg_color = healthbar_mid_health_color
|
||||||
|
elif health <= 40:
|
||||||
|
healthbar_fill_stylebox.bg_color = healthbar_low_health_color
|
||||||
|
else:
|
||||||
|
healthbar_fill_stylebox.bg_color = healthbar_high_health_color
|
||||||
|
|
||||||
|
func _on_health_changed(new_health : float) -> void:
|
||||||
|
_update_health_bar(new_health)
|
||||||
54
interfaces/hud/iffs/iff.tscn
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
[gd_scene load_steps=4 format=3 uid="uid://dsysi2rd3bu76"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://interfaces/hud/iffs/iff.gd" id="1_g1wra"]
|
||||||
|
[ext_resource type="StyleBox" uid="uid://cgv081wfih7la" path="res://interfaces/hud/iffs/health_foreground.tres" id="2_e3xla"]
|
||||||
|
[ext_resource type="StyleBox" uid="uid://dcn1ll2ra4lwn" path="res://interfaces/hud/vitals/background.tres" id="2_jtos4"]
|
||||||
|
|
||||||
|
[node name="IFF" type="Control"]
|
||||||
|
layout_mode = 3
|
||||||
|
anchors_preset = 0
|
||||||
|
script = ExtResource("1_g1wra")
|
||||||
|
|
||||||
|
[node name="IFFContainer" type="MarginContainer" parent="."]
|
||||||
|
layout_mode = 0
|
||||||
|
offset_right = 63.0
|
||||||
|
offset_bottom = 42.0
|
||||||
|
mouse_filter = 2
|
||||||
|
|
||||||
|
[node name="IFFInRangeContainer" type="Control" parent="IFFContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
mouse_filter = 2
|
||||||
|
|
||||||
|
[node name="PlayerNameLabel" type="Label" parent="IFFContainer/IFFInRangeContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
offset_right = 63.0
|
||||||
|
offset_bottom = 17.0
|
||||||
|
theme_override_colors/font_color = Color(1, 1, 1, 1)
|
||||||
|
theme_override_font_sizes/font_size = 12
|
||||||
|
text = "Player"
|
||||||
|
horizontal_alignment = 1
|
||||||
|
metadata/_edit_use_anchors_ = true
|
||||||
|
|
||||||
|
[node name="HealthBar" type="ProgressBar" parent="IFFContainer/IFFInRangeContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
offset_top = 20.0
|
||||||
|
offset_right = 63.0
|
||||||
|
offset_bottom = 24.0
|
||||||
|
mouse_filter = 2
|
||||||
|
theme_override_styles/background = ExtResource("2_jtos4")
|
||||||
|
theme_override_styles/fill = ExtResource("2_e3xla")
|
||||||
|
value = 60.0
|
||||||
|
show_percentage = false
|
||||||
|
|
||||||
|
[node name="Chevron" type="Label" parent="IFFContainer"]
|
||||||
|
layout_direction = 2
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 1
|
||||||
|
theme_override_colors/font_color = Color(1, 0, 0, 0.2)
|
||||||
|
theme_override_colors/font_outline_color = Color(0, 0, 0, 0.2)
|
||||||
|
theme_override_constants/outline_size = 3
|
||||||
|
theme_override_constants/line_spacing = -20
|
||||||
|
theme_override_font_sizes/font_size = 14
|
||||||
|
text = "▼"
|
||||||
|
horizontal_alignment = 1
|
||||||
|
vertical_alignment = 2
|
||||||
9
interfaces/hud/vitals/background.tres
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
[gd_resource type="StyleBoxFlat" format=3 uid="uid://dcn1ll2ra4lwn"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
bg_color = Color(0, 0, 0, 0.25)
|
||||||
|
corner_radius_top_left = 3
|
||||||
|
corner_radius_top_right = 3
|
||||||
|
corner_radius_bottom_right = 3
|
||||||
|
corner_radius_bottom_left = 3
|
||||||
|
anti_aliasing = false
|
||||||
10
interfaces/hud/vitals/health_foreground.tres
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
[gd_resource type="StyleBoxFlat" format=3 uid="uid://bq7rjpm38pao7"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
resource_local_to_scene = true
|
||||||
|
bg_color = Color(0.025, 0.75, 0.1, 0.65)
|
||||||
|
corner_radius_top_left = 3
|
||||||
|
corner_radius_top_right = 3
|
||||||
|
corner_radius_bottom_right = 3
|
||||||
|
corner_radius_bottom_left = 3
|
||||||
|
anti_aliasing = false
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
[gd_scene load_steps=7 format=3 uid="uid://bjctlqvs33nqy"]
|
[gd_scene load_steps=9 format=3 uid="uid://bjctlqvs33nqy"]
|
||||||
|
|
||||||
[ext_resource type="Texture2D" uid="uid://c1tjamjm8qjog" path="res://interfaces/menus/boot/background.webp" id="1_ph586"]
|
[ext_resource type="Texture2D" uid="uid://c1tjamjm8qjog" path="res://interfaces/menus/boot/background.webp" id="1_ph586"]
|
||||||
|
|
||||||
|
|
@ -8,88 +8,144 @@ script/source = "class_name BootMenu extends CanvasLayer
|
||||||
|
|
||||||
signal start_demo
|
signal start_demo
|
||||||
|
|
||||||
func _on_demo_pressed():
|
func _on_demo_pressed() -> void:
|
||||||
start_demo.emit()
|
start_demo.emit()
|
||||||
|
|
||||||
|
func _on_multiplayer_pressed() -> void:
|
||||||
|
_show_menu($Multiplayer)
|
||||||
|
|
||||||
|
func _on_settings_pressed() -> void:
|
||||||
|
_show_menu($Settings)
|
||||||
|
|
||||||
|
func _on_quit_pressed() -> void:
|
||||||
|
get_tree().quit()
|
||||||
|
|
||||||
|
func _on_main_menu_pressed() -> void:
|
||||||
|
_show_menu($Main)
|
||||||
|
|
||||||
|
func _show_menu(menu : PanelContainer) -> void:
|
||||||
|
$Multiplayer.hide()
|
||||||
|
$Multiplayer.tab_container.current_tab = 0
|
||||||
|
$Settings.hide()
|
||||||
|
$Settings.tab_container.current_tab = 0
|
||||||
|
$Main.hide()
|
||||||
|
menu.show()
|
||||||
"
|
"
|
||||||
|
|
||||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_krqeq"]
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_krqeq"]
|
||||||
bg_color = Color(0.5, 0.5, 0.5, 0.25)
|
bg_color = Color(0.501961, 0.501961, 0.501961, 0.25098)
|
||||||
|
|
||||||
[sub_resource type="GDScript" id="GDScript_tc1bm"]
|
[sub_resource type="GDScript" id="GDScript_tc1bm"]
|
||||||
script/source = "class_name MultiplayerPanel extends PanelContainer
|
script/source = "class_name Multiplayer extends PanelContainer
|
||||||
|
|
||||||
const DEFAULT_HOST : String = \"localhost\"
|
const DEFAULT_HOST : String = \"localhost\"
|
||||||
const DEFAULT_PORT : int = 9000
|
const DEFAULT_PORT : int = 9000
|
||||||
|
const CONFIG_FILE_PATH : String = \"user://profile.cfg\"
|
||||||
|
|
||||||
var _join_address = RegEx.new()
|
var _join_address : RegEx = RegEx.new()
|
||||||
var _registered_ports = RegEx.new()
|
var _registered_ports : RegEx = RegEx.new()
|
||||||
|
var _config_file : ConfigFile = ConfigFile.new()
|
||||||
|
|
||||||
signal start_server(port)
|
signal start_server(port : int)
|
||||||
signal join_server(host, port)
|
signal join_server(host : String, port : int)
|
||||||
|
|
||||||
@onready var modal : Control = $Modal
|
@onready var modal : Control = $Modal
|
||||||
@onready var menu : CanvasLayer = get_parent()
|
@onready var menu : CanvasLayer = get_parent()
|
||||||
|
@export var tab_container : TabContainer
|
||||||
|
|
||||||
func _ready():
|
func _ready() -> void:
|
||||||
# see https://datatracker.ietf.org/doc/html/rfc1700
|
# see https://datatracker.ietf.org/doc/html/rfc1700
|
||||||
_registered_ports.compile(r'^(?:102[4-9]|10[3-9]\\d|1[1-9]\\d{2}|[2-9]\\d{3}|[1-5]\\d{4}|6[0-4]\\d{3}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5])$')
|
_registered_ports.compile(r'^(?:102[4-9]|10[3-9]\\d|1[1-9]\\d{2}|[2-9]\\d{3}|[1-5]\\d{4}|6[0-4]\\d{3}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5])$')
|
||||||
_join_address.compile(r'^(?<host>[a-zA-Z0-9.-]+)(:(?<port>:102[4-9]|10[3-9]\\d|1[1-9]\\d{2}|[2-9]\\d{3}|[1-5]\\d{4}|6[0-4]\\d{3}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5]))?$')
|
_join_address.compile(r'^(?<host>[a-zA-Z0-9.-]+)(:(?<port>:102[4-9]|10[3-9]\\d|1[1-9]\\d{2}|[2-9]\\d{3}|[1-5]\\d{4}|6[0-4]\\d{3}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5]))?$')
|
||||||
|
_load_config()
|
||||||
hide() # start hidden
|
hide() # start hidden
|
||||||
|
|
||||||
func _on_menu_pressed():
|
func _load_config() -> void:
|
||||||
|
var error : Error = _config_file.load(CONFIG_FILE_PATH)
|
||||||
|
if error != OK:
|
||||||
|
return
|
||||||
|
|
||||||
|
var profile_name : String = _config_file.get_value(\"profile\", \"name\", \"Newblood\")
|
||||||
|
%ProfileName.text = profile_name
|
||||||
|
|
||||||
|
func _on_save_pressed() -> void:
|
||||||
|
_config_file.set_value(\"profile\", \"name\", %ProfileName.text)
|
||||||
|
_config_file.save(CONFIG_FILE_PATH)
|
||||||
|
|
||||||
|
func _on_menu_pressed() -> void:
|
||||||
hide()
|
hide()
|
||||||
owner.get_node(\"Main\").show()
|
owner.get_node(\"Main\").show()
|
||||||
|
|
||||||
func _on_quit_pressed():
|
func _on_quit_pressed() -> void:
|
||||||
get_tree().quit()
|
get_tree().quit()
|
||||||
|
|
||||||
func _on_host_pressed():
|
func _on_host_pressed() -> void:
|
||||||
var port = DEFAULT_PORT
|
var port : int = DEFAULT_PORT
|
||||||
# check for registered ports number matches
|
# check for registered ports number matches
|
||||||
if %ServerPort.text:
|
if %ServerPort.text:
|
||||||
var result = _registered_ports.search(%ServerPort.text)
|
var result : RegExMatch = _registered_ports.search(%ServerPort.text)
|
||||||
if result: # port is valid
|
if result: # port is valid
|
||||||
port = int(result.get_string())
|
port = int(result.get_string())
|
||||||
else: # port is not valid
|
else: # port is not valid
|
||||||
push_warning(\"A valid port number in the range 1024-65535 is required.\")
|
push_warning(\"A valid port number in the range 1024-65535 is required.\")
|
||||||
return
|
return
|
||||||
|
|
||||||
start_server.emit(port)
|
|
||||||
|
|
||||||
func _on_join_pressed():
|
start_server.emit(port, %ProfileName.text)
|
||||||
var addr = [DEFAULT_HOST, DEFAULT_PORT]
|
|
||||||
|
func _on_join_pressed() -> void:
|
||||||
|
var addr : Array = [DEFAULT_HOST, DEFAULT_PORT]
|
||||||
# validate join address input
|
# validate join address input
|
||||||
var result = _join_address.search(%JoinAddress.text)
|
var result : RegExMatch = _join_address.search(%JoinAddress.text)
|
||||||
if result: # address is valid
|
if result: # address is valid
|
||||||
addr[0] = result.get_string(\"host\")
|
addr[0] = result.get_string(\"host\")
|
||||||
var rport = result.get_string(\"port\")
|
var rport : String = result.get_string(\"port\")
|
||||||
if rport: addr[1] = int(rport)
|
if rport: addr[1] = int(rport)
|
||||||
|
|
||||||
$Modal.show()
|
$Modal.show()
|
||||||
join_server.emit(addr[0], addr[1])
|
join_server.emit(addr[0], addr[1], %ProfileName.text)
|
||||||
|
|
||||||
func _on_connected_to_server():
|
func _on_connected_to_server() -> void:
|
||||||
$Modal.hide()
|
$Modal.hide()
|
||||||
menu.hide()
|
menu.hide()
|
||||||
|
|
||||||
func _on_connection_failed():
|
func _on_connection_failed() -> void:
|
||||||
$Modal.hide()
|
$Modal.hide()
|
||||||
"
|
"
|
||||||
|
|
||||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_snh7i"]
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ky5sv"]
|
||||||
bg_color = Color(0, 0.5, 0.5, 0.25)
|
bg_color = Color(0.5, 0.5, 0.5, 0.25)
|
||||||
|
|
||||||
[sub_resource type="GDScript" id="GDScript_yqbr7"]
|
[sub_resource type="GDScript" id="GDScript_gbnwv"]
|
||||||
|
resource_name = "Settings"
|
||||||
script/source = "extends PanelContainer
|
script/source = "extends PanelContainer
|
||||||
|
|
||||||
func _on_multiplayer_pressed():
|
const WINDOW_MODE_OPTIONS = [DisplayServer.WINDOW_MODE_WINDOWED, DisplayServer.WINDOW_MODE_FULLSCREEN]
|
||||||
hide()
|
|
||||||
owner.get_node(\"Multiplayer\").show()
|
@onready var _game_settings : Settings = get_node(\"/root/GlobalSettings\")
|
||||||
|
|
||||||
func _on_quit_pressed():
|
@export var tab_container : TabContainer
|
||||||
get_tree().quit()
|
|
||||||
|
func _ready() -> void:
|
||||||
|
%FOVSpinBox.value = _game_settings.fov
|
||||||
|
%SensitivitySpinBox.value = _game_settings.mouse_sensitivity
|
||||||
|
var window_mode : int = 1 if _game_settings.fullscreen else 0
|
||||||
|
%InvertedYCheckbox.button_pressed = _game_settings.inverted_y_axis
|
||||||
|
%WindowModeOptionButton.select(window_mode)
|
||||||
|
|
||||||
|
func _on_save_pressed() -> void:
|
||||||
|
_game_settings.fov = %FOVSpinBox.value
|
||||||
|
_game_settings.mouse_sensitivity = %SensitivitySpinBox.value
|
||||||
|
_game_settings.inverted_y_axis = %InvertedYCheckbox.button_pressed
|
||||||
|
_game_settings.fullscreen = %WindowModeOptionButton.selected == 1
|
||||||
|
_game_settings.save_to_file()
|
||||||
"
|
"
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_c4ymk"]
|
||||||
|
bg_color = Color(0, 0, 0, 0)
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_dq4me"]
|
||||||
|
bg_color = Color(0, 0.5, 0.5, 0.2)
|
||||||
|
|
||||||
[node name="BootMenu" type="CanvasLayer"]
|
[node name="BootMenu" type="CanvasLayer"]
|
||||||
script = SubResource("GDScript_jd8xf")
|
script = SubResource("GDScript_jd8xf")
|
||||||
|
|
||||||
|
|
@ -103,7 +159,7 @@ mouse_filter = 2
|
||||||
texture = ExtResource("1_ph586")
|
texture = ExtResource("1_ph586")
|
||||||
stretch_mode = 6
|
stretch_mode = 6
|
||||||
|
|
||||||
[node name="Multiplayer" type="PanelContainer" parent="."]
|
[node name="Multiplayer" type="PanelContainer" parent="." node_paths=PackedStringArray("tab_container")]
|
||||||
visible = false
|
visible = false
|
||||||
anchors_preset = 15
|
anchors_preset = 15
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
|
|
@ -112,6 +168,7 @@ grow_horizontal = 2
|
||||||
grow_vertical = 2
|
grow_vertical = 2
|
||||||
theme_override_styles/panel = SubResource("StyleBoxFlat_krqeq")
|
theme_override_styles/panel = SubResource("StyleBoxFlat_krqeq")
|
||||||
script = SubResource("GDScript_tc1bm")
|
script = SubResource("GDScript_tc1bm")
|
||||||
|
tab_container = NodePath("MarginContainer/VBoxContainer/TabContainer")
|
||||||
|
|
||||||
[node name="MarginContainer" type="MarginContainer" parent="Multiplayer"]
|
[node name="MarginContainer" type="MarginContainer" parent="Multiplayer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
@ -120,15 +177,19 @@ theme_override_constants/margin_top = 20
|
||||||
theme_override_constants/margin_right = 20
|
theme_override_constants/margin_right = 20
|
||||||
theme_override_constants/margin_bottom = 20
|
theme_override_constants/margin_bottom = 20
|
||||||
|
|
||||||
[node name="TabContainer" type="TabContainer" parent="Multiplayer/MarginContainer"]
|
[node name="VBoxContainer" type="VBoxContainer" parent="Multiplayer/MarginContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="TabContainer" type="TabContainer" parent="Multiplayer/MarginContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
theme_override_constants/side_margin = 0
|
theme_override_constants/side_margin = 0
|
||||||
|
|
||||||
[node name="Profile" type="TabBar" parent="Multiplayer/MarginContainer/TabContainer"]
|
[node name="Profile" type="TabBar" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
theme_override_constants/h_separation = 0
|
theme_override_constants/h_separation = 0
|
||||||
|
|
||||||
[node name="MarginContainer" type="MarginContainer" parent="Multiplayer/MarginContainer/TabContainer/Profile"]
|
[node name="MarginContainer" type="MarginContainer" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Profile"]
|
||||||
layout_mode = 0
|
layout_mode = 0
|
||||||
offset_right = 1116.0
|
offset_right = 1116.0
|
||||||
offset_bottom = 577.0
|
offset_bottom = 577.0
|
||||||
|
|
@ -137,58 +198,80 @@ theme_override_constants/margin_top = 20
|
||||||
theme_override_constants/margin_right = 20
|
theme_override_constants/margin_right = 20
|
||||||
theme_override_constants/margin_bottom = 20
|
theme_override_constants/margin_bottom = 20
|
||||||
|
|
||||||
[node name="HBoxContainer" type="HBoxContainer" parent="Multiplayer/MarginContainer/TabContainer/Profile/MarginContainer"]
|
[node name="HBoxContainer" type="HBoxContainer" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Profile/MarginContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
theme_override_constants/separation = 20
|
theme_override_constants/separation = 20
|
||||||
|
|
||||||
[node name="LeftBox" type="VBoxContainer" parent="Multiplayer/MarginContainer/TabContainer/Profile/MarginContainer/HBoxContainer"]
|
[node name="LeftBox" type="Control" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Profile/MarginContainer/HBoxContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
size_flags_stretch_ratio = 0.25
|
size_flags_stretch_ratio = 0.25
|
||||||
|
|
||||||
[node name="Create" type="Button" parent="Multiplayer/MarginContainer/TabContainer/Profile/MarginContainer/HBoxContainer/LeftBox"]
|
[node name="Top" type="VBoxContainer" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Profile/MarginContainer/HBoxContainer/LeftBox"]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 10
|
||||||
|
anchor_right = 1.0
|
||||||
|
offset_bottom = 101.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_stretch_ratio = 0.25
|
||||||
|
|
||||||
|
[node name="Create" type="Button" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Profile/MarginContainer/HBoxContainer/LeftBox/Top"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
disabled = true
|
disabled = true
|
||||||
text = "Create"
|
text = "Create"
|
||||||
|
|
||||||
[node name="Delete" type="Button" parent="Multiplayer/MarginContainer/TabContainer/Profile/MarginContainer/HBoxContainer/LeftBox"]
|
[node name="Delete" type="Button" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Profile/MarginContainer/HBoxContainer/LeftBox/Top"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
disabled = true
|
disabled = true
|
||||||
text = "Delete"
|
text = "Delete"
|
||||||
|
|
||||||
[node name="Spacer" type="MarginContainer" parent="Multiplayer/MarginContainer/TabContainer/Profile/MarginContainer/HBoxContainer/LeftBox"]
|
[node name="Save" type="Button" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Profile/MarginContainer/HBoxContainer/LeftBox/Top"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_vertical = 3
|
text = "Save"
|
||||||
|
|
||||||
[node name="Menu" type="Button" parent="Multiplayer/MarginContainer/TabContainer/Profile/MarginContainer/HBoxContainer/LeftBox"]
|
[node name="Bottom" type="VBoxContainer" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Profile/MarginContainer/HBoxContainer/LeftBox"]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 12
|
||||||
|
anchor_top = 1.0
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_top = -31.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 0
|
||||||
|
size_flags_horizontal = 0
|
||||||
|
|
||||||
|
[node name="MainMenu" type="Button" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Profile/MarginContainer/HBoxContainer/LeftBox/Bottom"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Menu
|
size_flags_horizontal = 3
|
||||||
|
text = "Main Menu
|
||||||
"
|
"
|
||||||
|
|
||||||
[node name="Quit" type="Button" parent="Multiplayer/MarginContainer/TabContainer/Profile/MarginContainer/HBoxContainer/LeftBox"]
|
[node name="Quit" type="Button" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Profile/MarginContainer/HBoxContainer/LeftBox/Bottom"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
text = "Quit"
|
text = "Quit"
|
||||||
|
|
||||||
[node name="RightBox" type="VBoxContainer" parent="Multiplayer/MarginContainer/TabContainer/Profile/MarginContainer/HBoxContainer"]
|
[node name="RightBox" type="VBoxContainer" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Profile/MarginContainer/HBoxContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="Multiplayer/MarginContainer/TabContainer/Profile/MarginContainer/HBoxContainer/RightBox"]
|
[node name="Label" type="Label" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Profile/MarginContainer/HBoxContainer/RightBox"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Current Profile:"
|
text = "Current Profile:"
|
||||||
|
|
||||||
[node name="ProfileName" type="LineEdit" parent="Multiplayer/MarginContainer/TabContainer/Profile/MarginContainer/HBoxContainer/RightBox"]
|
[node name="ProfileName" type="LineEdit" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Profile/MarginContainer/HBoxContainer/RightBox"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
text = "Newblood"
|
text = "Newblood"
|
||||||
|
|
||||||
[node name="Join" type="TabBar" parent="Multiplayer/MarginContainer/TabContainer"]
|
[node name="Join" type="TabBar" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer"]
|
||||||
visible = false
|
visible = false
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
select_with_rmb = true
|
select_with_rmb = true
|
||||||
|
|
||||||
[node name="MarginContainer" type="MarginContainer" parent="Multiplayer/MarginContainer/TabContainer/Join"]
|
[node name="MarginContainer" type="MarginContainer" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Join"]
|
||||||
layout_mode = 1
|
layout_mode = 1
|
||||||
anchors_preset = 15
|
anchors_preset = 15
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
|
|
@ -200,47 +283,65 @@ theme_override_constants/margin_top = 20
|
||||||
theme_override_constants/margin_right = 20
|
theme_override_constants/margin_right = 20
|
||||||
theme_override_constants/margin_bottom = 20
|
theme_override_constants/margin_bottom = 20
|
||||||
|
|
||||||
[node name="HBoxContainer" type="HBoxContainer" parent="Multiplayer/MarginContainer/TabContainer/Join/MarginContainer"]
|
[node name="HBoxContainer" type="HBoxContainer" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Join/MarginContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
theme_override_constants/separation = 10
|
theme_override_constants/separation = 10
|
||||||
|
|
||||||
[node name="LeftBox" type="VBoxContainer" parent="Multiplayer/MarginContainer/TabContainer/Join/MarginContainer/HBoxContainer"]
|
[node name="LeftBox" type="Control" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Join/MarginContainer/HBoxContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
size_flags_stretch_ratio = 0.25
|
size_flags_stretch_ratio = 0.25
|
||||||
|
|
||||||
[node name="Join" type="Button" parent="Multiplayer/MarginContainer/TabContainer/Join/MarginContainer/HBoxContainer/LeftBox"]
|
[node name="Top" type="VBoxContainer" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Join/MarginContainer/HBoxContainer/LeftBox"]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 10
|
||||||
|
anchor_right = 1.0
|
||||||
|
offset_bottom = 101.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_stretch_ratio = 0.25
|
||||||
|
|
||||||
|
[node name="Join" type="Button" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Join/MarginContainer/HBoxContainer/LeftBox/Top"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Join"
|
text = "Join"
|
||||||
|
|
||||||
[node name="Spacer" type="MarginContainer" parent="Multiplayer/MarginContainer/TabContainer/Join/MarginContainer/HBoxContainer/LeftBox"]
|
[node name="Bottom" type="VBoxContainer" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Join/MarginContainer/HBoxContainer/LeftBox"]
|
||||||
layout_mode = 2
|
layout_mode = 1
|
||||||
size_flags_vertical = 3
|
anchors_preset = 12
|
||||||
|
anchor_top = 1.0
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_top = -31.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 0
|
||||||
|
size_flags_horizontal = 0
|
||||||
|
|
||||||
[node name="Menu" type="Button" parent="Multiplayer/MarginContainer/TabContainer/Join/MarginContainer/HBoxContainer/LeftBox"]
|
[node name="MainMenu" type="Button" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Join/MarginContainer/HBoxContainer/LeftBox/Bottom"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Menu
|
size_flags_horizontal = 3
|
||||||
|
text = "Main Menu
|
||||||
"
|
"
|
||||||
|
|
||||||
[node name="Quit" type="Button" parent="Multiplayer/MarginContainer/TabContainer/Join/MarginContainer/HBoxContainer/LeftBox"]
|
[node name="Quit" type="Button" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Join/MarginContainer/HBoxContainer/LeftBox/Bottom"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
text = "Quit"
|
text = "Quit"
|
||||||
|
|
||||||
[node name="RightBox" type="VBoxContainer" parent="Multiplayer/MarginContainer/TabContainer/Join/MarginContainer/HBoxContainer"]
|
[node name="RightBox" type="VBoxContainer" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Join/MarginContainer/HBoxContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
[node name="JoinAddress" type="LineEdit" parent="Multiplayer/MarginContainer/TabContainer/Join/MarginContainer/HBoxContainer/RightBox"]
|
[node name="JoinAddress" type="LineEdit" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Join/MarginContainer/HBoxContainer/RightBox"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
placeholder_text = "localhost"
|
placeholder_text = "localhost"
|
||||||
|
|
||||||
[node name="Host" type="TabBar" parent="Multiplayer/MarginContainer/TabContainer"]
|
[node name="Host" type="TabBar" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer"]
|
||||||
visible = false
|
visible = false
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
select_with_rmb = true
|
select_with_rmb = true
|
||||||
|
|
||||||
[node name="MarginContainer" type="MarginContainer" parent="Multiplayer/MarginContainer/TabContainer/Host"]
|
[node name="MarginContainer" type="MarginContainer" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Host"]
|
||||||
layout_mode = 1
|
layout_mode = 1
|
||||||
anchors_preset = 15
|
anchors_preset = 15
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
|
|
@ -252,37 +353,55 @@ theme_override_constants/margin_top = 20
|
||||||
theme_override_constants/margin_right = 20
|
theme_override_constants/margin_right = 20
|
||||||
theme_override_constants/margin_bottom = 20
|
theme_override_constants/margin_bottom = 20
|
||||||
|
|
||||||
[node name="HBoxContainer" type="HBoxContainer" parent="Multiplayer/MarginContainer/TabContainer/Host/MarginContainer"]
|
[node name="HBoxContainer" type="HBoxContainer" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Host/MarginContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
theme_override_constants/separation = 10
|
theme_override_constants/separation = 10
|
||||||
|
|
||||||
[node name="LeftBox" type="VBoxContainer" parent="Multiplayer/MarginContainer/TabContainer/Host/MarginContainer/HBoxContainer"]
|
[node name="LeftBox" type="Control" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Host/MarginContainer/HBoxContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
size_flags_stretch_ratio = 0.25
|
size_flags_stretch_ratio = 0.25
|
||||||
|
|
||||||
[node name="Host" type="Button" parent="Multiplayer/MarginContainer/TabContainer/Host/MarginContainer/HBoxContainer/LeftBox"]
|
[node name="Top" type="VBoxContainer" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Host/MarginContainer/HBoxContainer/LeftBox"]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 10
|
||||||
|
anchor_right = 1.0
|
||||||
|
offset_bottom = 101.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_stretch_ratio = 0.25
|
||||||
|
|
||||||
|
[node name="Host" type="Button" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Host/MarginContainer/HBoxContainer/LeftBox/Top"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Host"
|
text = "Host"
|
||||||
|
|
||||||
[node name="Spacer" type="MarginContainer" parent="Multiplayer/MarginContainer/TabContainer/Host/MarginContainer/HBoxContainer/LeftBox"]
|
[node name="Bottom" type="VBoxContainer" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Host/MarginContainer/HBoxContainer/LeftBox"]
|
||||||
layout_mode = 2
|
layout_mode = 1
|
||||||
size_flags_vertical = 3
|
anchors_preset = 12
|
||||||
|
anchor_top = 1.0
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_top = -66.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 0
|
||||||
|
size_flags_horizontal = 0
|
||||||
|
|
||||||
[node name="Menu" type="Button" parent="Multiplayer/MarginContainer/TabContainer/Host/MarginContainer/HBoxContainer/LeftBox"]
|
[node name="MainMenu" type="Button" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Host/MarginContainer/HBoxContainer/LeftBox/Bottom"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Menu
|
size_flags_horizontal = 3
|
||||||
|
text = "Main Menu
|
||||||
"
|
"
|
||||||
|
|
||||||
[node name="Quit" type="Button" parent="Multiplayer/MarginContainer/TabContainer/Host/MarginContainer/HBoxContainer/LeftBox"]
|
[node name="Quit" type="Button" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Host/MarginContainer/HBoxContainer/LeftBox/Bottom"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
text = "Quit"
|
text = "Quit"
|
||||||
|
|
||||||
[node name="RightBox" type="VBoxContainer" parent="Multiplayer/MarginContainer/TabContainer/Host/MarginContainer/HBoxContainer"]
|
[node name="RightBox" type="VBoxContainer" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Host/MarginContainer/HBoxContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
[node name="ServerPort" type="LineEdit" parent="Multiplayer/MarginContainer/TabContainer/Host/MarginContainer/HBoxContainer/RightBox"]
|
[node name="ServerPort" type="LineEdit" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Host/MarginContainer/HBoxContainer/RightBox"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
placeholder_text = "9000"
|
placeholder_text = "9000"
|
||||||
|
|
@ -306,51 +425,250 @@ grow_horizontal = 2
|
||||||
grow_vertical = 2
|
grow_vertical = 2
|
||||||
text = "CONNECTING..."
|
text = "CONNECTING..."
|
||||||
|
|
||||||
[node name="Main" type="PanelContainer" parent="."]
|
[node name="Settings" type="PanelContainer" parent="." node_paths=PackedStringArray("tab_container")]
|
||||||
anchors_preset = 9
|
visible = false
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
offset_right = 313.0
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_ky5sv")
|
||||||
|
script = SubResource("GDScript_gbnwv")
|
||||||
|
tab_container = NodePath("MarginContainer/VBoxContainer/TabContainer")
|
||||||
|
|
||||||
|
[node name="MarginContainer" type="MarginContainer" parent="Settings"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_constants/margin_left = 20
|
||||||
|
theme_override_constants/margin_top = 20
|
||||||
|
theme_override_constants/margin_right = 20
|
||||||
|
theme_override_constants/margin_bottom = 20
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="Settings/MarginContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="TabContainer" type="TabContainer" parent="Settings/MarginContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
theme_override_constants/side_margin = 0
|
||||||
|
|
||||||
|
[node name="Gameplay" type="TabBar" parent="Settings/MarginContainer/VBoxContainer/TabContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_constants/h_separation = 0
|
||||||
|
|
||||||
|
[node name="MarginContainer" type="MarginContainer" parent="Settings/MarginContainer/VBoxContainer/TabContainer/Gameplay"]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
theme_override_constants/margin_left = 20
|
||||||
|
theme_override_constants/margin_top = 20
|
||||||
|
theme_override_constants/margin_right = 20
|
||||||
|
theme_override_constants/margin_bottom = 20
|
||||||
|
|
||||||
|
[node name="GridContainer" type="GridContainer" parent="Settings/MarginContainer/VBoxContainer/TabContainer/Gameplay/MarginContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
columns = 2
|
||||||
|
|
||||||
|
[node name="FOVLabel" type="Label" parent="Settings/MarginContainer/VBoxContainer/TabContainer/Gameplay/MarginContainer/GridContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Field of view"
|
||||||
|
|
||||||
|
[node name="FOVSpinBox" type="SpinBox" parent="Settings/MarginContainer/VBoxContainer/TabContainer/Gameplay/MarginContainer/GridContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
min_value = 60.0
|
||||||
|
max_value = 120.0
|
||||||
|
value = 60.0
|
||||||
|
|
||||||
|
[node name="SensitivityLabel" type="Label" parent="Settings/MarginContainer/VBoxContainer/TabContainer/Gameplay/MarginContainer/GridContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Mouse sensitivity"
|
||||||
|
|
||||||
|
[node name="SensitivitySpinBox" type="SpinBox" parent="Settings/MarginContainer/VBoxContainer/TabContainer/Gameplay/MarginContainer/GridContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
max_value = 1.0
|
||||||
|
step = 0.01
|
||||||
|
value = 1.0
|
||||||
|
|
||||||
|
[node name="InvertedYLabel" type="Label" parent="Settings/MarginContainer/VBoxContainer/TabContainer/Gameplay/MarginContainer/GridContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Inverted Y"
|
||||||
|
|
||||||
|
[node name="InvertedYCheckbox" type="CheckBox" parent="Settings/MarginContainer/VBoxContainer/TabContainer/Gameplay/MarginContainer/GridContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Buttons" type="HBoxContainer" parent="Settings/MarginContainer/VBoxContainer/TabContainer/Gameplay/MarginContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 8
|
||||||
|
|
||||||
|
[node name="Bottom" type="VBoxContainer" parent="Settings/MarginContainer/VBoxContainer/TabContainer/Gameplay/MarginContainer/Buttons"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_stretch_ratio = 0.2
|
||||||
|
|
||||||
|
[node name="Save" type="Button" parent="Settings/MarginContainer/VBoxContainer/TabContainer/Gameplay/MarginContainer/Buttons/Bottom"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Save
|
||||||
|
"
|
||||||
|
|
||||||
|
[node name="MainMenu" type="Button" parent="Settings/MarginContainer/VBoxContainer/TabContainer/Gameplay/MarginContainer/Buttons/Bottom"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = "Main Menu
|
||||||
|
"
|
||||||
|
|
||||||
|
[node name="Quit" type="Button" parent="Settings/MarginContainer/VBoxContainer/TabContainer/Gameplay/MarginContainer/Buttons/Bottom"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = "Quit"
|
||||||
|
|
||||||
|
[node name="Spacer" type="Control" parent="Settings/MarginContainer/VBoxContainer/TabContainer/Gameplay/MarginContainer/Buttons"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_stretch_ratio = 0.8
|
||||||
|
|
||||||
|
[node name="Graphics" type="TabBar" parent="Settings/MarginContainer/VBoxContainer/TabContainer"]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
select_with_rmb = true
|
||||||
|
|
||||||
|
[node name="MarginContainer" type="MarginContainer" parent="Settings/MarginContainer/VBoxContainer/TabContainer/Graphics"]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
theme_override_constants/margin_left = 20
|
||||||
|
theme_override_constants/margin_top = 20
|
||||||
|
theme_override_constants/margin_right = 20
|
||||||
|
theme_override_constants/margin_bottom = 20
|
||||||
|
|
||||||
|
[node name="GridContainer" type="GridContainer" parent="Settings/MarginContainer/VBoxContainer/TabContainer/Graphics/MarginContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
columns = 2
|
||||||
|
|
||||||
|
[node name="WindowModeLabel" type="Label" parent="Settings/MarginContainer/VBoxContainer/TabContainer/Graphics/MarginContainer/GridContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Window mode"
|
||||||
|
|
||||||
|
[node name="WindowModeOptionButton" type="OptionButton" parent="Settings/MarginContainer/VBoxContainer/TabContainer/Graphics/MarginContainer/GridContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
item_count = 2
|
||||||
|
selected = 0
|
||||||
|
popup/item_0/text = "Windowed"
|
||||||
|
popup/item_0/id = 0
|
||||||
|
popup/item_1/text = "Fullscreen"
|
||||||
|
popup/item_1/id = 1
|
||||||
|
|
||||||
|
[node name="Buttons" type="HBoxContainer" parent="Settings/MarginContainer/VBoxContainer/TabContainer/Graphics/MarginContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 8
|
||||||
|
|
||||||
|
[node name="Bottom" type="VBoxContainer" parent="Settings/MarginContainer/VBoxContainer/TabContainer/Graphics/MarginContainer/Buttons"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_stretch_ratio = 0.2
|
||||||
|
|
||||||
|
[node name="Save" type="Button" parent="Settings/MarginContainer/VBoxContainer/TabContainer/Graphics/MarginContainer/Buttons/Bottom"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Save
|
||||||
|
"
|
||||||
|
|
||||||
|
[node name="MainMenu" type="Button" parent="Settings/MarginContainer/VBoxContainer/TabContainer/Graphics/MarginContainer/Buttons/Bottom"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = "Main Menu
|
||||||
|
"
|
||||||
|
|
||||||
|
[node name="Quit" type="Button" parent="Settings/MarginContainer/VBoxContainer/TabContainer/Graphics/MarginContainer/Buttons/Bottom"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = "Quit"
|
||||||
|
|
||||||
|
[node name="Spacer" type="Control" parent="Settings/MarginContainer/VBoxContainer/TabContainer/Graphics/MarginContainer/Buttons"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_stretch_ratio = 0.8
|
||||||
|
|
||||||
|
[node name="Main" type="PanelContainer" parent="."]
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
grow_vertical = 2
|
grow_vertical = 2
|
||||||
size_flags_horizontal = 0
|
size_flags_horizontal = 0
|
||||||
theme_override_styles/panel = SubResource("StyleBoxFlat_snh7i")
|
theme_override_styles/panel = SubResource("StyleBoxFlat_c4ymk")
|
||||||
script = SubResource("GDScript_yqbr7")
|
|
||||||
|
|
||||||
[node name="MarginContainer" type="MarginContainer" parent="Main"]
|
[node name="HBoxContainer" type="HBoxContainer" parent="Main"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="PanelContainer" type="PanelContainer" parent="Main/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_stretch_ratio = 0.3
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_dq4me")
|
||||||
|
|
||||||
|
[node name="MarginContainer" type="MarginContainer" parent="Main/HBoxContainer/PanelContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
theme_override_constants/margin_left = 20
|
theme_override_constants/margin_left = 20
|
||||||
theme_override_constants/margin_right = 20
|
theme_override_constants/margin_right = 20
|
||||||
|
|
||||||
[node name="VBoxContainer" type="VBoxContainer" parent="Main/MarginContainer"]
|
[node name="VBoxContainer" type="VBoxContainer" parent="Main/HBoxContainer/PanelContainer/MarginContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
theme_override_constants/separation = 10
|
theme_override_constants/separation = 10
|
||||||
alignment = 1
|
alignment = 1
|
||||||
|
|
||||||
[node name="Demo" type="Button" parent="Main/MarginContainer/VBoxContainer"]
|
[node name="Demo" type="Button" parent="Main/HBoxContainer/PanelContainer/MarginContainer/VBoxContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
theme_override_font_sizes/font_size = 32
|
theme_override_font_sizes/font_size = 32
|
||||||
text = "Demo"
|
text = "Demo"
|
||||||
|
|
||||||
[node name="Multiplayer" type="Button" parent="Main/MarginContainer/VBoxContainer"]
|
[node name="Multiplayer" type="Button" parent="Main/HBoxContainer/PanelContainer/MarginContainer/VBoxContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
theme_override_font_sizes/font_size = 32
|
theme_override_font_sizes/font_size = 32
|
||||||
text = "Multiplayer"
|
text = "Multiplayer"
|
||||||
|
|
||||||
[node name="Quit" type="Button" parent="Main/MarginContainer/VBoxContainer"]
|
[node name="Settings" type="Button" parent="Main/HBoxContainer/PanelContainer/MarginContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_font_sizes/font_size = 32
|
||||||
|
text = "Settings"
|
||||||
|
|
||||||
|
[node name="Quit" type="Button" parent="Main/HBoxContainer/PanelContainer/MarginContainer/VBoxContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
theme_override_font_sizes/font_size = 32
|
theme_override_font_sizes/font_size = 32
|
||||||
text = "Quit"
|
text = "Quit"
|
||||||
|
|
||||||
|
[node name="Control" type="Control" parent="Main/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_stretch_ratio = 0.8
|
||||||
|
|
||||||
[connection signal="join_server" from="Multiplayer" to="." method="_on_multiplayer_join_server"]
|
[connection signal="join_server" from="Multiplayer" to="." method="_on_multiplayer_join_server"]
|
||||||
[connection signal="start_server" from="Multiplayer" to="." method="_on_multiplayer_start_server"]
|
[connection signal="start_server" from="Multiplayer" to="." method="_on_multiplayer_start_server"]
|
||||||
[connection signal="pressed" from="Multiplayer/MarginContainer/TabContainer/Profile/MarginContainer/HBoxContainer/LeftBox/Menu" to="Multiplayer" method="_on_menu_pressed"]
|
[connection signal="pressed" from="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Profile/MarginContainer/HBoxContainer/LeftBox/Top/Save" to="Multiplayer" method="_on_save_pressed"]
|
||||||
[connection signal="pressed" from="Multiplayer/MarginContainer/TabContainer/Profile/MarginContainer/HBoxContainer/LeftBox/Quit" to="Multiplayer" method="_on_quit_pressed"]
|
[connection signal="pressed" from="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Profile/MarginContainer/HBoxContainer/LeftBox/Bottom/MainMenu" to="." method="_on_main_menu_pressed"]
|
||||||
[connection signal="pressed" from="Multiplayer/MarginContainer/TabContainer/Join/MarginContainer/HBoxContainer/LeftBox/Join" to="Multiplayer" method="_on_join_pressed"]
|
[connection signal="pressed" from="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Profile/MarginContainer/HBoxContainer/LeftBox/Bottom/Quit" to="." method="_on_quit_pressed"]
|
||||||
[connection signal="pressed" from="Multiplayer/MarginContainer/TabContainer/Join/MarginContainer/HBoxContainer/LeftBox/Menu" to="Multiplayer" method="_on_menu_pressed"]
|
[connection signal="pressed" from="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Join/MarginContainer/HBoxContainer/LeftBox/Top/Join" to="Multiplayer" method="_on_join_pressed"]
|
||||||
[connection signal="pressed" from="Multiplayer/MarginContainer/TabContainer/Join/MarginContainer/HBoxContainer/LeftBox/Quit" to="Multiplayer" method="_on_quit_pressed"]
|
[connection signal="pressed" from="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Join/MarginContainer/HBoxContainer/LeftBox/Bottom/MainMenu" to="." method="_on_main_menu_pressed"]
|
||||||
[connection signal="pressed" from="Multiplayer/MarginContainer/TabContainer/Host/MarginContainer/HBoxContainer/LeftBox/Host" to="Multiplayer" method="_on_host_pressed"]
|
[connection signal="pressed" from="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Join/MarginContainer/HBoxContainer/LeftBox/Bottom/Quit" to="." method="_on_quit_pressed"]
|
||||||
[connection signal="pressed" from="Multiplayer/MarginContainer/TabContainer/Host/MarginContainer/HBoxContainer/LeftBox/Menu" to="Multiplayer" method="_on_menu_pressed"]
|
[connection signal="pressed" from="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Host/MarginContainer/HBoxContainer/LeftBox/Top/Host" to="Multiplayer" method="_on_host_pressed"]
|
||||||
[connection signal="pressed" from="Multiplayer/MarginContainer/TabContainer/Host/MarginContainer/HBoxContainer/LeftBox/Quit" to="Multiplayer" method="_on_quit_pressed"]
|
[connection signal="pressed" from="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Host/MarginContainer/HBoxContainer/LeftBox/Bottom/MainMenu" to="." method="_on_main_menu_pressed"]
|
||||||
[connection signal="text_changed" from="Multiplayer/MarginContainer/TabContainer/Host/MarginContainer/HBoxContainer/RightBox/ServerPort" to="Multiplayer/MarginContainer/TabContainer/Host/MarginContainer/HBoxContainer/RightBox/ServerPort" method="_on_text_changed"]
|
[connection signal="pressed" from="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Host/MarginContainer/HBoxContainer/LeftBox/Bottom/Quit" to="." method="_on_quit_pressed"]
|
||||||
[connection signal="pressed" from="Main/MarginContainer/VBoxContainer/Demo" to="." method="_on_demo_pressed"]
|
[connection signal="text_changed" from="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Host/MarginContainer/HBoxContainer/RightBox/ServerPort" to="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Host/MarginContainer/HBoxContainer/RightBox/ServerPort" method="_on_text_changed"]
|
||||||
[connection signal="pressed" from="Main/MarginContainer/VBoxContainer/Multiplayer" to="Main" method="_on_multiplayer_pressed"]
|
[connection signal="pressed" from="Settings/MarginContainer/VBoxContainer/TabContainer/Gameplay/MarginContainer/Buttons/Bottom/Save" to="Settings" method="_on_save_pressed"]
|
||||||
[connection signal="pressed" from="Main/MarginContainer/VBoxContainer/Quit" to="Main" method="_on_quit_pressed"]
|
[connection signal="pressed" from="Settings/MarginContainer/VBoxContainer/TabContainer/Gameplay/MarginContainer/Buttons/Bottom/MainMenu" to="." method="_on_main_menu_pressed"]
|
||||||
|
[connection signal="pressed" from="Settings/MarginContainer/VBoxContainer/TabContainer/Gameplay/MarginContainer/Buttons/Bottom/Quit" to="." method="_on_quit_pressed"]
|
||||||
|
[connection signal="pressed" from="Settings/MarginContainer/VBoxContainer/TabContainer/Graphics/MarginContainer/Buttons/Bottom/Save" to="Settings" method="_on_save_pressed"]
|
||||||
|
[connection signal="pressed" from="Settings/MarginContainer/VBoxContainer/TabContainer/Graphics/MarginContainer/Buttons/Bottom/MainMenu" to="." method="_on_main_menu_pressed"]
|
||||||
|
[connection signal="pressed" from="Settings/MarginContainer/VBoxContainer/TabContainer/Graphics/MarginContainer/Buttons/Bottom/Quit" to="." method="_on_quit_pressed"]
|
||||||
|
[connection signal="pressed" from="Main/HBoxContainer/PanelContainer/MarginContainer/VBoxContainer/Demo" to="." method="_on_demo_pressed"]
|
||||||
|
[connection signal="pressed" from="Main/HBoxContainer/PanelContainer/MarginContainer/VBoxContainer/Multiplayer" to="." method="_on_multiplayer_pressed"]
|
||||||
|
[connection signal="pressed" from="Main/HBoxContainer/PanelContainer/MarginContainer/VBoxContainer/Settings" to="." method="_on_settings_pressed"]
|
||||||
|
[connection signal="pressed" from="Main/HBoxContainer/PanelContainer/MarginContainer/VBoxContainer/Quit" to="." method="_on_quit_pressed"]
|
||||||
|
|
|
||||||
47
main.tscn
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[ext_resource type="PackedScene" uid="uid://boviiugcnfyrj" path="res://modes/demo.tscn" id="1_50a80"]
|
[ext_resource type="PackedScene" uid="uid://boviiugcnfyrj" path="res://modes/demo.tscn" id="1_50a80"]
|
||||||
[ext_resource type="PackedScene" uid="uid://bjctlqvs33nqy" path="res://interfaces/menus/boot/boot.tscn" id="1_acy5o"]
|
[ext_resource type="PackedScene" uid="uid://bjctlqvs33nqy" path="res://interfaces/menus/boot/boot.tscn" id="1_acy5o"]
|
||||||
[ext_resource type="PackedScene" uid="uid://c7ae4jw5d8mue" path="res://modes/multiplayer.tscn" id="2_g8xeb"]
|
[ext_resource type="PackedScene" uid="uid://bvwxfgygm2xb8" path="res://modes/multiplayer.tscn" id="2_g8xeb"]
|
||||||
|
|
||||||
[sub_resource type="GDScript" id="GDScript_e61dq"]
|
[sub_resource type="GDScript" id="GDScript_e61dq"]
|
||||||
script/source = "class_name Game extends Node3D
|
script/source = "class_name Game extends Node3D
|
||||||
|
|
@ -13,43 +13,50 @@ script/source = "class_name Game extends Node3D
|
||||||
|
|
||||||
var mode : Node
|
var mode : Node
|
||||||
|
|
||||||
func _ready():
|
func _ready() -> void:
|
||||||
$BootMenu.start_demo.connect(_start_demo)
|
$BootMenu.start_demo.connect(_start_demo)
|
||||||
$BootMenu/Multiplayer.start_server.connect(_start_server)
|
$BootMenu/Multiplayer.start_server.connect(_start_server)
|
||||||
$BootMenu/Multiplayer.join_server.connect(_join_server)
|
$BootMenu/Multiplayer.join_server.connect(_join_server)
|
||||||
|
|
||||||
func _start_demo():
|
func _start_demo() -> void:
|
||||||
if mode: mode.queue_free()
|
_set_game_mode(SINGLEPLAYER.instantiate())
|
||||||
mode = SINGLEPLAYER.instantiate() # demo scene
|
|
||||||
add_child(mode)
|
|
||||||
$BootMenu.hide()
|
$BootMenu.hide()
|
||||||
|
|
||||||
func _start_server(port):
|
func _start_server(port : int, nickname : String) -> void:
|
||||||
if mode: mode.queue_free()
|
_set_game_mode(MULTIPLAYER.instantiate())
|
||||||
mode = MULTIPLAYER.instantiate() # server scene
|
mode.start_server(port, nickname)
|
||||||
add_child(mode)
|
|
||||||
mode.start_server(port)
|
|
||||||
$BootMenu.hide()
|
$BootMenu.hide()
|
||||||
|
|
||||||
func _join_server(host, port):
|
func _join_server(host : String, port : int, nickname : String) -> void:
|
||||||
if mode: mode.queue_free()
|
_set_game_mode(MULTIPLAYER.instantiate())
|
||||||
mode = MULTIPLAYER.instantiate() # client scene
|
|
||||||
add_child(mode)
|
|
||||||
mode.connected_to_server.connect($BootMenu/Multiplayer._on_connected_to_server)
|
mode.connected_to_server.connect($BootMenu/Multiplayer._on_connected_to_server)
|
||||||
mode.connection_failed.connect($BootMenu/Multiplayer._on_connection_failed)
|
mode.connection_failed.connect($BootMenu/Multiplayer._on_connection_failed)
|
||||||
mode.join_server(host, port)
|
mode.join_server(host, port, nickname)
|
||||||
|
|
||||||
func _unhandled_input(event):
|
func _input(event : InputEvent) -> void:
|
||||||
# exit the program
|
|
||||||
if event.is_action_pressed(\"exit\"):
|
if event.is_action_pressed(\"exit\"):
|
||||||
get_tree().quit()
|
_set_game_mode(null)
|
||||||
|
multiplayer.multiplayer_peer.close()
|
||||||
|
$BootMenu.show()
|
||||||
|
|
||||||
|
func _set_game_mode(new_mode : Node) -> void:
|
||||||
|
if mode != null:
|
||||||
|
remove_child(mode)
|
||||||
|
mode.queue_free()
|
||||||
|
mode = new_mode
|
||||||
|
if mode == null:
|
||||||
|
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
|
||||||
|
else:
|
||||||
|
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
||||||
|
add_child(mode)
|
||||||
|
|
||||||
|
func _unhandled_input(event : InputEvent) -> void:
|
||||||
# switch window mode
|
# switch window mode
|
||||||
if event.is_action_pressed(\"window_mode\"):
|
if event.is_action_pressed(\"window_mode\"):
|
||||||
if DisplayServer.window_get_mode() == DisplayServer.WINDOW_MODE_FULLSCREEN:
|
if DisplayServer.window_get_mode() == DisplayServer.WINDOW_MODE_FULLSCREEN:
|
||||||
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
|
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
|
||||||
else:
|
else:
|
||||||
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
|
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
|
||||||
|
|
||||||
# switch mouse mode
|
# switch mouse mode
|
||||||
if OS.is_debug_build() and Input.is_action_just_pressed(\"toggle_mouse_capture\"):
|
if OS.is_debug_build() and Input.is_action_just_pressed(\"toggle_mouse_capture\"):
|
||||||
if Input.mouse_mode == Input.MOUSE_MODE_VISIBLE:
|
if Input.mouse_mode == Input.MOUSE_MODE_VISIBLE:
|
||||||
|
|
|
||||||
22
maps/desert/desert.tscn
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
[gd_scene load_steps=5 format=3 uid="uid://btlkog4b87p4x"]
|
||||||
|
|
||||||
|
[ext_resource type="Terrain3DStorage" uid="uid://wgmg245njt8e" path="res://maps/desert/resources/storage.res" id="1_7nbyj"]
|
||||||
|
[ext_resource type="Environment" uid="uid://nw62ce5cglvs" path="res://environments/desert.tres" id="1_e1o3u"]
|
||||||
|
[ext_resource type="Terrain3DMaterial" uid="uid://c3isipd4wqxpk" path="res://maps/desert/resources/material.tres" id="2_psdr0"]
|
||||||
|
[ext_resource type="Terrain3DTextureList" uid="uid://d1j24k8sq8qpj" path="res://maps/desert/resources/textures.tres" id="3_aowug"]
|
||||||
|
|
||||||
|
[node name="Desert" type="Node3D"]
|
||||||
|
|
||||||
|
[node name="Sunlight" type="DirectionalLight3D" parent="."]
|
||||||
|
transform = Transform3D(0.5, 0.55667, -0.663414, 0, 0.766044, 0.642788, 0.866025, -0.321394, 0.383022, -1613.38, 2730.74, 446.64)
|
||||||
|
shadow_enabled = true
|
||||||
|
|
||||||
|
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||||
|
environment = ExtResource("1_e1o3u")
|
||||||
|
|
||||||
|
[node name="Terrain3D" type="Terrain3D" parent="."]
|
||||||
|
storage = ExtResource("1_7nbyj")
|
||||||
|
material = ExtResource("2_psdr0")
|
||||||
|
texture_list = ExtResource("3_aowug")
|
||||||
|
collision_layer = 2147483648
|
||||||
|
collision_mask = 2147483648
|
||||||
58
maps/desert/resources/material.tres
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
[gd_resource type="Terrain3DMaterial" load_steps=4 format=3 uid="uid://c3isipd4wqxpk"]
|
||||||
|
|
||||||
|
[sub_resource type="Gradient" id="Gradient_rr0fn"]
|
||||||
|
offsets = PackedFloat32Array(0.2, 1)
|
||||||
|
colors = PackedColorArray(1, 1, 1, 1, 0, 0, 0, 1)
|
||||||
|
|
||||||
|
[sub_resource type="FastNoiseLite" id="FastNoiseLite_e3unr"]
|
||||||
|
noise_type = 2
|
||||||
|
frequency = 0.03
|
||||||
|
cellular_jitter = 3.0
|
||||||
|
cellular_return_type = 0
|
||||||
|
domain_warp_enabled = true
|
||||||
|
domain_warp_type = 1
|
||||||
|
domain_warp_amplitude = 50.0
|
||||||
|
domain_warp_fractal_type = 2
|
||||||
|
domain_warp_fractal_lacunarity = 1.5
|
||||||
|
domain_warp_fractal_gain = 1.0
|
||||||
|
|
||||||
|
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_esvkc"]
|
||||||
|
seamless = true
|
||||||
|
color_ramp = SubResource("Gradient_rr0fn")
|
||||||
|
noise = SubResource("FastNoiseLite_e3unr")
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
_shader_parameters = {
|
||||||
|
"_mouse_layer": 2147483648,
|
||||||
|
"auto_base_texture": 0,
|
||||||
|
"auto_height_reduction": 0.085,
|
||||||
|
"auto_overlay_texture": 1,
|
||||||
|
"auto_slope": 1.0,
|
||||||
|
"blend_sharpness": 0.85,
|
||||||
|
"dual_scale_far": 350.0,
|
||||||
|
"dual_scale_near": 0.0,
|
||||||
|
"dual_scale_reduction": 1.0,
|
||||||
|
"dual_scale_texture": 1,
|
||||||
|
"height_blending": true,
|
||||||
|
"macro_variation1": Color(1, 1, 1, 1),
|
||||||
|
"macro_variation2": Color(0.968627, 0.929412, 0.905882, 1),
|
||||||
|
"noise1_angle": 0.0,
|
||||||
|
"noise1_offset": Vector2(0.5, 0.5),
|
||||||
|
"noise1_scale": 0.4,
|
||||||
|
"noise2_scale": 0.5,
|
||||||
|
"noise3_scale": 0.225,
|
||||||
|
"noise_texture": SubResource("NoiseTexture2D_esvkc"),
|
||||||
|
"tri_scale_reduction": 0.075,
|
||||||
|
"world_noise_blend_far": 1.0,
|
||||||
|
"world_noise_blend_near": 0.75,
|
||||||
|
"world_noise_height": 40.0,
|
||||||
|
"world_noise_lod_distance": 500.0,
|
||||||
|
"world_noise_max_octaves": 6,
|
||||||
|
"world_noise_min_octaves": 5,
|
||||||
|
"world_noise_offset": Vector3(0, 0, 0),
|
||||||
|
"world_noise_scale": 7.5
|
||||||
|
}
|
||||||
|
world_background = 2
|
||||||
|
texture_filtering = 1
|
||||||
|
auto_shader = true
|
||||||
|
dual_scaling = true
|
||||||
BIN
maps/desert/resources/storage.res
Normal file
24
maps/desert/resources/textures.tres
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
[gd_resource type="Terrain3DTextureList" load_steps=7 format=3 uid="uid://d1j24k8sq8qpj"]
|
||||||
|
|
||||||
|
[ext_resource type="Texture2D" uid="uid://cngjywcua4vv8" path="res://maps/desert/textures/ground054_alb_ht.png" id="1_rh7of"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://cbk7l6hs0yrcc" path="res://maps/desert/textures/ground054_nrm_rgh.png" id="2_xt1tc"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://dwk8islw7ebab" path="res://maps/desert/textures/rock029_alb_ht.png" id="3_elstl"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://lgfhdcsb2ryx" path="res://maps/desert/textures/rock029_nrm_rgh.png" id="4_6h5db"]
|
||||||
|
|
||||||
|
[sub_resource type="Terrain3DTexture" id="Terrain3DTexture_wue72"]
|
||||||
|
name = "Rock"
|
||||||
|
albedo_color = Color(0.921569, 0.890196, 0.933333, 1)
|
||||||
|
albedo_texture = ExtResource("3_elstl")
|
||||||
|
normal_texture = ExtResource("4_6h5db")
|
||||||
|
uv_scale = 0.05
|
||||||
|
|
||||||
|
[sub_resource type="Terrain3DTexture" id="Terrain3DTexture_dkh73"]
|
||||||
|
name = "Sand"
|
||||||
|
texture_id = 1
|
||||||
|
albedo_color = Color(0.792157, 0.72549, 0.694118, 1)
|
||||||
|
albedo_texture = ExtResource("1_rh7of")
|
||||||
|
normal_texture = ExtResource("2_xt1tc")
|
||||||
|
uv_scale = 0.15
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
textures = Array[Terrain3DTexture]([SubResource("Terrain3DTexture_wue72"), SubResource("Terrain3DTexture_dkh73")])
|
||||||
BIN
maps/desert/textures/ground054_alb_ht.png
Normal file
|
After Width: | Height: | Size: 2.5 MiB |
35
maps/desert/textures/ground054_alb_ht.png.import
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://cngjywcua4vv8"
|
||||||
|
path.bptc="res://.godot/imported/ground054_alb_ht.png-c1e6560e1b831d8f5772408a395cdf1b.bptc.ctex"
|
||||||
|
metadata={
|
||||||
|
"imported_formats": ["s3tc_bptc"],
|
||||||
|
"vram_texture": true
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://maps/desert/textures/ground054_alb_ht.png"
|
||||||
|
dest_files=["res://.godot/imported/ground054_alb_ht.png-c1e6560e1b831d8f5772408a395cdf1b.bptc.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=2
|
||||||
|
compress/high_quality=true
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=2
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=true
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
BIN
maps/desert/textures/ground054_nrm_rgh.png
Normal file
|
After Width: | Height: | Size: 2.7 MiB |
35
maps/desert/textures/ground054_nrm_rgh.png.import
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://cbk7l6hs0yrcc"
|
||||||
|
path.bptc="res://.godot/imported/ground054_nrm_rgh.png-70f079690ff8219938f9079109780fc1.bptc.ctex"
|
||||||
|
metadata={
|
||||||
|
"imported_formats": ["s3tc_bptc"],
|
||||||
|
"vram_texture": true
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://maps/desert/textures/ground054_nrm_rgh.png"
|
||||||
|
dest_files=["res://.godot/imported/ground054_nrm_rgh.png-70f079690ff8219938f9079109780fc1.bptc.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=2
|
||||||
|
compress/high_quality=true
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=1
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=true
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
BIN
maps/desert/textures/rock029_alb_ht.png
Normal file
|
After Width: | Height: | Size: 2.3 MiB |
35
maps/desert/textures/rock029_alb_ht.png.import
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dwk8islw7ebab"
|
||||||
|
path.bptc="res://.godot/imported/rock029_alb_ht.png-a5e0a4f98f29bdeb159f1e749d7737b1.bptc.ctex"
|
||||||
|
metadata={
|
||||||
|
"imported_formats": ["s3tc_bptc"],
|
||||||
|
"vram_texture": true
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://maps/desert/textures/rock029_alb_ht.png"
|
||||||
|
dest_files=["res://.godot/imported/rock029_alb_ht.png-a5e0a4f98f29bdeb159f1e749d7737b1.bptc.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=2
|
||||||
|
compress/high_quality=true
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=2
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=true
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
BIN
maps/desert/textures/rock029_nrm_rgh.png
Normal file
|
After Width: | Height: | Size: 3.2 MiB |
35
maps/desert/textures/rock029_nrm_rgh.png.import
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://lgfhdcsb2ryx"
|
||||||
|
path.bptc="res://.godot/imported/rock029_nrm_rgh.png-21134283f9adb86493d1d72a4f30e20a.bptc.ctex"
|
||||||
|
metadata={
|
||||||
|
"imported_formats": ["s3tc_bptc"],
|
||||||
|
"vram_texture": true
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://maps/desert/textures/rock029_nrm_rgh.png"
|
||||||
|
dest_files=["res://.godot/imported/rock029_nrm_rgh.png-21134283f9adb86493d1d72a4f30e20a.bptc.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=2
|
||||||
|
compress/high_quality=true
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=1
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=true
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
|
|
@ -1,47 +1,64 @@
|
||||||
[gd_scene load_steps=7 format=3 uid="uid://chbno00ugl6te"]
|
[gd_scene load_steps=8 format=3 uid="uid://chbno00ugl6te"]
|
||||||
|
|
||||||
|
[ext_resource type="Environment" uid="uid://d2ahijqqspw5f" path="res://environments/default.tres" id="1_3nr12"]
|
||||||
|
[ext_resource type="Script" path="res://maps/map.gd" id="1_6ysiv"]
|
||||||
[ext_resource type="Terrain3DStorage" uid="uid://dyon4xda4k40d" path="res://maps/genesis/resources/storage.res" id="1_a88qe"]
|
[ext_resource type="Terrain3DStorage" uid="uid://dyon4xda4k40d" path="res://maps/genesis/resources/storage.res" id="1_a88qe"]
|
||||||
[ext_resource type="Terrain3DMaterial" uid="uid://bd4lr5sxu8xu" path="res://maps/genesis/resources/material.res" id="2_o2y3d"]
|
[ext_resource type="Terrain3DMaterial" uid="uid://bd4lr5sxu8xu" path="res://maps/genesis/resources/material.res" id="2_o2y3d"]
|
||||||
[ext_resource type="Terrain3DTextureList" uid="uid://dnqa8kxgm3xuw" path="res://maps/genesis/resources/textures.res" id="3_1cww7"]
|
[ext_resource type="Terrain3DTextureList" uid="uid://dnqa8kxgm3xuw" path="res://maps/genesis/resources/textures.res" id="3_1cww7"]
|
||||||
|
|
||||||
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_gi1uj"]
|
[sub_resource type="CapsuleMesh" id="CapsuleMesh_k2vhq"]
|
||||||
sky_top_color = Color(0.384314, 0.454902, 0.54902, 1)
|
|
||||||
sky_horizon_color = Color(0.64625, 0.65575, 0.67075, 1)
|
|
||||||
ground_horizon_color = Color(0.64625, 0.65575, 0.67075, 1)
|
|
||||||
|
|
||||||
[sub_resource type="Sky" id="Sky_t5qlv"]
|
[sub_resource type="CapsuleMesh" id="CapsuleMesh_5ytwx"]
|
||||||
sky_material = SubResource("ProceduralSkyMaterial_gi1uj")
|
|
||||||
process_mode = 1
|
|
||||||
radiance_size = 4
|
|
||||||
|
|
||||||
[sub_resource type="Environment" id="Environment_6whfw"]
|
[node name="Map" type="Node" node_paths=PackedStringArray("_flagstand", "_player_spawns_root")]
|
||||||
background_mode = 2
|
script = ExtResource("1_6ysiv")
|
||||||
sky = SubResource("Sky_t5qlv")
|
_flagstand = NodePath("Terrain3D/FlagPillar/CSGCylinder3D/FlagStand")
|
||||||
tonemap_mode = 3
|
_player_spawns_root = NodePath("Terrain3D/PlayerSpawns")
|
||||||
glow_normalized = true
|
|
||||||
glow_intensity = 2.0
|
|
||||||
glow_strength = 0.96
|
|
||||||
fog_light_color = Color(0.721569, 0.494118, 0.294118, 1)
|
|
||||||
fog_sun_scatter = 0.27
|
|
||||||
fog_density = 0.0001
|
|
||||||
fog_aerial_perspective = 0.602
|
|
||||||
fog_sky_affect = 0.518
|
|
||||||
volumetric_fog_density = 0.003
|
|
||||||
volumetric_fog_albedo = Color(1, 0.380392, 0.380392, 1)
|
|
||||||
volumetric_fog_emission_energy = 192.23
|
|
||||||
volumetric_fog_length = 551.32
|
|
||||||
volumetric_fog_ambient_inject = 0.37
|
|
||||||
|
|
||||||
[node name="Map" type="Node3D"]
|
|
||||||
|
|
||||||
[node name="Sunlight" type="DirectionalLight3D" parent="."]
|
|
||||||
transform = Transform3D(-0.866024, -0.433016, 0.250001, 0, 0.499998, 0.866026, -0.500003, 0.749999, -0.43301, 0, 0, 0)
|
|
||||||
shadow_enabled = true
|
|
||||||
|
|
||||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
|
||||||
environment = SubResource("Environment_6whfw")
|
|
||||||
|
|
||||||
[node name="Terrain3D" type="Terrain3D" parent="."]
|
[node name="Terrain3D" type="Terrain3D" parent="."]
|
||||||
storage = ExtResource("1_a88qe")
|
storage = ExtResource("1_a88qe")
|
||||||
material = ExtResource("2_o2y3d")
|
material = ExtResource("2_o2y3d")
|
||||||
texture_list = ExtResource("3_1cww7")
|
texture_list = ExtResource("3_1cww7")
|
||||||
|
collision_layer = 2147483648
|
||||||
|
collision_mask = 2147483648
|
||||||
|
mesh_size = 24
|
||||||
|
|
||||||
|
[node name="PlayerSpawns" type="Node" parent="Terrain3D"]
|
||||||
|
|
||||||
|
[node name="Spawn1" type="Marker3D" parent="Terrain3D/PlayerSpawns"]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 95.5378, -32.735)
|
||||||
|
visible = false
|
||||||
|
|
||||||
|
[node name="MeshInstance3D" type="MeshInstance3D" parent="Terrain3D/PlayerSpawns/Spawn1"]
|
||||||
|
mesh = SubResource("CapsuleMesh_k2vhq")
|
||||||
|
|
||||||
|
[node name="Spawn2" type="Marker3D" parent="Terrain3D/PlayerSpawns"]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 9, 98.3078, 18.061)
|
||||||
|
visible = false
|
||||||
|
|
||||||
|
[node name="MeshInstance3D" type="MeshInstance3D" parent="Terrain3D/PlayerSpawns/Spawn2"]
|
||||||
|
mesh = SubResource("CapsuleMesh_5ytwx")
|
||||||
|
|
||||||
|
[node name="FlagPillar" type="CSGCombiner3D" parent="Terrain3D"]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 2.83726, 0, 0, 0, 1, 0, 94.6411, 0)
|
||||||
|
use_collision = true
|
||||||
|
collision_layer = 2147483648
|
||||||
|
collision_mask = 0
|
||||||
|
|
||||||
|
[node name="CSGBox3D" type="CSGBox3D" parent="Terrain3D/FlagPillar"]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.9311, 0)
|
||||||
|
size = Vector3(0.5, 6, 0.5)
|
||||||
|
|
||||||
|
[node name="CSGCylinder3D" type="CSGCylinder3D" parent="Terrain3D/FlagPillar"]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.42967, 0)
|
||||||
|
height = 5.0
|
||||||
|
|
||||||
|
[node name="FlagStand" type="Marker3D" parent="Terrain3D/FlagPillar/CSGCylinder3D"]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3.42315, 0)
|
||||||
|
|
||||||
|
[node name="Sunlight" type="DirectionalLight3D" parent="."]
|
||||||
|
transform = Transform3D(-0.866024, -0.433016, 0.25, 0, 0.499998, 0.866027, -0.500003, 0.75, -0.43301, 0, 100, 0)
|
||||||
|
shadow_enabled = true
|
||||||
|
|
||||||
|
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||||
|
environment = ExtResource("1_3nr12")
|
||||||
|
|
|
||||||
16
maps/map.gd
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
class_name Map extends Node
|
||||||
|
|
||||||
|
@export var _flagstand : Node3D
|
||||||
|
@export var _player_spawns_root : Node
|
||||||
|
|
||||||
|
var _rng : RandomNumberGenerator = RandomNumberGenerator.new()
|
||||||
|
|
||||||
|
func get_flagstand() -> Node3D:
|
||||||
|
return _flagstand
|
||||||
|
|
||||||
|
func get_player_spawn() -> Node3D:
|
||||||
|
var spawn_count : int = _player_spawns_root.get_child_count()
|
||||||
|
var spawn_index : int = _rng.randi_range(0, spawn_count - 1)
|
||||||
|
var spawn_selected : Node3D = _player_spawns_root.get_child(spawn_index)
|
||||||
|
return spawn_selected
|
||||||
|
|
||||||
|
|
@ -1,21 +1,22 @@
|
||||||
[gd_scene load_steps=6 format=3 uid="uid://boviiugcnfyrj"]
|
[gd_scene load_steps=7 format=3 uid="uid://boviiugcnfyrj"]
|
||||||
|
|
||||||
[ext_resource type="PackedScene" uid="uid://cbhx1xme0sb7k" path="res://entities/player/player.tscn" id="2_6wbjq"]
|
[ext_resource type="PackedScene" uid="uid://cbhx1xme0sb7k" path="res://entities/player/player.tscn" id="2_6wbjq"]
|
||||||
[ext_resource type="PackedScene" uid="uid://chbno00ugl6te" path="res://maps/genesis/genesis.tscn" id="2_lsep7"]
|
|
||||||
[ext_resource type="PackedScene" uid="uid://dpnu1lvfncx6q" path="res://entities/target_dummy/target_dummy.tscn" id="3_fkq5v"]
|
[ext_resource type="PackedScene" uid="uid://dpnu1lvfncx6q" path="res://entities/target_dummy/target_dummy.tscn" id="3_fkq5v"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://c88l3h0ph00c7" path="res://entities/flag/flag.tscn" id="4_1j2pw"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://btlkog4b87p4x" path="res://maps/desert/desert.tscn" id="4_dogmv"]
|
||||||
|
|
||||||
[sub_resource type="GDScript" id="GDScript_iv0l6"]
|
[sub_resource type="GDScript" id="GDScript_iv0l6"]
|
||||||
script/source = "extends Node
|
script/source = "extends Node
|
||||||
|
|
||||||
@onready var player_node : Player = $Player
|
@onready var player_node : Player = $Player
|
||||||
@onready var target_dummy = $TargetDummy
|
@onready var target_dummy : RigidBody3D = $TargetDummy
|
||||||
|
|
||||||
@onready var player_respawn_location = player_node.position
|
@onready var player_respawn_location : Vector3 = player_node.position
|
||||||
|
|
||||||
func _ready():
|
func _ready() -> void:
|
||||||
player_node.died.connect(respawn_player)
|
player_node.died.connect(respawn_player)
|
||||||
|
|
||||||
func respawn_player(player):
|
func respawn_player(player : Player) -> void:
|
||||||
player.respawn(player_respawn_location)
|
player.respawn(player_respawn_location)
|
||||||
"
|
"
|
||||||
|
|
||||||
|
|
@ -27,11 +28,15 @@ absorbent = true
|
||||||
[node name="Demo" type="Node"]
|
[node name="Demo" type="Node"]
|
||||||
script = SubResource("GDScript_iv0l6")
|
script = SubResource("GDScript_iv0l6")
|
||||||
|
|
||||||
[node name="Map" parent="." instance=ExtResource("2_lsep7")]
|
|
||||||
|
|
||||||
[node name="Player" parent="." instance=ExtResource("2_6wbjq")]
|
[node name="Player" parent="." instance=ExtResource("2_6wbjq")]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 92.7007, 0)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 589.786, 210.119, 853.632)
|
||||||
physics_material_override = SubResource("PhysicsMaterial_c5jqv")
|
physics_material_override = SubResource("PhysicsMaterial_c5jqv")
|
||||||
|
|
||||||
[node name="TargetDummy" parent="." instance=ExtResource("3_fkq5v")]
|
[node name="TargetDummy" parent="." instance=ExtResource("3_fkq5v")]
|
||||||
transform = Transform3D(-0.995746, 0, -0.0921446, 0, 1, 0, 0.0921446, 0, -0.995746, 15.757, 95.1745, 0)
|
transform = Transform3D(-0.789567, 0, 0.613666, 0, 1, 0, -0.613666, 0, -0.789567, 418.132, 195.484, 802.593)
|
||||||
|
|
||||||
|
[node name="Flag" parent="." instance=ExtResource("4_1j2pw")]
|
||||||
|
transform = Transform3D(0.405891, 0, -0.913922, 0, 1, 0, 0.913922, 0, 0.405891, 890.762, 179.326, 1005.33)
|
||||||
|
|
||||||
|
[node name="Desert" parent="." instance=ExtResource("4_dogmv")]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0566101, 1456.67, 0.597462)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
[gd_scene load_steps=4 format=3 uid="uid://bvwxfgygm2xb8"]
|
[gd_scene load_steps=6 format=3 uid="uid://bvwxfgygm2xb8"]
|
||||||
|
|
||||||
[ext_resource type="PackedScene" uid="uid://chbno00ugl6te" path="res://maps/genesis/genesis.tscn" id="1_nulvv"]
|
[ext_resource type="PackedScene" uid="uid://chbno00ugl6te" path="res://maps/genesis/genesis.tscn" id="1_nulvv"]
|
||||||
[ext_resource type="PackedScene" uid="uid://cbhx1xme0sb7k" path="res://entities/player/player.tscn" id="2_og1vb"]
|
[ext_resource type="PackedScene" uid="uid://cbhx1xme0sb7k" path="res://entities/player/player.tscn" id="2_og1vb"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://c88l3h0ph00c7" path="res://entities/flag/flag.tscn" id="3_h0rie"]
|
||||||
|
[ext_resource type="Script" path="res://modes/scoreboard.gd" id="4_n0mhp"]
|
||||||
|
|
||||||
[sub_resource type="GDScript" id="GDScript_1qrbp"]
|
[sub_resource type="GDScript" id="GDScript_1qrbp"]
|
||||||
script/source = "class_name Multiplayer extends Node
|
script/source = "class_name Multiplayer extends Node
|
||||||
|
|
@ -9,68 +11,114 @@ script/source = "class_name Multiplayer extends Node
|
||||||
@export_category(\"Parameters\")
|
@export_category(\"Parameters\")
|
||||||
@export var MAP : PackedScene
|
@export var MAP : PackedScene
|
||||||
@export var PLAYER : PackedScene
|
@export var PLAYER : PackedScene
|
||||||
|
@export var FLAG : PackedScene
|
||||||
@export var MAX_CLIENTS : int = 24
|
@export var MAX_CLIENTS : int = 24
|
||||||
|
@export var RESPAWN_TIME : float = 3.0
|
||||||
|
|
||||||
@onready var map = $Map
|
@onready var players : Node = $Players
|
||||||
@onready var players = $Players
|
@onready var objectives : Node = $Objectives
|
||||||
|
@onready var map : Node = $Map
|
||||||
|
@onready var scoreboard : Scoreboard = $Scoreboard
|
||||||
|
@onready var scoreboard_ui : Node = $ScoreboardUI
|
||||||
|
|
||||||
|
var _map_manager : Map
|
||||||
|
|
||||||
signal connected_to_server
|
signal connected_to_server
|
||||||
signal connection_failed
|
signal connection_failed
|
||||||
|
|
||||||
func load_map(scene : PackedScene):
|
func start_server(port : int, nickname : String) -> void:
|
||||||
map.add_child(scene.instantiate())
|
var peer : ENetMultiplayerPeer = ENetMultiplayerPeer.new()
|
||||||
|
|
||||||
func start_server(port):
|
|
||||||
var peer = ENetMultiplayerPeer.new()
|
|
||||||
peer.create_server(port, MAX_CLIENTS)
|
peer.create_server(port, MAX_CLIENTS)
|
||||||
|
|
||||||
multiplayer.multiplayer_peer = peer
|
multiplayer.multiplayer_peer = peer
|
||||||
|
|
||||||
load_map.call_deferred(MAP)
|
_load_map.call_deferred(MAP, nickname)
|
||||||
|
|
||||||
multiplayer.peer_connected.connect(add_player)
|
|
||||||
multiplayer.peer_disconnected.connect(remove_player)
|
multiplayer.peer_disconnected.connect(remove_player)
|
||||||
|
|
||||||
for id in multiplayer.get_peers():
|
func join_server(host : String, port : int, nickname : String) -> void:
|
||||||
add_player(id)
|
var peer : ENetMultiplayerPeer = ENetMultiplayerPeer.new()
|
||||||
|
|
||||||
if DisplayServer.get_name() != \"headless\":
|
|
||||||
add_player(1)
|
|
||||||
|
|
||||||
func join_server(host, port):
|
|
||||||
var peer = ENetMultiplayerPeer.new()
|
|
||||||
peer.create_client(host, port)
|
peer.create_client(host, port)
|
||||||
multiplayer.connected_to_server.connect(_on_connected_to_server)
|
multiplayer.connected_to_server.connect(_on_connected_to_server.bind(nickname))
|
||||||
multiplayer.connection_failed.connect(_on_connection_failed)
|
multiplayer.connection_failed.connect(_on_connection_failed)
|
||||||
multiplayer.multiplayer_peer = peer
|
multiplayer.multiplayer_peer = peer
|
||||||
|
|
||||||
func _on_connected_to_server():
|
func _on_connected_to_server(nickname : String) -> void:
|
||||||
connected_to_server.emit()
|
connected_to_server.emit()
|
||||||
|
scoreboard.request_scoreboard_from_authority.rpc()
|
||||||
|
_join_match.rpc(nickname)
|
||||||
|
|
||||||
func _on_connection_failed():
|
func _on_connection_failed() -> void:
|
||||||
connection_failed.emit()
|
connection_failed.emit()
|
||||||
|
|
||||||
func respawn_player(player):
|
func _on_player_died(player : Player, killer_id : int) -> void:
|
||||||
player.respawn(Vector3(0.0, 150.0, 0.0))
|
if player.player_id != killer_id:
|
||||||
|
var node_name : String = str(killer_id)
|
||||||
|
if players.has_node(node_name):
|
||||||
|
var killer : Player = players.get_node(node_name)
|
||||||
|
scoreboard.increment_kill_count(killer)
|
||||||
|
scoreboard.add_score_to_player(killer, 10)
|
||||||
|
scoreboard.broadcast_player_score_update(killer)
|
||||||
|
await get_tree().create_timer(RESPAWN_TIME).timeout
|
||||||
|
respawn_player(player)
|
||||||
|
|
||||||
func add_player(peer_id : int):
|
func respawn_player(player : Player) -> void:
|
||||||
|
var spawn_location : Vector3 = _map_manager.get_player_spawn().position
|
||||||
|
player.respawn(spawn_location)
|
||||||
|
|
||||||
|
func add_player(peer_id : int, nickname : String) -> void:
|
||||||
var player : Player = PLAYER.instantiate()
|
var player : Player = PLAYER.instantiate()
|
||||||
player.name = str(peer_id)
|
player.name = str(peer_id)
|
||||||
player.player_id = peer_id
|
player.player_id = peer_id
|
||||||
player.position = Vector3(0.0, 150.0, 0.0)
|
player.nickname = nickname
|
||||||
|
player.global_position = _map_manager.get_player_spawn().position
|
||||||
players.add_child(player)
|
players.add_child(player)
|
||||||
player.died.connect(respawn_player)
|
player.died.connect(_on_player_died)
|
||||||
|
scoreboard.add_entry(player)
|
||||||
print(\"Peer `%s` connected\" % player.name)
|
print(\"Peer `%s` connected\" % player.name)
|
||||||
|
|
||||||
func remove_player(peer_id : int):
|
func remove_player(peer_id : int) -> void:
|
||||||
var node_name = str(peer_id)
|
var node_name : String = str(peer_id)
|
||||||
if players.has_node(node_name):
|
if players.has_node(node_name):
|
||||||
players.get_node(node_name).queue_free()
|
var player : Player = players.get_node(node_name)
|
||||||
|
scoreboard.remove_entry(player)
|
||||||
|
player.die(-1)
|
||||||
|
player.queue_free()
|
||||||
print(\"Peer `%s` disconnected\" % node_name)
|
print(\"Peer `%s` disconnected\" % node_name)
|
||||||
|
|
||||||
func _exit_tree():
|
func _load_map(scene : PackedScene, nickname : String) -> void:
|
||||||
if multiplayer.is_server():
|
var map_scene : Node = scene.instantiate()
|
||||||
multiplayer.peer_connected.disconnect(add_player)
|
_map_manager = map_scene
|
||||||
|
map_scene.ready.connect(_add_flag)
|
||||||
|
if DisplayServer.get_name() != \"headless\":
|
||||||
|
add_player(1, nickname)
|
||||||
|
map.add_child(map_scene)
|
||||||
|
|
||||||
|
func _add_flag() -> void:
|
||||||
|
var flag : Flag = FLAG.instantiate()
|
||||||
|
flag.global_position = _map_manager.get_flagstand().global_position
|
||||||
|
objectives.add_child(flag)
|
||||||
|
|
||||||
|
func _unhandled_input(event : InputEvent) -> void:
|
||||||
|
if event.is_action_pressed(\"scoreboard\"):
|
||||||
|
var entries : Array = scoreboard.get_entries()
|
||||||
|
for entry : Scoreboard.ScoreboardEntry in entries:
|
||||||
|
var entry_label : Label = Label.new()
|
||||||
|
entry_label.text = \"%s | kills: %s | score: %s\" % [entry.nickname, entry.kills, entry.score]
|
||||||
|
%Scores.add_child(entry_label)
|
||||||
|
scoreboard_ui.show()
|
||||||
|
elif event.is_action_released(\"scoreboard\"):
|
||||||
|
scoreboard_ui.hide()
|
||||||
|
for score_label in %Scores.get_children():
|
||||||
|
score_label.queue_free()
|
||||||
|
|
||||||
|
@rpc(\"any_peer\")
|
||||||
|
func _join_match(nickname : String) -> void:
|
||||||
|
if is_multiplayer_authority():
|
||||||
|
add_player(multiplayer.get_remote_sender_id(), nickname)
|
||||||
|
|
||||||
|
func _exit_tree() -> void:
|
||||||
|
if is_multiplayer_authority():
|
||||||
multiplayer.peer_disconnected.disconnect(remove_player)
|
multiplayer.peer_disconnected.disconnect(remove_player)
|
||||||
"
|
"
|
||||||
|
|
||||||
|
|
@ -78,6 +126,7 @@ func _exit_tree():
|
||||||
script = SubResource("GDScript_1qrbp")
|
script = SubResource("GDScript_1qrbp")
|
||||||
MAP = ExtResource("1_nulvv")
|
MAP = ExtResource("1_nulvv")
|
||||||
PLAYER = ExtResource("2_og1vb")
|
PLAYER = ExtResource("2_og1vb")
|
||||||
|
FLAG = ExtResource("3_h0rie")
|
||||||
|
|
||||||
[node name="Map" type="Node" parent="."]
|
[node name="Map" type="Node" parent="."]
|
||||||
|
|
||||||
|
|
@ -91,3 +140,42 @@ spawn_limit = 1
|
||||||
[node name="PlayersSpawner" type="MultiplayerSpawner" parent="."]
|
[node name="PlayersSpawner" type="MultiplayerSpawner" parent="."]
|
||||||
_spawnable_scenes = PackedStringArray("res://entities/player/player.tscn")
|
_spawnable_scenes = PackedStringArray("res://entities/player/player.tscn")
|
||||||
spawn_path = NodePath("../Players")
|
spawn_path = NodePath("../Players")
|
||||||
|
|
||||||
|
[node name="Objectives" type="Node" parent="."]
|
||||||
|
|
||||||
|
[node name="ObjectivesSpawner" type="MultiplayerSpawner" parent="."]
|
||||||
|
_spawnable_scenes = PackedStringArray("res://entities/flag/flag.tscn")
|
||||||
|
spawn_path = NodePath("../Objectives")
|
||||||
|
|
||||||
|
[node name="Scoreboard" type="Node" parent="."]
|
||||||
|
script = ExtResource("4_n0mhp")
|
||||||
|
|
||||||
|
[node name="ScoreboardUI" type="Control" parent="."]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 3
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
|
||||||
|
[node name="PanelContainer" type="PanelContainer" parent="ScoreboardUI"]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="ScoreboardUI/PanelContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 4
|
||||||
|
size_flags_vertical = 0
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="ScoreboardUI/PanelContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Scoreboard"
|
||||||
|
|
||||||
|
[node name="Scores" type="VBoxContainer" parent="ScoreboardUI/PanelContainer/VBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
|
|
||||||
77
modes/scoreboard.gd
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
# This file is part of open-fpsz.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
class_name Scoreboard extends Node
|
||||||
|
|
||||||
|
@export var _entries : Dictionary = {}
|
||||||
|
|
||||||
|
class ScoreboardEntry:
|
||||||
|
var nickname : String
|
||||||
|
var kills : int
|
||||||
|
var score : int
|
||||||
|
|
||||||
|
func add_entry(player : Player) -> void:
|
||||||
|
var new_entry : ScoreboardEntry = ScoreboardEntry.new()
|
||||||
|
new_entry.nickname = player.nickname
|
||||||
|
new_entry.kills = 0
|
||||||
|
new_entry.score = 0
|
||||||
|
_entries[player.player_id] = new_entry
|
||||||
|
_send_scoreboard_entry.rpc(player.player_id, new_entry.nickname, new_entry.kills, new_entry.score)
|
||||||
|
|
||||||
|
func remove_entry(player : Player) -> void:
|
||||||
|
_entries.erase(player.player_id)
|
||||||
|
_broadcast_player_removed(player)
|
||||||
|
|
||||||
|
func add_score_to_player(player : Player, amount : int) -> void:
|
||||||
|
_entries[player.player_id].score += amount
|
||||||
|
|
||||||
|
func increment_kill_count(player : Player) -> void:
|
||||||
|
_entries[player.player_id].kills += 1
|
||||||
|
|
||||||
|
func get_entries() -> Array:
|
||||||
|
return _entries.values()
|
||||||
|
|
||||||
|
@rpc("any_peer", "call_remote", "reliable")
|
||||||
|
func request_scoreboard_from_authority() -> void:
|
||||||
|
if is_multiplayer_authority():
|
||||||
|
var recipient_id : int = multiplayer.get_remote_sender_id()
|
||||||
|
_clear_scoreboard.rpc_id(recipient_id)
|
||||||
|
for entry_key : int in _entries:
|
||||||
|
var entry : ScoreboardEntry = _entries[entry_key]
|
||||||
|
_send_scoreboard_entry.rpc_id(recipient_id, entry_key, entry.nickname, entry.kills, entry.score)
|
||||||
|
|
||||||
|
@rpc("authority", "reliable")
|
||||||
|
func _clear_scoreboard() -> void:
|
||||||
|
_entries.clear()
|
||||||
|
|
||||||
|
@rpc("authority", "reliable")
|
||||||
|
func _send_scoreboard_entry(player_id : int, nickname : String, kills : int, score : int) -> void:
|
||||||
|
var new_entry : ScoreboardEntry = ScoreboardEntry.new()
|
||||||
|
new_entry.nickname = nickname
|
||||||
|
new_entry.kills = kills
|
||||||
|
new_entry.score = score
|
||||||
|
_entries[player_id] = new_entry
|
||||||
|
|
||||||
|
@rpc("authority", "reliable")
|
||||||
|
func _remove_scoreboard_entry(player_id : int) -> void:
|
||||||
|
_entries.erase(player_id)
|
||||||
|
|
||||||
|
func broadcast_player_score_update(player : Player) -> void:
|
||||||
|
var player_id : int = player.player_id
|
||||||
|
var player_score_entry : ScoreboardEntry = _entries[player_id]
|
||||||
|
_send_scoreboard_entry.rpc(player_id, player_score_entry.nickname, player_score_entry.kills, player_score_entry.score)
|
||||||
|
|
||||||
|
func _broadcast_player_removed(player : Player) -> void:
|
||||||
|
var player_id : int = player.player_id
|
||||||
|
_remove_scoreboard_entry.rpc(player_id)
|
||||||
|
|
@ -15,13 +15,43 @@ run/main_scene="res://main.tscn"
|
||||||
config/features=PackedStringArray("4.2", "Forward Plus")
|
config/features=PackedStringArray("4.2", "Forward Plus")
|
||||||
config/icon="res://icon.svg"
|
config/icon="res://icon.svg"
|
||||||
|
|
||||||
|
[autoload]
|
||||||
|
|
||||||
|
GlobalSettings="*res://systems/settings.gd"
|
||||||
|
|
||||||
|
[debug]
|
||||||
|
|
||||||
|
gdscript/warnings/unassigned_variable=2
|
||||||
|
gdscript/warnings/unassigned_variable_op_assign=2
|
||||||
|
gdscript/warnings/unused_variable=2
|
||||||
|
gdscript/warnings/unused_local_constant=2
|
||||||
|
gdscript/warnings/unused_private_class_variable=2
|
||||||
|
gdscript/warnings/unused_parameter=2
|
||||||
|
gdscript/warnings/unused_signal=2
|
||||||
|
gdscript/warnings/shadowed_variable=2
|
||||||
|
gdscript/warnings/shadowed_variable_base_class=2
|
||||||
|
gdscript/warnings/shadowed_global_identifier=2
|
||||||
|
gdscript/warnings/unreachable_code=2
|
||||||
|
gdscript/warnings/unreachable_pattern=2
|
||||||
|
gdscript/warnings/standalone_expression=2
|
||||||
|
gdscript/warnings/standalone_ternary=2
|
||||||
|
gdscript/warnings/incompatible_ternary=2
|
||||||
|
gdscript/warnings/property_used_as_function=2
|
||||||
|
gdscript/warnings/constant_used_as_function=2
|
||||||
|
gdscript/warnings/function_used_as_property=2
|
||||||
|
gdscript/warnings/untyped_declaration=2
|
||||||
|
|
||||||
[editor]
|
[editor]
|
||||||
|
|
||||||
movie_writer/disable_vsync=true
|
movie_writer/disable_vsync=true
|
||||||
|
|
||||||
[editor_plugins]
|
[editor_plugins]
|
||||||
|
|
||||||
enabled=PackedStringArray("res://addons/gut/plugin.cfg", "res://addons/terrain_3d/plugin.cfg")
|
enabled=PackedStringArray("res://addons/gut/plugin.cfg", "res://addons/smoothing/plugin.cfg", "res://addons/terrain_3d/plugin.cfg")
|
||||||
|
|
||||||
|
[filesystem]
|
||||||
|
|
||||||
|
import/blender/enabled=false
|
||||||
|
|
||||||
[input]
|
[input]
|
||||||
|
|
||||||
|
|
@ -75,15 +105,27 @@ fire_primary={
|
||||||
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":1,"canceled":false,"pressed":false,"double_click":false,"script":null)
|
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":1,"canceled":false,"pressed":false,"double_click":false,"script":null)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
throw_flag={
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":70,"key_label":0,"unicode":102,"echo":false,"script":null)
|
||||||
|
]
|
||||||
|
}
|
||||||
toggle_mouse_capture={
|
toggle_mouse_capture={
|
||||||
"deadzone": 0.5,
|
"deadzone": 0.5,
|
||||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194332,"key_label":0,"unicode":0,"echo":false,"script":null)
|
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194332,"key_label":0,"unicode":0,"echo":false,"script":null)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
scoreboard={
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194306,"key_label":0,"unicode":0,"echo":false,"script":null)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
[layer_names]
|
[layer_names]
|
||||||
|
|
||||||
3d_physics/layer_3="Damage"
|
3d_physics/layer_3="Damage"
|
||||||
|
3d_physics/layer_4="Objective"
|
||||||
|
3d_physics/layer_32="Terrain"
|
||||||
|
|
||||||
[physics]
|
[physics]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
shader_type canvas_item;
|
|
||||||
|
|
||||||
uniform sampler2D background : source_color;
|
|
||||||
|
|
||||||
void fragment() {
|
|
||||||
COLOR = texture(background, UV);
|
|
||||||
}
|
|
||||||
|
|
||||||
36
systems/settings.gd
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
class_name Settings extends Node
|
||||||
|
|
||||||
|
var _config_file : ConfigFile = ConfigFile.new()
|
||||||
|
|
||||||
|
var fov : int
|
||||||
|
var mouse_sensitivity : float
|
||||||
|
var inverted_y_axis : bool
|
||||||
|
var fullscreen : bool
|
||||||
|
|
||||||
|
const SETTINGS_FILE_PATH : String = "user://settings.cfg"
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
var error : Error = _config_file.load(SETTINGS_FILE_PATH)
|
||||||
|
if error != OK:
|
||||||
|
print("Settings not found, using defaults")
|
||||||
|
return
|
||||||
|
|
||||||
|
fov = _config_file.get_value("gameplay", "fov", 90)
|
||||||
|
mouse_sensitivity = _config_file.get_value("gameplay", "mouse_sensitivity", 0.6)
|
||||||
|
inverted_y_axis = _config_file.get_value("gameplay", "inverted_y_axis", false)
|
||||||
|
fullscreen = _config_file.get_value("graphics", "fullscreen", false)
|
||||||
|
_update_screen()
|
||||||
|
|
||||||
|
func save_to_file() -> void:
|
||||||
|
_config_file.set_value("gameplay", "fov", fov)
|
||||||
|
_config_file.set_value("gameplay", "mouse_sensitivity", mouse_sensitivity)
|
||||||
|
_config_file.set_value("gameplay", "inverted_y_axis", inverted_y_axis)
|
||||||
|
_config_file.set_value("graphics", "fullscreen", fullscreen)
|
||||||
|
_update_screen()
|
||||||
|
_config_file.save(SETTINGS_FILE_PATH)
|
||||||
|
|
||||||
|
func _update_screen() -> void:
|
||||||
|
if fullscreen:
|
||||||
|
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
|
||||||
|
else:
|
||||||
|
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
|
||||||
|
|
@ -1,21 +1,21 @@
|
||||||
# This file is part of open-fpsz.
|
# This file is part of open-fpsz.
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
# (at your option) any later version.
|
# (at your option) any later version.
|
||||||
#
|
#
|
||||||
# This program is distributed in the hope that it will be useful,
|
# This program is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
extends GutTest
|
extends GutTest
|
||||||
|
|
||||||
func _test_projectile_class():
|
func test_projectile_class() -> void:
|
||||||
var projectile = Projectile.new()
|
var projectile : Projectile = Projectile.new()
|
||||||
assert(projectile != null, "Projectile class should be instantiated")
|
assert_true(projectile != null, "Projectile class should be instantiated")
|
||||||
assert(projectile.speed == 78.4, "Projectile damage should be initialized to 78.4")
|
assert_true(projectile.speed == 78.4, "Projectile damage should be initialized to 78.4")
|
||||||
projectile.queue_free()
|
projectile.free()
|
||||||
|
|
|
||||||
52
tests/test_health_component.gd
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
# This file is part of open-fpsz.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
extends GutTest
|
||||||
|
|
||||||
|
var _subject : HealthComponent
|
||||||
|
const TEST_MAX_HEALTH : float = 100.0
|
||||||
|
|
||||||
|
func before_each() -> void:
|
||||||
|
_subject = HealthComponent.new()
|
||||||
|
watch_signals(_subject)
|
||||||
|
_subject.max_health = TEST_MAX_HEALTH
|
||||||
|
add_child(_subject)
|
||||||
|
|
||||||
|
func after_each() -> void:
|
||||||
|
_subject.free()
|
||||||
|
|
||||||
|
func test_that_it_has_max_health_when_ready() -> void:
|
||||||
|
assert_eq(_subject.health, _subject.max_health)
|
||||||
|
|
||||||
|
func test_that_it_takes_damage() -> void:
|
||||||
|
var damage_amount : float = 10
|
||||||
|
_subject.damage(damage_amount, -1)
|
||||||
|
assert_eq(_subject.health, TEST_MAX_HEALTH - damage_amount)
|
||||||
|
|
||||||
|
func test_that_it_emits_health_changed_after_damage() -> void:
|
||||||
|
_subject.damage(1, -1)
|
||||||
|
assert_signal_emitted(_subject, 'health_changed')
|
||||||
|
|
||||||
|
func test_that_it_emits_health_zeroed() -> void:
|
||||||
|
_subject.damage(TEST_MAX_HEALTH, -1)
|
||||||
|
assert_signal_emitted_with_parameters(_subject, 'health_zeroed', [-1])
|
||||||
|
|
||||||
|
func test_that_it_heals_fully() -> void:
|
||||||
|
_subject.health = 10
|
||||||
|
_subject.heal_full()
|
||||||
|
assert_eq(_subject.health, TEST_MAX_HEALTH)
|
||||||
|
|
||||||
|
func test_that_it_emits_health_changed_after_heal_full() -> void:
|
||||||
|
_subject.heal_full()
|
||||||
|
assert_signal_emitted(_subject, 'health_changed')
|
||||||
57
tests/test_scoreboard.gd
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
# This file is part of open-fpsz.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
extends GutTest
|
||||||
|
|
||||||
|
var PLAYER : PackedScene = preload("res://entities/player/player.tscn")
|
||||||
|
|
||||||
|
var _subject : Scoreboard
|
||||||
|
|
||||||
|
func before_each() -> void:
|
||||||
|
_subject = Scoreboard.new()
|
||||||
|
add_child(_subject)
|
||||||
|
|
||||||
|
func after_each() -> void:
|
||||||
|
_subject.free()
|
||||||
|
|
||||||
|
func test_that_new_scoreboard_is_empty() -> void:
|
||||||
|
assert_eq(_subject.get_entries(), [])
|
||||||
|
|
||||||
|
func test_that_added_entry_is_added_correctly() -> void:
|
||||||
|
var player : Player = PLAYER.instantiate()
|
||||||
|
player.nickname = "test_nickname"
|
||||||
|
_subject.add_entry(player)
|
||||||
|
var entries : Array = _subject.get_entries()
|
||||||
|
assert_eq(1, entries.size())
|
||||||
|
var tested_entry : Scoreboard.ScoreboardEntry = entries[0]
|
||||||
|
assert_eq("test_nickname", tested_entry.nickname)
|
||||||
|
assert_eq(0, tested_entry.kills)
|
||||||
|
assert_eq(0, tested_entry.score)
|
||||||
|
player.free()
|
||||||
|
|
||||||
|
func test_that_scores_are_added_correctly() -> void:
|
||||||
|
var player : Player = PLAYER.instantiate()
|
||||||
|
_subject.add_entry(player)
|
||||||
|
_subject.add_score_to_player(player, 10)
|
||||||
|
var tested_entry : Scoreboard.ScoreboardEntry = _subject.get_entries()[0]
|
||||||
|
assert_eq(10, tested_entry.score)
|
||||||
|
player.free()
|
||||||
|
|
||||||
|
func test_that_kill_counts_are_incremented_correctly() -> void:
|
||||||
|
var player : Player = PLAYER.instantiate()
|
||||||
|
_subject.add_entry(player)
|
||||||
|
_subject.increment_kill_count(player)
|
||||||
|
var tested_entry : Scoreboard.ScoreboardEntry = _subject.get_entries()[0]
|
||||||
|
assert_eq(1, tested_entry.kills)
|
||||||
|
player.free()
|
||||||
|
Before Width: | Height: | Size: 364 KiB |
|
|
@ -1,3 +0,0 @@
|
||||||
[gd_resource type="ShaderMaterial" format=3 uid="uid://de6t4olk7hrs1"]
|
|
||||||
|
|
||||||
[resource]
|
|
||||||
|
Before Width: | Height: | Size: 364 KiB |