Merge branch 'develop' into feat/cicd-tests
1
.gitignore
vendored
|
|
@ -2,7 +2,6 @@
|
|||
.godot/
|
||||
|
||||
# Godot-specific ignores
|
||||
*.import
|
||||
export.cfg
|
||||
export_presets.cfg
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
image: $CI_REGISTRY/open-fpsz/docker-godot/godot
|
||||
|
||||
variables:
|
||||
EXPORT_NAME: open-fpsz
|
||||
|
||||
stages:
|
||||
- addons
|
||||
- tests
|
||||
|
|
@ -15,66 +18,45 @@ cache: &global_cache
|
|||
addons:
|
||||
stage: addons
|
||||
script:
|
||||
- timeout 10 godot --headless --editor --verbose || true
|
||||
- timeout 10 godot --headless --editor --verbose || true
|
||||
only:
|
||||
- main
|
||||
- develop
|
||||
|
||||
# run tests
|
||||
tests:
|
||||
stage: tests
|
||||
needs: [ "addons" ]
|
||||
script:
|
||||
- godot --headless --path "$PWD" -s addons/gut/gut_cmdln.gd
|
||||
only:
|
||||
- main
|
||||
- develop
|
||||
- timeout 15 godot --headless --editor --verbose || true
|
||||
- timeout 15 godot --headless --editor --verbose || true
|
||||
rules:
|
||||
- if: '$CI_COMMIT_TAG =~ /^v\d\.\d\.\d$/'
|
||||
|
||||
# export binaries
|
||||
.export_presets:
|
||||
needs: [ "tests" ]
|
||||
before_script:
|
||||
- cp "$EXPORT_PRESETS" export_presets.cfg
|
||||
only:
|
||||
- main
|
||||
|
||||
variables:
|
||||
EXPORT_NAME: open-fpsz
|
||||
- export ZIP_ARCHIVE_NAME="$EXPORT_NAME-$CI_COMMIT_TAG-$CI_JOB_NAME.zip"
|
||||
rules:
|
||||
- if: '$CI_COMMIT_TAG =~ /^v\d\.\d\.\d$/'
|
||||
|
||||
linux:
|
||||
stage: export
|
||||
extends: [ .export_presets ]
|
||||
when: manual
|
||||
script:
|
||||
- mkdir -v -p build/linux
|
||||
- godot --headless --verbose --export-release "Linux/X11" build/linux/$EXPORT_NAME.x86_64
|
||||
artifacts:
|
||||
name: $EXPORT_NAME-$CI_JOB_NAME
|
||||
paths:
|
||||
- build/linux
|
||||
- mkdir -vp build/$CI_JOB_NAME
|
||||
- godot --headless --verbose --export-release "Linux/X11" build/$CI_JOB_NAME/$EXPORT_NAME.x86_64
|
||||
- cd build && zip -r $ZIP_ARCHIVE_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"'
|
||||
|
||||
windows:
|
||||
stage: export
|
||||
extends: [ .export_presets ]
|
||||
when: manual
|
||||
script:
|
||||
- mkdir -v -p build/windows
|
||||
- godot --headless --verbose --export-release "Windows Desktop" build/windows/$EXPORT_NAME.exe
|
||||
artifacts:
|
||||
name: $EXPORT_NAME-$CI_JOB_NAME
|
||||
paths:
|
||||
- build/windows
|
||||
- mkdir -vp build/$CI_JOB_NAME
|
||||
- godot --headless --verbose --export-release "Windows Desktop" build/$CI_JOB_NAME/$EXPORT_NAME.exe
|
||||
- cd build && zip -r $ZIP_ARCHIVE_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"'
|
||||
|
||||
mac:
|
||||
stage: export
|
||||
extends: [ .export_presets ]
|
||||
when: manual
|
||||
script:
|
||||
- mkdir -v -p build/mac
|
||||
- godot --headless --verbose --export-release "Mac OSX" build/mac/$EXPORT_NAME.zip
|
||||
artifacts:
|
||||
name: $EXPORT_NAME-$CI_JOB_NAME
|
||||
paths:
|
||||
- build/mac
|
||||
|
||||
- mkdir -vp build/$CI_JOB_NAME
|
||||
- godot --headless --verbose --export-release "macOS" build/$CI_JOB_NAME/$ZIP_ARCHIVE_NAME
|
||||
- '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"'
|
||||
|
|
|
|||
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"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://b30y3pq4u5r0h"
|
||||
path="res://.godot/imported/albedo0.png-8dedb9e51f95ee8e69f9a00bccf9fb16.ctex"
|
||||
uid="uid://bm44ebnxqc82"
|
||||
path="res://.godot/imported/smoothing.png-6b454a779e636eaa20b6c6ac618bf82a.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://weapons/space_gun/assets/textures/albedo0.png"
|
||||
dest_files=["res://.godot/imported/albedo0.png-8dedb9e51f95ee8e69f9a00bccf9fb16.ctex"]
|
||||
source_file="res://addons/smoothing/smoothing.png"
|
||||
dest_files=["res://.godot/imported/smoothing.png-6b454a779e636eaa20b6c6ac618bf82a.ctex"]
|
||||
|
||||
[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 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 ExplosiveDamageComponent extends Area3D
|
||||
|
||||
@export var damage : int = 100
|
||||
@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():
|
||||
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)
|
||||
|
||||
for area in get_overlapping_areas():
|
||||
if area is HealthComponent and is_multiplayer_authority():
|
||||
area.damage.rpc(damage)
|
||||
area.damage.rpc(damage, damage_dealer.player_id)
|
||||
|
||||
set_physics_process(false)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,6 @@
|
|||
|
||||
[node name="ExplosiveDamage" type="Area3D"]
|
||||
collision_layer = 0
|
||||
collision_mask = 5
|
||||
collision_mask = 13
|
||||
monitorable = false
|
||||
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 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 HealthComponent extends Area3D
|
||||
|
|
@ -20,23 +20,23 @@ class_name HealthComponent extends Area3D
|
|||
health = value
|
||||
health_changed.emit(value)
|
||||
|
||||
signal health_zeroed
|
||||
signal health_changed(value : int)
|
||||
signal health_zeroed(killer_id : int)
|
||||
signal health_changed(value : float)
|
||||
|
||||
func _ready():
|
||||
func _ready() -> void:
|
||||
heal_full()
|
||||
|
||||
@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)
|
||||
if health == 0.0:
|
||||
health_zeroed.emit()
|
||||
health_zeroed.emit(damage_dealer_id)
|
||||
|
||||
@rpc("call_local")
|
||||
func _heal(amount : int):
|
||||
func _heal(amount : float) -> void:
|
||||
health = clampf(health + amount, 0.0, max_health)
|
||||
|
||||
func heal_full():
|
||||
func heal_full() -> void:
|
||||
if not is_multiplayer_authority():
|
||||
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="Shape3D" uid="uid://dkwljsgaflf31" path="res://entities/player/collision_shape.res" id="2_sgbmt"]
|
||||
|
||||
[node name="HealthComponent" type="Area3D"]
|
||||
collision_layer = 4
|
||||
collision_mask = 0
|
||||
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_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://clq4uym4arpv3"
|
||||
path="res://.godot/imported/SpaceGun.glb-ee1e940c9dd77150eaf36c6537feefef.scn"
|
||||
uid="uid://d3l7fvbdg6m5g"
|
||||
path="res://.godot/imported/flag.glb-0a51d316969707bbb012f3287265227f.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://weapons/space_gun/assets/SpaceGun.glb"
|
||||
dest_files=["res://.godot/imported/SpaceGun.glb-ee1e940c9dd77150eaf36c6537feefef.scn"]
|
||||
source_file="res://entities/flag/assets/flag.glb"
|
||||
dest_files=["res://.godot/imported/flag.glb-0a51d316969707bbb012f3287265227f.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
|
|
@ -29,17 +29,6 @@ animation/fps=30
|
|||
animation/trimming=false
|
||||
animation/remove_immutable_tracks=true
|
||||
import_script/path=""
|
||||
_subresources={
|
||||
"materials": {
|
||||
"_defaultMat": {
|
||||
"use_external/enabled": true,
|
||||
"use_external/path": ""
|
||||
},
|
||||
"dark": {
|
||||
"use_external/enabled": true,
|
||||
"use_external/path": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
_subresources={}
|
||||
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
|
||||
|
||||
@onready var animation_tree : AnimationTree = $AnimationTree
|
||||
@onready var spine_ik = $Node/Skeleton3D/SpineIK
|
||||
@onready var spine_ik_target = $SpineIKTarget
|
||||
@onready var spine_ik : SkeletonIK3D = $Node/Skeleton3D/SpineIK
|
||||
@onready var spine_ik_target : Node3D = $SpineIKTarget
|
||||
|
||||
enum GroundState { GROUND_STATE_GROUNDED, GROUND_STATE_MID_AIR, GROUND_STATE_DEAD }
|
||||
|
||||
func _ready():
|
||||
func _ready() -> void:
|
||||
spine_ik.start()
|
||||
|
||||
func _process(_delta):
|
||||
func _process(_delta : float) -> void:
|
||||
spine_ik_target.global_transform = spine_ik_target_attachment.global_transform
|
||||
|
||||
func set_locomotion(locomotion : Vector2, ground_speed_factor : float) -> void:
|
||||
animation_tree.set("parameters/Locomotion/blend_position", locomotion)
|
||||
animation_tree.set("parameters/GroundSpeed/scale", ground_speed_factor)
|
||||
|
||||
func set_ground_state(ground_state : GroundState):
|
||||
var transition_name = "grounded"
|
||||
func set_ground_state(ground_state : GroundState) -> void:
|
||||
var transition_name : String = "grounded"
|
||||
if ground_state == GroundState.GROUND_STATE_MID_AIR:
|
||||
transition_name = "mid_air"
|
||||
if ground_state == GroundState.GROUND_STATE_DEAD:
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
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={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
|
|
@ -13,12 +13,12 @@ generator_parameters={}
|
|||
[deps]
|
||||
|
||||
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]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/high_quality=true
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
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={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
|
|
@ -13,12 +13,12 @@ generator_parameters={}
|
|||
[deps]
|
||||
|
||||
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]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/high_quality=true
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=1
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
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={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
|
|
@ -13,12 +13,12 @@ generator_parameters={}
|
|||
[deps]
|
||||
|
||||
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]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/high_quality=true
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=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 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 Player extends RigidBody3D
|
||||
|
||||
enum PlayerState { PLAYER_ALIVE, PLAYER_DEAD }
|
||||
|
||||
@export var iff : Control
|
||||
|
||||
@export_category("Parameters")
|
||||
@export var ground_speed : float = 48 / 3.6 # m/s
|
||||
@export var aerial_control_force : int = 400
|
||||
@export var jump_height : float = 2.0
|
||||
@export var max_floor_angle : float = 60
|
||||
|
||||
@export_group("Jetpack")
|
||||
|
|
@ -31,97 +34,130 @@ enum PlayerState { PLAYER_ALIVE, PLAYER_DEAD }
|
|||
@export var jetpack_vertical_force : float = 800
|
||||
|
||||
@export_group("State")
|
||||
@export var player_state = PlayerState.PLAYER_ALIVE
|
||||
@export var player_id = 1:
|
||||
@export var player_state : PlayerState = PlayerState.PLAYER_ALIVE
|
||||
@export var player_id : int = 1:
|
||||
set(id):
|
||||
player_id = id
|
||||
$PlayerInput.set_multiplayer_authority(id)
|
||||
@export var nickname : String
|
||||
|
||||
@onready var input : PlayerInput = $PlayerInput
|
||||
@onready var camera = $SpringArm3D/Camera3D
|
||||
@onready var hud = $HUD
|
||||
@onready var iff = $ThirdPerson/IFF
|
||||
@onready var shape_cast = $ShapeCast3D
|
||||
@onready var weapon = $SpringArm3D/Inventory/SpaceGun
|
||||
@onready var camera : Camera3D = $Smoothing/SpringArm3D/Camera3D
|
||||
@onready var hud : CanvasLayer = $HUD
|
||||
@onready var shape_cast : ShapeCast3D = $ShapeCast3D
|
||||
@onready var weapon : Node3D = $Smoothing/SpringArm3D/Inventory/SpaceGun
|
||||
@onready var animation_player : AnimationPlayer = $AnimationPlayer
|
||||
@onready var health_component = $HealthComponent
|
||||
@onready var spring_arm_height = $SpringArm3D.position.y
|
||||
@onready var health_component : Area3D = $HealthComponent
|
||||
@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 flag_carry_attachment : Node3D = $Smoothing/SpringArm3D/FlagCarryAttachment
|
||||
@onready var _game_settings : Settings = get_node("/root/GlobalSettings")
|
||||
|
||||
signal died(player)
|
||||
signal energy_changed(energy)
|
||||
signal died(player : Player, killer_id : int)
|
||||
signal energy_changed(energy : float)
|
||||
|
||||
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 _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)
|
||||
health_component.health_changed.connect(hud._on_health_changed)
|
||||
health_component.health_changed.connect(iff._on_health_changed)
|
||||
health_component.health_changed.emit(health_component.health)
|
||||
health_component.health_zeroed.connect(_die)
|
||||
if _is_first_person():
|
||||
camera.current = true
|
||||
remove_child($ThirdPerson)
|
||||
else:
|
||||
remove_child($HUD)
|
||||
weapon.hide()
|
||||
health_component.health_zeroed.connect(die)
|
||||
|
||||
input.fired_primary.connect(_fire_primary)
|
||||
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()
|
||||
|
||||
func _fire_primary():
|
||||
func _fire_primary() -> void:
|
||||
if _is_player_dead():
|
||||
return
|
||||
if not weapon.can_fire():
|
||||
return
|
||||
var current_weapon_transform = weapon.transform
|
||||
var current_weapon_transform : Transform3D = weapon.transform
|
||||
weapon.transform = _original_weapon_transform
|
||||
weapon.fire_primary()
|
||||
weapon.transform = current_weapon_transform
|
||||
if _is_first_person():
|
||||
if _is_pawn():
|
||||
animation_player.stop()
|
||||
animation_player.play("shoot")
|
||||
|
||||
func _jump():
|
||||
func _jump() -> void:
|
||||
if _is_player_dead():
|
||||
return
|
||||
_jumping = true
|
||||
|
||||
func _throw_flag() -> void:
|
||||
flag_carry_component.throw(linear_velocity)
|
||||
|
||||
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:
|
||||
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():
|
||||
apply_force(direction * aerial_control_force)
|
||||
|
||||
func _handle_jetpack(delta, direction):
|
||||
func _handle_jetpack(direction : Vector3) -> void:
|
||||
if input.jetting:
|
||||
if energy > 0:
|
||||
var up_vector = Vector3.UP * jetpack_vertical_force * jetpack_force_factor
|
||||
var side_vector = direction * jetpack_horizontal_force * jetpack_force_factor
|
||||
var up_vector : Vector3 = Vector3.UP * jetpack_vertical_force * jetpack_force_factor
|
||||
var side_vector : Vector3 = direction * jetpack_horizontal_force * jetpack_force_factor
|
||||
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:
|
||||
energy += energy_charge_rate * delta
|
||||
|
||||
energy = clamp(energy, 0, energy_max)
|
||||
energy_changed.emit(energy)
|
||||
|
||||
func _process(_delta):
|
||||
func _process(_delta : float) -> void:
|
||||
if _is_player_dead():
|
||||
iff.hide()
|
||||
return
|
||||
else:
|
||||
iff.show()
|
||||
if not _is_first_person():
|
||||
$ThirdPerson/PlayerMesh.global_transform.basis = Basis.from_euler(Vector3(0.0, input.camera_rotation.x + PI, 0.0))
|
||||
if not _is_pawn():
|
||||
$Smoothing/ThirdPerson/PlayerMesh.global_transform.basis = Basis.from_euler(Vector3(0.0, input.camera_rotation.x + PI, 0.0))
|
||||
else:
|
||||
if animation_player.current_animation == "shoot":
|
||||
pass
|
||||
|
|
@ -129,21 +165,25 @@ func _process(_delta):
|
|||
animation_player.play("idle")
|
||||
%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
|
||||
var _input_dir = input.direction
|
||||
var _input_dir : Vector2 = input.direction
|
||||
# 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()
|
||||
|
||||
if _is_player_dead():
|
||||
return
|
||||
|
||||
# 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_jetpack(delta, _direction)
|
||||
_handle_aerial_control(_direction)
|
||||
_handle_jetpack(_direction)
|
||||
|
||||
# handle ski
|
||||
if _is_skiing():
|
||||
|
|
@ -154,9 +194,9 @@ func _physics_process(delta):
|
|||
if is_on_floor():
|
||||
if not _direction.is_zero_approx() and not _is_skiing():
|
||||
# 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
|
||||
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
|
||||
if slope_angle <= max_floor_angle:
|
||||
# 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)
|
||||
|
||||
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
|
||||
|
||||
func _update_third_person_animations():
|
||||
if _is_first_person():
|
||||
func _integrate_forces(_state : PhysicsDirectBodyState3D) -> void:
|
||||
_handle_movement()
|
||||
|
||||
func _update_third_person_animations() -> void:
|
||||
if _is_pawn():
|
||||
return
|
||||
|
||||
var tp_player : Vanguard = $ThirdPerson/PlayerMesh
|
||||
var tp_player : Vanguard = $Smoothing/ThirdPerson/PlayerMesh
|
||||
|
||||
if _is_player_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)
|
||||
else:
|
||||
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
|
||||
tp_player.set_locomotion(Vector2(local_velocity.x, local_velocity.z), bias)
|
||||
|
||||
func _is_player_dead():
|
||||
return player_state == PlayerState.PLAYER_DEAD
|
||||
func _is_player_dead() -> bool:
|
||||
return player_state != PlayerState.PLAYER_ALIVE
|
||||
|
||||
func _die():
|
||||
func die(killer_id : int) -> void:
|
||||
flag_carry_component.drop()
|
||||
player_state = PlayerState.PLAYER_DEAD
|
||||
if _is_first_person():
|
||||
animation_player.stop()
|
||||
if _is_pawn():
|
||||
animation_player.play("death")
|
||||
var tween = create_tween()
|
||||
tween.tween_interval(4)
|
||||
tween.tween_callback(func():
|
||||
died.emit(self)
|
||||
if _is_first_person():
|
||||
animation_player.stop()
|
||||
)
|
||||
died.emit(self, killer_id)
|
||||
|
||||
func respawn(location):
|
||||
func respawn(location : Vector3) -> void:
|
||||
player_state = PlayerState.PLAYER_ALIVE
|
||||
linear_velocity = Vector3()
|
||||
health_component.heal_full()
|
||||
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="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="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://c8co0qa2omjmh" path="res://weapons/space_gun/space_gun.tscn" id="4_lhn5w"]
|
||||
[ext_resource type="PackedScene" uid="uid://dn1tcakam5egs" path="res://weapons/space_gun/projectile.tscn" id="5_lvaut"]
|
||||
[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://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="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"]
|
||||
resource_local_to_scene = true
|
||||
|
|
@ -26,50 +27,50 @@ length = 0.001
|
|||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
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/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"times": PackedFloat32Array(0, 0.0001),
|
||||
"transitions": PackedFloat32Array(1, 1),
|
||||
"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/imported = false
|
||||
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/loop_wrap = true
|
||||
tracks/1/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 0,
|
||||
"values": [Vector3(0, 3.14159, 0)]
|
||||
"values": [Vector3(0, 0, 0)]
|
||||
}
|
||||
tracks/2/type = "value"
|
||||
tracks/2/imported = false
|
||||
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/loop_wrap = true
|
||||
tracks/2/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 0,
|
||||
"values": [Vector3(0, 0.5, 0)]
|
||||
"values": [Vector3(0.15, -0.3, -0.2)]
|
||||
}
|
||||
tracks/3/type = "value"
|
||||
tracks/3/imported = false
|
||||
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/loop_wrap = true
|
||||
tracks/3/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 0,
|
||||
"values": [Vector3(0, 0, 0)]
|
||||
"values": [Vector3(0, 3.14159, 0)]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_yqgrk"]
|
||||
|
|
@ -77,7 +78,7 @@ resource_name = "death"
|
|||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("SpringArm3D:position")
|
||||
tracks/0/path = NodePath("Smoothing/SpringArm3D:position")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
|
|
@ -89,7 +90,7 @@ tracks/0/keys = {
|
|||
tracks/1/type = "value"
|
||||
tracks/1/imported = false
|
||||
tracks/1/enabled = true
|
||||
tracks/1/path = NodePath("SpringArm3D:rotation")
|
||||
tracks/1/path = NodePath("Smoothing/SpringArm3D:rotation")
|
||||
tracks/1/interp = 1
|
||||
tracks/1/loop_wrap = true
|
||||
tracks/1/keys = {
|
||||
|
|
@ -106,26 +107,26 @@ loop_mode = 1
|
|||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
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/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 1.5),
|
||||
"transitions": PackedFloat32Array(-2, -2),
|
||||
"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/imported = false
|
||||
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/loop_wrap = true
|
||||
tracks/1/keys = {
|
||||
"times": PackedFloat32Array(0, 1.5),
|
||||
"transitions": PackedFloat32Array(-2, -2),
|
||||
"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"]
|
||||
|
|
@ -133,19 +134,19 @@ resource_name = "shoot"
|
|||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
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/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 1),
|
||||
"transitions": PackedFloat32Array(0.5, 1),
|
||||
"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/imported = false
|
||||
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/loop_wrap = true
|
||||
tracks/1/keys = {
|
||||
|
|
@ -179,6 +180,9 @@ properties/3/replication_mode = 2
|
|||
properties/4/path = NodePath(".:player_state")
|
||||
properties/4/spawn = true
|
||||
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"]
|
||||
properties/0/path = NodePath(".:direction")
|
||||
|
|
@ -194,55 +198,57 @@ properties/3/path = NodePath(".:skiing")
|
|||
properties/3/spawn = false
|
||||
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_y = true
|
||||
axis_lock_angular_z = true
|
||||
mass = 75.0
|
||||
physics_material_override = SubResource("PhysicsMaterial_clur0")
|
||||
can_sleep = false
|
||||
continuous_cd = true
|
||||
script = ExtResource("1_mk68k")
|
||||
iff = NodePath("Smoothing/ThirdPerson/IFF")
|
||||
jump_height = 1.5
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
|
||||
visible = false
|
||||
mesh = SubResource("CapsuleMesh_vmqfq")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
shape = ExtResource("2_8rtw3")
|
||||
shape = ExtResource("2_vjqny")
|
||||
|
||||
[node name="ShapeCast3D" type="ShapeCast3D" parent="."]
|
||||
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)
|
||||
collision_mask = 2147483648
|
||||
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="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="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="."]
|
||||
libraries = {
|
||||
"": SubResource("AnimationLibrary_hg307")
|
||||
}
|
||||
autoplay = "idle"
|
||||
autoplay = "shoot"
|
||||
playback_default_blend_time = 0.05
|
||||
|
||||
[node name="ServerSynchronizer" type="MultiplayerSynchronizer" parent="."]
|
||||
|
|
@ -253,15 +259,41 @@ root_path = NodePath(".")
|
|||
replication_config = SubResource("SceneReplicationConfig_5j4ew")
|
||||
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)
|
||||
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)
|
||||
|
||||
[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")
|
||||
player = NodePath("../..")
|
||||
|
|
|
|||
|
|
@ -1,71 +1,73 @@
|
|||
# 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 PlayerInput extends MultiplayerSynchronizer
|
||||
|
||||
@export var jetting = false
|
||||
@export var skiing = false
|
||||
@export var direction = Vector2.ZERO
|
||||
@export var jetting : bool = false
|
||||
@export var skiing : bool = false
|
||||
@export var direction : Vector2 = Vector2.ZERO
|
||||
@export var camera_rotation : Vector2
|
||||
@export var MOUSE_SENSITIVITY : float = .6
|
||||
@export var inverted_y_axis : bool = false
|
||||
|
||||
signal jumped
|
||||
signal fired_primary
|
||||
signal throwed_flag
|
||||
|
||||
var _mouse_position: Vector2
|
||||
|
||||
func _ready():
|
||||
var has_authority = is_multiplayer_authority()
|
||||
func _ready() -> void:
|
||||
var has_authority : bool = is_multiplayer_authority()
|
||||
set_process(has_authority)
|
||||
set_process_unhandled_input(has_authority)
|
||||
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
||||
|
||||
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
|
||||
if event is InputEventMouseMotion:
|
||||
if mouse_mode == Input.MOUSE_MODE_CAPTURED:
|
||||
# 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")
|
||||
if Input.is_action_just_pressed("jump_and_jet"):
|
||||
_jump.rpc()
|
||||
if Input.is_action_just_pressed("fire_primary"):
|
||||
_fire_primary.rpc()
|
||||
if Input.is_action_just_pressed("throw_flag"):
|
||||
_throw_flag.rpc()
|
||||
jetting = Input.is_action_pressed("jump_and_jet")
|
||||
skiing = Input.is_action_pressed("ski")
|
||||
|
||||
func _physics_process(delta):
|
||||
_update_camera(delta)
|
||||
|
||||
@rpc("call_local")
|
||||
func _jump():
|
||||
func _jump() -> void:
|
||||
jumped.emit()
|
||||
|
||||
@rpc("call_local")
|
||||
func _fire_primary():
|
||||
func _fire_primary() -> void:
|
||||
fired_primary.emit()
|
||||
|
||||
func _update_camera(delta):
|
||||
# clamp vertical rotation (head motion)
|
||||
camera_rotation.y -= _mouse_position.y * delta
|
||||
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
|
||||
@rpc("call_local")
|
||||
func _throw_flag() -> void:
|
||||
throwed_flag.emit()
|
||||
|
|
|
|||
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 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 DummyTarget extends RigidBody3D
|
||||
|
|
@ -24,8 +24,9 @@ var start_pos : Vector3
|
|||
func _ready() -> void:
|
||||
health_component.health_zeroed.connect(spawn)
|
||||
start_pos = global_position
|
||||
$TargetMesh/AnimationPlayer.play("gunTwoHanded")
|
||||
|
||||
func spawn():
|
||||
func spawn(_killer_id : int) -> void:
|
||||
hide()
|
||||
collision_shape_3d.disabled = true
|
||||
await get_tree().create_timer(respawn_time).timeout
|
||||
|
|
|
|||
|
|
@ -1,103 +1,25 @@
|
|||
[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="PackedScene" uid="uid://b83leo1ca47d7" path="res://entities/target_dummy/assets/player_mesh.blend" id="2_x73k8"]
|
||||
[ext_resource type="PackedScene" uid="uid://bof3mg7wgxrmn" path="res://components/health_component.tscn" id="3_g1ap4"]
|
||||
[ext_resource type="Script" path="res://entities/target_dummy/target_dummy.gd" id="1_iup5v"]
|
||||
[ext_resource type="Shape3D" uid="uid://cb8esdlnottdn" path="res://entities/player/collision_shape.tres" id="2_i5k5j"]
|
||||
[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"]
|
||||
radius = 0.3
|
||||
|
||||
[node name="TargetDummy" type="RigidBody3D"]
|
||||
[node name="DummyTarget" type="RigidBody3D"]
|
||||
collision_layer = 2147483649
|
||||
collision_mask = 2147483649
|
||||
axis_lock_angular_x = true
|
||||
axis_lock_angular_y = true
|
||||
axis_lock_angular_z = true
|
||||
mass = 75.0
|
||||
continuous_cd = true
|
||||
script = ExtResource("1_r02ch")
|
||||
|
||||
[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"
|
||||
script = ExtResource("1_iup5v")
|
||||
|
||||
[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")]
|
||||
max_health = 300
|
||||
[node name="HealthComponent" parent="." instance=ExtResource("4_l1exy")]
|
||||
|
||||
[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 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 Projectile extends Node3D
|
||||
|
|
@ -19,32 +19,34 @@ class_name Projectile extends Node3D
|
|||
@export var speed : float = 78.4 # m/s
|
||||
@export var lifespan : float = 5.0 # in seconds
|
||||
|
||||
@onready var shape_cast = $ShapeCast3D
|
||||
@onready var game = get_tree().get_current_scene()
|
||||
@onready var shape_cast : ShapeCast3D = $ShapeCast3D
|
||||
@onready var game : Node3D = get_tree().get_current_scene()
|
||||
|
||||
var velocity : Vector3 = Vector3.ZERO
|
||||
var shooter : Player
|
||||
|
||||
func _ready():
|
||||
var lifespan_timer = Timer.new()
|
||||
func _ready() -> void:
|
||||
var lifespan_timer : Timer = Timer.new()
|
||||
lifespan_timer.wait_time = lifespan
|
||||
lifespan_timer.one_shot = true
|
||||
lifespan_timer.autostart = true
|
||||
lifespan_timer.timeout.connect(self_destruct)
|
||||
add_child(lifespan_timer)
|
||||
|
||||
func self_destruct():
|
||||
func self_destruct() -> void:
|
||||
explode(position)
|
||||
|
||||
func explode(spawn_location):
|
||||
var spawned_explosion = EXPLOSION.instantiate()
|
||||
func explode(spawn_location : Vector3) -> void:
|
||||
var spawned_explosion : Node = EXPLOSION.instantiate()
|
||||
spawned_explosion.position = spawn_location
|
||||
spawned_explosion.shooter = shooter
|
||||
game.add_child(spawned_explosion)
|
||||
queue_free()
|
||||
|
||||
func _physics_process(delta):
|
||||
var previous_position = global_position
|
||||
func _physics_process(delta : float) -> void:
|
||||
var previous_position : Vector3 = global_position
|
||||
global_position += velocity * delta
|
||||
shape_cast.target_position = to_local(previous_position)
|
||||
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)
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
[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="PackedScene" uid="uid://8atq41j7wd55" path="res://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.gd" id="1_4j1dp"]
|
||||
[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://entities/weapons/space_gun/projectile_trail.gd" id="3_ygqbh"]
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_4a265"]
|
||||
transparency = 1
|
||||
|
|
@ -45,4 +45,5 @@ shape = SubResource("SphereShape3D_umtte")
|
|||
target_position = Vector3(0, 0, 0)
|
||||
margin = 0.1
|
||||
max_results = 1
|
||||
collision_mask = 2147483649
|
||||
debug_shape_custom_color = Color(1, 0, 0, 1)
|
||||
|
|
@ -1,23 +1,26 @@
|
|||
# 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 Node3D
|
||||
|
||||
@onready var fire = $Fire
|
||||
var shooter : Player
|
||||
|
||||
@onready var fire : GPUParticles3D = $Fire
|
||||
@onready var explosive_damage : ExplosiveDamageComponent = $ExplosiveDamageComponent
|
||||
var explosion_effect_pending : bool = false
|
||||
|
||||
func _ready():
|
||||
func _ready() -> void:
|
||||
explosive_damage.damage_dealer = shooter
|
||||
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"]
|
||||
|
||||
[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"]
|
||||
|
||||
[sub_resource type="Curve" id="Curve_rg204"]
|
||||
|
|
@ -1,22 +1,22 @@
|
|||
# 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 Trail3D extends MeshInstance3D
|
||||
|
||||
var _points = [] # 3D points of trail
|
||||
var _widths = [] # Calculated widths of trail
|
||||
var _lifespans = [] # Trail point lifespans
|
||||
var _points : Array = [] # 3D points of trail
|
||||
var _widths : Array = [] # Calculated widths of trail
|
||||
var _lifespans : Array = [] # Trail point lifespans
|
||||
|
||||
@export var _trail_enabled : bool = true # Is trail shown?
|
||||
|
||||
|
|
@ -33,7 +33,7 @@ var _lifespans = [] # Trail point lifespans
|
|||
|
||||
var _old_pos : Vector3 # Previous pos
|
||||
|
||||
func _append_point():
|
||||
func _append_point() -> void:
|
||||
_points.append(get_global_transform().origin)
|
||||
_widths.append([
|
||||
get_global_transform().basis.x * _from_width,
|
||||
|
|
@ -41,52 +41,52 @@ func _append_point():
|
|||
])
|
||||
_lifespans.append(0.0)
|
||||
|
||||
func _remove_point(i):
|
||||
func _remove_point(i : int) -> void:
|
||||
_points.remove_at(i)
|
||||
_widths.remove_at(i)
|
||||
_lifespans.remove_at(i)
|
||||
|
||||
func _ready():
|
||||
func _ready() -> void:
|
||||
_old_pos = get_global_transform().origin
|
||||
mesh = ImmediateMesh.new()
|
||||
|
||||
func _process(delta):
|
||||
func _process(delta : float) -> void:
|
||||
if(_old_pos - get_global_transform().origin).length() > _motion_delta and _trail_enabled:
|
||||
_append_point() # Create new point
|
||||
_old_pos = get_global_transform().origin # Update previous position to current position coordinates
|
||||
|
||||
|
||||
# Update the lifespan
|
||||
var p = 0
|
||||
var max_points = _points.size()
|
||||
var p : int = 0
|
||||
var max_points : int = _points.size()
|
||||
while p < max_points:
|
||||
_lifespans[p] += delta
|
||||
if _lifespans[p] > _lifespan:
|
||||
_remove_point(p)
|
||||
p -= 1
|
||||
if (p < 0): p = 0
|
||||
|
||||
|
||||
max_points = _points.size()
|
||||
p += 1
|
||||
|
||||
|
||||
mesh.clear_surfaces()
|
||||
|
||||
|
||||
# If less than 2 points, stop rendering trail
|
||||
if _points.size() < 2:
|
||||
return
|
||||
|
||||
|
||||
# Render new mesh for each point
|
||||
mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLE_STRIP)
|
||||
|
||||
|
||||
for i in range(_points.size()):
|
||||
var t = float(i) / (_points.size() - 1.0)
|
||||
var curr_color = _start_color.lerp(_end_color, 1 - t)
|
||||
var t : float = float(i) / (_points.size() - 1.0)
|
||||
var curr_color : Color = _start_color.lerp(_end_color, 1 - t)
|
||||
mesh.surface_set_color(curr_color)
|
||||
|
||||
var curr_width = _widths[i][0] - pow(1 - t, _scale_acceleration) * _widths[i][1]
|
||||
|
||||
var t0 = i / _points.size()
|
||||
var t1 = t
|
||||
|
||||
|
||||
var curr_width : Vector3 = _widths[i][0] - pow(1 - t, _scale_acceleration) * _widths[i][1]
|
||||
|
||||
var t0 : float = i / _points.size()
|
||||
var t1 : float = t
|
||||
|
||||
mesh.surface_set_uv(Vector2(t0, 0))
|
||||
mesh.surface_add_vertex(to_local(_points[i] + curr_width))
|
||||
mesh.surface_set_uv(Vector2(t1, 1))
|
||||
|
|
@ -1,24 +1,25 @@
|
|||
# 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 Node3D
|
||||
class_name SpaceGun
|
||||
|
||||
@export var PROJECTILE : PackedScene
|
||||
@export var holder : Player
|
||||
|
||||
@onready var nozzle = $Nozzle
|
||||
@onready var inventory = get_parent()
|
||||
@onready var nozzle : Node3D = $Nozzle
|
||||
@onready var inventory : Node3D = get_parent()
|
||||
|
||||
enum WeaponState { WEAPON_READY, WEAPON_RELOADING }
|
||||
|
||||
|
|
@ -27,20 +28,21 @@ var weapon_state : WeaponState = WeaponState.WEAPON_READY
|
|||
const inheritance : float = .5 # ratio
|
||||
const reload_time : float = 1. # seconds
|
||||
|
||||
func can_fire():
|
||||
func can_fire() -> bool:
|
||||
return weapon_state == WeaponState.WEAPON_READY
|
||||
|
||||
func fire_primary():
|
||||
func fire_primary() -> void:
|
||||
if not can_fire():
|
||||
return
|
||||
|
||||
var projectile = PROJECTILE.instantiate()
|
||||
var projectile : Node = PROJECTILE.instantiate()
|
||||
projectile.transform = nozzle.global_transform
|
||||
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)
|
||||
inventory.owner.add_sibling(projectile)
|
||||
var collider = projectile.shape_cast
|
||||
var collider : ShapeCast3D = projectile.shape_cast
|
||||
collider.add_exception(inventory.owner)
|
||||
weapon_state = WeaponState.WEAPON_RELOADING
|
||||
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"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cvtqt0k2ewd07"
|
||||
path.s3tc="res://.godot/imported/albedo.png-7f543d432ab75668956abd5bcc51a13b.s3tc.ctex"
|
||||
uid="uid://btdbu0qbe1646"
|
||||
path.bptc="res://.godot/imported/kloppenheim_06_puresky_2k.exr-ec828ffc9b05b2c03fb35e84cd230d2d.bptc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
|
|
@ -11,18 +11,18 @@ metadata={
|
|||
|
||||
[deps]
|
||||
|
||||
source_file="res://weapons/space_gun/assets/albedo.png"
|
||||
dest_files=["res://.godot/imported/albedo.png-7f543d432ab75668956abd5bcc51a13b.s3tc.ctex"]
|
||||
source_file="res://environments/skyboxes/kloppenheim_06_puresky_2k.exr"
|
||||
dest_files=["res://.godot/imported/kloppenheim_06_puresky_2k.exr-ec828ffc9b05b2c03fb35e84cd230d2d.bptc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/high_quality=true
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=true
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
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"]
|
||||
script/source = "extends CanvasLayer
|
||||
class_name HUD
|
||||
script/source = "class_name HUD extends CanvasLayer
|
||||
|
||||
@onready var _health_bar = $HealthBar
|
||||
@onready var _energy_bar = $EnergyBar
|
||||
@export_category(\"Vitals\")
|
||||
@export var _health_bar : ProgressBar
|
||||
@export var _energy_bar : ProgressBar
|
||||
|
||||
func _ready():
|
||||
_update_health_bar(100)
|
||||
_update_energy_bar(100)
|
||||
func _ready() -> void:
|
||||
_update_health_bar(100.)
|
||||
_update_energy_bar(100.)
|
||||
|
||||
func _update_energy_bar(energy) -> void:
|
||||
func _update_energy_bar(energy : float) -> void:
|
||||
_energy_bar.value = energy
|
||||
|
||||
func _on_energy_changed(new_energy) -> void:
|
||||
func _on_energy_changed(new_energy : float) -> void:
|
||||
_update_energy_bar(new_energy)
|
||||
|
||||
func _update_health_bar(health) -> void:
|
||||
func _update_health_bar(health : float) -> void:
|
||||
_health_bar.value = health
|
||||
|
||||
func _on_health_changed(new_health) -> void:
|
||||
func _on_health_changed(new_health : float) -> void:
|
||||
_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"]
|
||||
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.
|
||||
func _ready():
|
||||
pass # Replace with function body.
|
||||
func _ready() -> void:
|
||||
if not OS.is_debug_build():
|
||||
queue_free()
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(_delta):
|
||||
func _process(_delta : float) -> void:
|
||||
text = \"\"
|
||||
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 += \"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")
|
||||
|
||||
[node name="HealthBar" type="ProgressBar" parent="."]
|
||||
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
|
||||
_health_bar = NodePath("MarginContainer/HBoxContainer/VBoxContainer/HealthBar")
|
||||
_energy_bar = NodePath("MarginContainer/HBoxContainer/VBoxContainer/EnergyBar")
|
||||
|
||||
[node name="DebugLabel" type="Label" parent="."]
|
||||
anchors_preset = 2
|
||||
anchor_top = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_left = 20.0
|
||||
offset_top = -33.0
|
||||
offset_top = 20.0
|
||||
offset_right = 21.0
|
||||
offset_bottom = -10.0
|
||||
grow_vertical = 0
|
||||
offset_bottom = 43.0
|
||||
script = SubResource("GDScript_w8l21")
|
||||
|
||||
[node name="Reticle" type="Control" parent="."]
|
||||
layout_mode = 3
|
||||
[node name="Reticle" type="ColorRect" parent="."]
|
||||
material = SubResource("ShaderMaterial_7blp5")
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -20.0
|
||||
offset_top = -20.0
|
||||
offset_right = 20.0
|
||||
offset_bottom = 20.0
|
||||
offset_left = -1.5
|
||||
offset_top = -1.5
|
||||
offset_right = 1.5
|
||||
offset_bottom = 1.5
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="LineBottom" type="Line2D" parent="Reticle"]
|
||||
position = Vector2(13, 4)
|
||||
points = PackedVector2Array(7, 19, 7, 31)
|
||||
width = 2.0
|
||||
[node name="MarginContainer" type="MarginContainer" parent="."]
|
||||
anchors_preset = 12
|
||||
anchor_top = 1.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"]
|
||||
position = Vector2(36, 13)
|
||||
rotation = 1.5708
|
||||
points = PackedVector2Array(7, 19, 7, 31)
|
||||
width = 2.0
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="LineTop" type="Line2D" parent="Reticle"]
|
||||
position = Vector2(13, -14)
|
||||
points = PackedVector2Array(7, 19, 7, 31)
|
||||
width = 2.0
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_stretch_ratio = 0.2
|
||||
theme_override_constants/separation = 6
|
||||
|
||||
[node name="LineRight" type="Line2D" parent="Reticle"]
|
||||
position = Vector2(54, 13)
|
||||
rotation = 1.5708
|
||||
points = PackedVector2Array(7, 19, 7, 31)
|
||||
width = 2.0
|
||||
[node name="HealthBar" 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 = 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"]
|
||||
|
||||
|
|
@ -8,88 +8,144 @@ script/source = "class_name BootMenu extends CanvasLayer
|
|||
|
||||
signal start_demo
|
||||
|
||||
func _on_demo_pressed():
|
||||
func _on_demo_pressed() -> void:
|
||||
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"]
|
||||
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"]
|
||||
script/source = "class_name MultiplayerPanel extends PanelContainer
|
||||
script/source = "class_name Multiplayer extends PanelContainer
|
||||
|
||||
const DEFAULT_HOST : String = \"localhost\"
|
||||
const DEFAULT_PORT : int = 9000
|
||||
const CONFIG_FILE_PATH : String = \"user://profile.cfg\"
|
||||
|
||||
var _join_address = RegEx.new()
|
||||
var _registered_ports = RegEx.new()
|
||||
var _join_address : RegEx = RegEx.new()
|
||||
var _registered_ports : RegEx = RegEx.new()
|
||||
var _config_file : ConfigFile = ConfigFile.new()
|
||||
|
||||
signal start_server(port)
|
||||
signal join_server(host, port)
|
||||
signal start_server(port : int)
|
||||
signal join_server(host : String, port : int)
|
||||
|
||||
@onready var modal : Control = $Modal
|
||||
@onready var menu : CanvasLayer = get_parent()
|
||||
@export var tab_container : TabContainer
|
||||
|
||||
func _ready():
|
||||
func _ready() -> void:
|
||||
# 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])$')
|
||||
_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
|
||||
|
||||
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()
|
||||
owner.get_node(\"Main\").show()
|
||||
|
||||
func _on_quit_pressed():
|
||||
func _on_quit_pressed() -> void:
|
||||
get_tree().quit()
|
||||
|
||||
func _on_host_pressed():
|
||||
var port = DEFAULT_PORT
|
||||
func _on_host_pressed() -> void:
|
||||
var port : int = DEFAULT_PORT
|
||||
# check for registered ports number matches
|
||||
if %ServerPort.text:
|
||||
var result = _registered_ports.search(%ServerPort.text)
|
||||
var result : RegExMatch = _registered_ports.search(%ServerPort.text)
|
||||
if result: # port is valid
|
||||
port = int(result.get_string())
|
||||
else: # port is not valid
|
||||
push_warning(\"A valid port number in the range 1024-65535 is required.\")
|
||||
return
|
||||
|
||||
start_server.emit(port)
|
||||
|
||||
func _on_join_pressed():
|
||||
var addr = [DEFAULT_HOST, DEFAULT_PORT]
|
||||
start_server.emit(port, %ProfileName.text)
|
||||
|
||||
func _on_join_pressed() -> void:
|
||||
var addr : Array = [DEFAULT_HOST, DEFAULT_PORT]
|
||||
# validate join address input
|
||||
var result = _join_address.search(%JoinAddress.text)
|
||||
var result : RegExMatch = _join_address.search(%JoinAddress.text)
|
||||
if result: # address is valid
|
||||
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)
|
||||
|
||||
$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()
|
||||
menu.hide()
|
||||
|
||||
func _on_connection_failed():
|
||||
func _on_connection_failed() -> void:
|
||||
$Modal.hide()
|
||||
"
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_snh7i"]
|
||||
bg_color = Color(0, 0.5, 0.5, 0.25)
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ky5sv"]
|
||||
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
|
||||
|
||||
func _on_multiplayer_pressed():
|
||||
hide()
|
||||
owner.get_node(\"Multiplayer\").show()
|
||||
|
||||
func _on_quit_pressed():
|
||||
get_tree().quit()
|
||||
const WINDOW_MODE_OPTIONS = [DisplayServer.WINDOW_MODE_WINDOWED, DisplayServer.WINDOW_MODE_FULLSCREEN]
|
||||
|
||||
@onready var _game_settings : Settings = get_node(\"/root/GlobalSettings\")
|
||||
|
||||
@export var tab_container : TabContainer
|
||||
|
||||
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"]
|
||||
script = SubResource("GDScript_jd8xf")
|
||||
|
||||
|
|
@ -103,7 +159,7 @@ mouse_filter = 2
|
|||
texture = ExtResource("1_ph586")
|
||||
stretch_mode = 6
|
||||
|
||||
[node name="Multiplayer" type="PanelContainer" parent="."]
|
||||
[node name="Multiplayer" type="PanelContainer" parent="." node_paths=PackedStringArray("tab_container")]
|
||||
visible = false
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
|
|
@ -112,6 +168,7 @@ grow_horizontal = 2
|
|||
grow_vertical = 2
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_krqeq")
|
||||
script = SubResource("GDScript_tc1bm")
|
||||
tab_container = NodePath("MarginContainer/VBoxContainer/TabContainer")
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="Multiplayer"]
|
||||
layout_mode = 2
|
||||
|
|
@ -120,15 +177,19 @@ theme_override_constants/margin_top = 20
|
|||
theme_override_constants/margin_right = 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
|
||||
|
||||
[node name="TabContainer" type="TabContainer" parent="Multiplayer/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
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
|
||||
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
|
||||
offset_right = 1116.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_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
|
||||
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
|
||||
size_flags_horizontal = 3
|
||||
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
|
||||
disabled = true
|
||||
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
|
||||
disabled = true
|
||||
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
|
||||
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
|
||||
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
|
||||
size_flags_horizontal = 3
|
||||
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
|
||||
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
|
||||
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
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Newblood"
|
||||
|
||||
[node name="Join" type="TabBar" parent="Multiplayer/MarginContainer/TabContainer"]
|
||||
[node name="Join" type="TabBar" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer"]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
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
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
|
|
@ -200,47 +283,65 @@ theme_override_constants/margin_top = 20
|
|||
theme_override_constants/margin_right = 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
|
||||
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
|
||||
size_flags_horizontal = 3
|
||||
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
|
||||
text = "Join"
|
||||
|
||||
[node name="Spacer" type="MarginContainer" parent="Multiplayer/MarginContainer/TabContainer/Join/MarginContainer/HBoxContainer/LeftBox"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
[node name="Bottom" type="VBoxContainer" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Join/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="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
|
||||
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
|
||||
size_flags_horizontal = 3
|
||||
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
|
||||
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
|
||||
layout_mode = 2
|
||||
placeholder_text = "localhost"
|
||||
|
||||
[node name="Host" type="TabBar" parent="Multiplayer/MarginContainer/TabContainer"]
|
||||
[node name="Host" type="TabBar" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer"]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
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
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
|
|
@ -252,37 +353,55 @@ theme_override_constants/margin_top = 20
|
|||
theme_override_constants/margin_right = 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
|
||||
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
|
||||
size_flags_horizontal = 3
|
||||
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
|
||||
text = "Host"
|
||||
|
||||
[node name="Spacer" type="MarginContainer" parent="Multiplayer/MarginContainer/TabContainer/Host/MarginContainer/HBoxContainer/LeftBox"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
[node name="Bottom" type="VBoxContainer" parent="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Host/MarginContainer/HBoxContainer/LeftBox"]
|
||||
layout_mode = 1
|
||||
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
|
||||
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
|
||||
size_flags_horizontal = 3
|
||||
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
|
||||
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
|
||||
layout_mode = 2
|
||||
placeholder_text = "9000"
|
||||
|
|
@ -306,51 +425,250 @@ grow_horizontal = 2
|
|||
grow_vertical = 2
|
||||
text = "CONNECTING..."
|
||||
|
||||
[node name="Main" type="PanelContainer" parent="."]
|
||||
anchors_preset = 9
|
||||
[node name="Settings" type="PanelContainer" parent="." node_paths=PackedStringArray("tab_container")]
|
||||
visible = false
|
||||
anchors_preset = 15
|
||||
anchor_right = 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
|
||||
size_flags_horizontal = 0
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_snh7i")
|
||||
script = SubResource("GDScript_yqbr7")
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_c4ymk")
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="Main"]
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="Main"]
|
||||
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_right = 20
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="Main/MarginContainer"]
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="Main/HBoxContainer/PanelContainer/MarginContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 10
|
||||
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
|
||||
theme_override_font_sizes/font_size = 32
|
||||
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
|
||||
theme_override_font_sizes/font_size = 32
|
||||
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
|
||||
theme_override_font_sizes/font_size = 32
|
||||
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="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/TabContainer/Profile/MarginContainer/HBoxContainer/LeftBox/Quit" to="Multiplayer" method="_on_quit_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/TabContainer/Join/MarginContainer/HBoxContainer/LeftBox/Menu" to="Multiplayer" method="_on_menu_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/TabContainer/Host/MarginContainer/HBoxContainer/LeftBox/Host" to="Multiplayer" method="_on_host_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/TabContainer/Host/MarginContainer/HBoxContainer/LeftBox/Quit" to="Multiplayer" method="_on_quit_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="Main/MarginContainer/VBoxContainer/Demo" to="." method="_on_demo_pressed"]
|
||||
[connection signal="pressed" from="Main/MarginContainer/VBoxContainer/Multiplayer" to="Main" method="_on_multiplayer_pressed"]
|
||||
[connection signal="pressed" from="Main/MarginContainer/VBoxContainer/Quit" to="Main" method="_on_quit_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/VBoxContainer/TabContainer/Profile/MarginContainer/HBoxContainer/LeftBox/Bottom/MainMenu" to="." method="_on_main_menu_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/VBoxContainer/TabContainer/Join/MarginContainer/HBoxContainer/LeftBox/Top/Join" to="Multiplayer" method="_on_join_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/VBoxContainer/TabContainer/Join/MarginContainer/HBoxContainer/LeftBox/Bottom/Quit" to="." method="_on_quit_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/VBoxContainer/TabContainer/Host/MarginContainer/HBoxContainer/LeftBox/Bottom/MainMenu" to="." method="_on_main_menu_pressed"]
|
||||
[connection signal="pressed" from="Multiplayer/MarginContainer/VBoxContainer/TabContainer/Host/MarginContainer/HBoxContainer/LeftBox/Bottom/Quit" to="." method="_on_quit_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="Settings/MarginContainer/VBoxContainer/TabContainer/Gameplay/MarginContainer/Buttons/Bottom/Save" to="Settings" method="_on_save_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://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"]
|
||||
script/source = "class_name Game extends Node3D
|
||||
|
|
@ -13,43 +13,50 @@ script/source = "class_name Game extends Node3D
|
|||
|
||||
var mode : Node
|
||||
|
||||
func _ready():
|
||||
func _ready() -> void:
|
||||
$BootMenu.start_demo.connect(_start_demo)
|
||||
$BootMenu/Multiplayer.start_server.connect(_start_server)
|
||||
$BootMenu/Multiplayer.join_server.connect(_join_server)
|
||||
|
||||
func _start_demo():
|
||||
if mode: mode.queue_free()
|
||||
mode = SINGLEPLAYER.instantiate() # demo scene
|
||||
add_child(mode)
|
||||
func _start_demo() -> void:
|
||||
_set_game_mode(SINGLEPLAYER.instantiate())
|
||||
$BootMenu.hide()
|
||||
|
||||
func _start_server(port):
|
||||
if mode: mode.queue_free()
|
||||
mode = MULTIPLAYER.instantiate() # server scene
|
||||
add_child(mode)
|
||||
mode.start_server(port)
|
||||
func _start_server(port : int, nickname : String) -> void:
|
||||
_set_game_mode(MULTIPLAYER.instantiate())
|
||||
mode.start_server(port, nickname)
|
||||
$BootMenu.hide()
|
||||
|
||||
func _join_server(host, port):
|
||||
if mode: mode.queue_free()
|
||||
mode = MULTIPLAYER.instantiate() # client scene
|
||||
add_child(mode)
|
||||
func _join_server(host : String, port : int, nickname : String) -> void:
|
||||
_set_game_mode(MULTIPLAYER.instantiate())
|
||||
mode.connected_to_server.connect($BootMenu/Multiplayer._on_connected_to_server)
|
||||
mode.connection_failed.connect($BootMenu/Multiplayer._on_connection_failed)
|
||||
mode.join_server(host, port)
|
||||
mode.join_server(host, port, nickname)
|
||||
|
||||
func _unhandled_input(event):
|
||||
# exit the program
|
||||
func _input(event : InputEvent) -> void:
|
||||
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
|
||||
if event.is_action_pressed(\"window_mode\"):
|
||||
if DisplayServer.window_get_mode() == DisplayServer.WINDOW_MODE_FULLSCREEN:
|
||||
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
|
||||
else:
|
||||
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
|
||||
|
||||
# switch mouse mode
|
||||
if OS.is_debug_build() and Input.is_action_just_pressed(\"toggle_mouse_capture\"):
|
||||
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="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"]
|
||||
|
||||
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_gi1uj"]
|
||||
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="CapsuleMesh" id="CapsuleMesh_k2vhq"]
|
||||
|
||||
[sub_resource type="Sky" id="Sky_t5qlv"]
|
||||
sky_material = SubResource("ProceduralSkyMaterial_gi1uj")
|
||||
process_mode = 1
|
||||
radiance_size = 4
|
||||
[sub_resource type="CapsuleMesh" id="CapsuleMesh_5ytwx"]
|
||||
|
||||
[sub_resource type="Environment" id="Environment_6whfw"]
|
||||
background_mode = 2
|
||||
sky = SubResource("Sky_t5qlv")
|
||||
tonemap_mode = 3
|
||||
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="Map" type="Node" node_paths=PackedStringArray("_flagstand", "_player_spawns_root")]
|
||||
script = ExtResource("1_6ysiv")
|
||||
_flagstand = NodePath("Terrain3D/FlagPillar/CSGCylinder3D/FlagStand")
|
||||
_player_spawns_root = NodePath("Terrain3D/PlayerSpawns")
|
||||
|
||||
[node name="Terrain3D" type="Terrain3D" parent="."]
|
||||
storage = ExtResource("1_a88qe")
|
||||
material = ExtResource("2_o2y3d")
|
||||
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://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://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"]
|
||||
script/source = "extends Node
|
||||
|
||||
@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)
|
||||
|
||||
func respawn_player(player):
|
||||
func respawn_player(player : Player) -> void:
|
||||
player.respawn(player_respawn_location)
|
||||
"
|
||||
|
||||
|
|
@ -27,11 +28,15 @@ absorbent = true
|
|||
[node name="Demo" type="Node"]
|
||||
script = SubResource("GDScript_iv0l6")
|
||||
|
||||
[node name="Map" parent="." instance=ExtResource("2_lsep7")]
|
||||
|
||||
[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")
|
||||
|
||||
[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://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"]
|
||||
script/source = "class_name Multiplayer extends Node
|
||||
|
|
@ -9,68 +11,114 @@ script/source = "class_name Multiplayer extends Node
|
|||
@export_category(\"Parameters\")
|
||||
@export var MAP : PackedScene
|
||||
@export var PLAYER : PackedScene
|
||||
@export var FLAG : PackedScene
|
||||
@export var MAX_CLIENTS : int = 24
|
||||
@export var RESPAWN_TIME : float = 3.0
|
||||
|
||||
@onready var map = $Map
|
||||
@onready var players = $Players
|
||||
@onready var players : Node = $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 connection_failed
|
||||
|
||||
func load_map(scene : PackedScene):
|
||||
map.add_child(scene.instantiate())
|
||||
|
||||
func start_server(port):
|
||||
var peer = ENetMultiplayerPeer.new()
|
||||
func start_server(port : int, nickname : String) -> void:
|
||||
var peer : ENetMultiplayerPeer = ENetMultiplayerPeer.new()
|
||||
peer.create_server(port, MAX_CLIENTS)
|
||||
|
||||
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)
|
||||
|
||||
for id in multiplayer.get_peers():
|
||||
add_player(id)
|
||||
|
||||
if DisplayServer.get_name() != \"headless\":
|
||||
add_player(1)
|
||||
|
||||
func join_server(host, port):
|
||||
var peer = ENetMultiplayerPeer.new()
|
||||
func join_server(host : String, port : int, nickname : String) -> void:
|
||||
var peer : ENetMultiplayerPeer = ENetMultiplayerPeer.new()
|
||||
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.multiplayer_peer = peer
|
||||
|
||||
func _on_connected_to_server():
|
||||
func _on_connected_to_server(nickname : String) -> void:
|
||||
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()
|
||||
|
||||
func respawn_player(player):
|
||||
player.respawn(Vector3(0.0, 150.0, 0.0))
|
||||
func _on_player_died(player : Player, killer_id : int) -> void:
|
||||
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()
|
||||
player.name = str(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)
|
||||
player.died.connect(respawn_player)
|
||||
player.died.connect(_on_player_died)
|
||||
scoreboard.add_entry(player)
|
||||
print(\"Peer `%s` connected\" % player.name)
|
||||
|
||||
func remove_player(peer_id : int):
|
||||
var node_name = str(peer_id)
|
||||
func remove_player(peer_id : int) -> void:
|
||||
var node_name : String = str(peer_id)
|
||||
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)
|
||||
|
||||
func _exit_tree():
|
||||
if multiplayer.is_server():
|
||||
multiplayer.peer_connected.disconnect(add_player)
|
||||
func _load_map(scene : PackedScene, nickname : String) -> void:
|
||||
var map_scene : Node = scene.instantiate()
|
||||
_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)
|
||||
"
|
||||
|
||||
|
|
@ -78,6 +126,7 @@ func _exit_tree():
|
|||
script = SubResource("GDScript_1qrbp")
|
||||
MAP = ExtResource("1_nulvv")
|
||||
PLAYER = ExtResource("2_og1vb")
|
||||
FLAG = ExtResource("3_h0rie")
|
||||
|
||||
[node name="Map" type="Node" parent="."]
|
||||
|
||||
|
|
@ -91,3 +140,42 @@ spawn_limit = 1
|
|||
[node name="PlayersSpawner" type="MultiplayerSpawner" parent="."]
|
||||
_spawnable_scenes = PackedStringArray("res://entities/player/player.tscn")
|
||||
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/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]
|
||||
|
||||
movie_writer/disable_vsync=true
|
||||
|
||||
[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]
|
||||
|
||||
|
|
@ -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)
|
||||
]
|
||||
}
|
||||
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={
|
||||
"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)
|
||||
]
|
||||
}
|
||||
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]
|
||||
|
||||
3d_physics/layer_3="Damage"
|
||||
3d_physics/layer_4="Objective"
|
||||
3d_physics/layer_32="Terrain"
|
||||
|
||||
[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 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
|
||||
|
||||
func _test_projectile_class():
|
||||
var projectile = Projectile.new()
|
||||
assert(projectile != null, "Projectile class should be instantiated")
|
||||
assert(projectile.speed == 78.4, "Projectile damage should be initialized to 78.4")
|
||||
projectile.queue_free()
|
||||
func test_projectile_class() -> void:
|
||||
var projectile : Projectile = Projectile.new()
|
||||
assert_true(projectile != null, "Projectile class should be instantiated")
|
||||
assert_true(projectile.speed == 78.4, "Projectile damage should be initialized to 78.4")
|
||||
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 |