Browse Source

Merge branch 'master' into feature-internal-update

master
Luna 7 years ago
parent
commit
0a64d1743a
79 changed files with 3502 additions and 926 deletions
  1. +1
    -1
      .gitignore
  2. +8
    -3
      README.md
  3. +19
    -0
      assets/heroes/0.obj.import
  4. +19
    -0
      assets/heroes/0_head.obj.import
  5. +19
    -0
      assets/heroes/1.obj.import
  6. +19
    -0
      assets/heroes/1_head.obj.import
  7. +19
    -0
      assets/heroes/2.obj.import
  8. +19
    -0
      assets/heroes/2_head.obj.import
  9. +19
    -0
      assets/heroes/3.obj.import
  10. +19
    -0
      assets/heroes/3_head.obj.import
  11. +19
    -0
      assets/heroes/4.obj.import
  12. +19
    -0
      assets/heroes/4_beam.obj.import
  13. +19
    -0
      assets/heroes/4_head.obj.import
  14. +19
    -0
      assets/heroes/5.obj.import
  15. +19
    -0
      assets/heroes/5_head.obj.import
  16. +19
    -0
      assets/heroes/5_portal.obj.import
  17. +19
    -0
      assets/levels/0.obj.import
  18. +19
    -0
      assets/levels/1.obj.import
  19. +1065
    -0
      assets/levels/2.dae.import
  20. +19
    -0
      assets/levels/2.obj.import
  21. +19
    -0
      assets/maze-high-obj.obj.import
  22. +19
    -0
      assets/maze.obj.import
  23. +32
    -0
      assets/objective-left.png.import
  24. +32
    -0
      assets/objective-right.png.import
  25. +19
    -0
      assets/objective.obj.import
  26. +19
    -0
      assets/player.obj.import
  27. +16
    -0
      assets/theme.tres
  28. +32
    -0
      docs/2018-02-14-heroes.png.import
  29. +32
    -0
      icon.png.import
  30. +3
    -0
      plans.md
  31. +14
    -0
      project.godot
  32. +167
    -0
      scenes/ability_icon.tscn
  33. +1
    -1
      scenes/ai.tscn
  34. +232
    -0
      scenes/custom_game.tscn
  35. +1
    -2
      scenes/hero_select.tscn
  36. +18
    -4
      scenes/heroes/0.tscn
  37. +18
    -2
      scenes/heroes/1.tscn
  38. +1
    -3
      scenes/heroes/1_wall.tscn
  39. +0
    -1
      scenes/heroes/2.tscn
  40. +0
    -1
      scenes/heroes/3.tscn
  41. +17
    -3
      scenes/heroes/4.tscn
  42. +30
    -2
      scenes/heroes/5.tscn
  43. +1
    -3
      scenes/heroes/5_portal.tscn
  44. +1
    -12
      scenes/level.tscn
  45. +1
    -1
      scenes/levels/0.tscn
  46. +1
    -3
      scenes/levels/2.tscn
  47. +120
    -475
      scenes/lobby.tscn
  48. +164
    -0
      scenes/menu.tscn
  49. +1
    -11
      scenes/objective.tscn
  50. +171
    -29
      scenes/player.tscn
  51. +87
    -0
      scenes/singleplayer_lobby.tscn
  52. +0
    -8
      scenes/test-level.tscn
  53. +1
    -3
      scenes/update.tscn
  54. +51
    -0
      scripts/ability_icon.gd
  55. +3
    -3
      scripts/ai.gd
  56. +14
    -0
      scripts/custom_game.gd
  57. +14
    -3
      scripts/hero_select.gd
  58. +13
    -2
      scripts/heroes/0.gd
  59. +20
    -1
      scripts/heroes/1.gd
  60. +4
    -1
      scripts/heroes/1_wall.gd
  61. +1
    -1
      scripts/heroes/2.gd
  62. +8
    -5
      scripts/heroes/3.gd
  63. +16
    -3
      scripts/heroes/4.gd
  64. +43
    -2
      scripts/heroes/5.gd
  65. +12
    -11
      scripts/heroes/5_portal.gd
  66. +97
    -257
      scripts/lobby.gd
  67. +105
    -0
      scripts/matchmaking.gd
  68. +56
    -0
      scripts/menu.gd
  69. +202
    -0
      scripts/networking.gd
  70. +4
    -0
      scripts/placeable.gd
  71. +11
    -9
      scripts/placement.gd
  72. +103
    -55
      scripts/player.gd
  73. +0
    -1
      scripts/tp_camera.gd
  74. +1
    -1
      scripts/update.gd
  75. +31
    -1
      scripts/util.gd
  76. +23
    -0
      util/clear_editor_state.py
  77. +1
    -0
      util/matchmaker.sh
  78. +1
    -1
      util/server.sh
  79. +1
    -1
      util/start-multiple.sh

+ 1
- 1
.gitignore View File

@ -3,13 +3,13 @@
*.swo *.swo
.fscache .fscache
.import .import
*.import
*.blend1 *.blend1
nohup.out nohup.out
recordings recordings
ai ai
release release
vanagloria.pck vanagloria.pck
addons/open-external-editor
._* ._*
ehthumbs.db ehthumbs.db


+ 8
- 3
README.md View File

@ -27,22 +27,27 @@ Current heroes:
- CARITAS (Margarine) - CARITAS (Margarine)
- SUPERBIA (Build portals) - SUPERBIA (Build portals)
Ideas for Heroes:
Ideas for Heroes / Abilities:
- More active - More active
- Blink (Tracer) - no cooldown, but loses all speed on hitting walls
- Blink (like tracer) costs charge
- Heavy guy - Slow, but very heavy for the see-saw - Heavy guy - Slow, but very heavy for the see-saw
- Climb and glide abilities - Climb and glide abilities
- JUMPING - JUMPING
- More supportive - More supportive
- Switch places with a TEAMMATE
- This is awesomely self-regulating because it's zero-sum
- However, it can't really gain charge because it can still be abused
- Boost - Area of effect or zarya-like cast, speeds people up - Boost - Area of effect or zarya-like cast, speeds people up
- Flop - Changes side of see-saw for each team (should it be mechanic instead??) - Flop - Changes side of see-saw for each team (should it be mechanic instead??)
- Build - Build Zineth-like rails for anyone to use - Build - Build Zineth-like rails for anyone to use
- (Combine with Ira?) Portal 2-like gels (bounce, speed, slow?)
- (Combine with IRA?) Portal 2-like gels (bounce, speed, slow?)
- (Combine with LUSSURIA?) Hook and swing on terrain - (Combine with LUSSURIA?) Hook and swing on terrain
- More offensive - More offensive
- Lay traps - Lay traps
- Freeze a hero. A teammate of that hero must unfreeze them! (Or *n* seconds or whatever)
- (Combine with PAZIENZA?) Destroy buildings - (Combine with PAZIENZA?) Destroy buildings
- (Combine wit LUSSURIA?) Hold, then release to explode enemies away
Key concepts: Key concepts:


+ 19
- 0
assets/heroes/0.obj.import View File

@ -0,0 +1,19 @@
[remap]
importer="wavefront_obj"
type="Mesh"
path="res://.import/0.obj-5ff3661b08325671ce64079449bc78dd.mesh"
[deps]
files=[ "res://.import/0.obj-5ff3661b08325671ce64079449bc78dd.mesh" ]
source_file="res://assets/heroes/0.obj"
source_md5="214f8b376199d3c947df1d85a0928dec"
dest_files=[ "res://.import/0.obj-5ff3661b08325671ce64079449bc78dd.mesh", "res://.import/0.obj-5ff3661b08325671ce64079449bc78dd.mesh" ]
dest_md5="4306afcb3a4b4978cce778634c97e7d0"
[params]
generate_tangents=true

+ 19
- 0
assets/heroes/0_head.obj.import View File

@ -0,0 +1,19 @@
[remap]
importer="wavefront_obj"
type="Mesh"
path="res://.import/0_head.obj-0b002be4b283361f171e2d4dd9a85105.mesh"
[deps]
files=[ "res://.import/0_head.obj-0b002be4b283361f171e2d4dd9a85105.mesh" ]
source_file="res://assets/heroes/0_head.obj"
source_md5="4ae67462b018895ed3f258a0db4239e4"
dest_files=[ "res://.import/0_head.obj-0b002be4b283361f171e2d4dd9a85105.mesh", "res://.import/0_head.obj-0b002be4b283361f171e2d4dd9a85105.mesh" ]
dest_md5="7094164b68aeac1c4dd9bd292282e4b9"
[params]
generate_tangents=true

+ 19
- 0
assets/heroes/1.obj.import View File

@ -0,0 +1,19 @@
[remap]
importer="wavefront_obj"
type="Mesh"
path="res://.import/1.obj-3a9ae1e4a3d92228bd05741755fdbcdd.mesh"
[deps]
files=[ "res://.import/1.obj-3a9ae1e4a3d92228bd05741755fdbcdd.mesh" ]
source_file="res://assets/heroes/1.obj"
source_md5="6a83c78e54b84bd01eb44630c48362f2"
dest_files=[ "res://.import/1.obj-3a9ae1e4a3d92228bd05741755fdbcdd.mesh", "res://.import/1.obj-3a9ae1e4a3d92228bd05741755fdbcdd.mesh" ]
dest_md5="808804a04eb10327391dd96c30f14435"
[params]
generate_tangents=true

+ 19
- 0
assets/heroes/1_head.obj.import View File

@ -0,0 +1,19 @@
[remap]
importer="wavefront_obj"
type="Mesh"
path="res://.import/1_head.obj-661a3a390ef1299857e3de1aba5a1d01.mesh"
[deps]
files=[ "res://.import/1_head.obj-661a3a390ef1299857e3de1aba5a1d01.mesh" ]
source_file="res://assets/heroes/1_head.obj"
source_md5="78a4e4475d699dbd061ec9a916cbd606"
dest_files=[ "res://.import/1_head.obj-661a3a390ef1299857e3de1aba5a1d01.mesh", "res://.import/1_head.obj-661a3a390ef1299857e3de1aba5a1d01.mesh" ]
dest_md5="65c8304300dd9929d0b3b008623845a0"
[params]
generate_tangents=true

+ 19
- 0
assets/heroes/2.obj.import View File

@ -0,0 +1,19 @@
[remap]
importer="wavefront_obj"
type="Mesh"
path="res://.import/2.obj-85c8b4ac312b9585e4dda4f545679e80.mesh"
[deps]
files=[ "res://.import/2.obj-85c8b4ac312b9585e4dda4f545679e80.mesh" ]
source_file="res://assets/heroes/2.obj"
source_md5="7b2a64047a6477edd16b10f1c8601e15"
dest_files=[ "res://.import/2.obj-85c8b4ac312b9585e4dda4f545679e80.mesh", "res://.import/2.obj-85c8b4ac312b9585e4dda4f545679e80.mesh" ]
dest_md5="cf97b53977d069c0f48e104093031357"
[params]
generate_tangents=true

+ 19
- 0
assets/heroes/2_head.obj.import View File

@ -0,0 +1,19 @@
[remap]
importer="wavefront_obj"
type="Mesh"
path="res://.import/2_head.obj-642d7e5721ba3621d4aeef33bf9079f3.mesh"
[deps]
files=[ "res://.import/2_head.obj-642d7e5721ba3621d4aeef33bf9079f3.mesh" ]
source_file="res://assets/heroes/2_head.obj"
source_md5="3800b7ca51634172c29e2627d0688739"
dest_files=[ "res://.import/2_head.obj-642d7e5721ba3621d4aeef33bf9079f3.mesh", "res://.import/2_head.obj-642d7e5721ba3621d4aeef33bf9079f3.mesh" ]
dest_md5="f41bf13cd6278973e335edcb5af07800"
[params]
generate_tangents=true

+ 19
- 0
assets/heroes/3.obj.import View File

@ -0,0 +1,19 @@
[remap]
importer="wavefront_obj"
type="Mesh"
path="res://.import/3.obj-a2b36e0242832fc3ee6cf8133bec1df6.mesh"
[deps]
files=[ "res://.import/3.obj-a2b36e0242832fc3ee6cf8133bec1df6.mesh" ]
source_file="res://assets/heroes/3.obj"
source_md5="ae31181eed13485b325d439fd465e246"
dest_files=[ "res://.import/3.obj-a2b36e0242832fc3ee6cf8133bec1df6.mesh", "res://.import/3.obj-a2b36e0242832fc3ee6cf8133bec1df6.mesh" ]
dest_md5="3afa20d19f1fa09fcf2fee691c245317"
[params]
generate_tangents=true

+ 19
- 0
assets/heroes/3_head.obj.import View File

@ -0,0 +1,19 @@
[remap]
importer="wavefront_obj"
type="Mesh"
path="res://.import/3_head.obj-31149354fd38179ee6897017177772af.mesh"
[deps]
files=[ "res://.import/3_head.obj-31149354fd38179ee6897017177772af.mesh" ]
source_file="res://assets/heroes/3_head.obj"
source_md5="4f6b31cfbe16a55cce978896cf8b0b12"
dest_files=[ "res://.import/3_head.obj-31149354fd38179ee6897017177772af.mesh", "res://.import/3_head.obj-31149354fd38179ee6897017177772af.mesh" ]
dest_md5="8ba28a8f98e213a2382b508bb344084c"
[params]
generate_tangents=true

+ 19
- 0
assets/heroes/4.obj.import View File

@ -0,0 +1,19 @@
[remap]
importer="wavefront_obj"
type="Mesh"
path="res://.import/4.obj-773905e6e7c2c08ad34fe36bfaacca4e.mesh"
[deps]
files=[ "res://.import/4.obj-773905e6e7c2c08ad34fe36bfaacca4e.mesh" ]
source_file="res://assets/heroes/4.obj"
source_md5="8a2ea58bae6a5ba0b5a28b7ab6163ed9"
dest_files=[ "res://.import/4.obj-773905e6e7c2c08ad34fe36bfaacca4e.mesh", "res://.import/4.obj-773905e6e7c2c08ad34fe36bfaacca4e.mesh" ]
dest_md5="93358c6c816510bd069825e089cee878"
[params]
generate_tangents=true

+ 19
- 0
assets/heroes/4_beam.obj.import View File

@ -0,0 +1,19 @@
[remap]
importer="wavefront_obj"
type="Mesh"
path="res://.import/4_beam.obj-00b64391bae3ea00b0d3ef163bfa8860.mesh"
[deps]
files=[ "res://.import/4_beam.obj-00b64391bae3ea00b0d3ef163bfa8860.mesh" ]
source_file="res://assets/heroes/4_beam.obj"
source_md5="8583eb948f98e108f6848c4fc96a2562"
dest_files=[ "res://.import/4_beam.obj-00b64391bae3ea00b0d3ef163bfa8860.mesh", "res://.import/4_beam.obj-00b64391bae3ea00b0d3ef163bfa8860.mesh" ]
dest_md5="76cbfe93be8dd02d9519c5284d1e638f"
[params]
generate_tangents=true

+ 19
- 0
assets/heroes/4_head.obj.import View File

@ -0,0 +1,19 @@
[remap]
importer="wavefront_obj"
type="Mesh"
path="res://.import/4_head.obj-0f05fd2c5005558302023bc511be8ae6.mesh"
[deps]
files=[ "res://.import/4_head.obj-0f05fd2c5005558302023bc511be8ae6.mesh" ]
source_file="res://assets/heroes/4_head.obj"
source_md5="2ed548efe830daac45b9e4fa4b5b1b73"
dest_files=[ "res://.import/4_head.obj-0f05fd2c5005558302023bc511be8ae6.mesh", "res://.import/4_head.obj-0f05fd2c5005558302023bc511be8ae6.mesh" ]
dest_md5="9a188b6c84c8a296472464a3366650fc"
[params]
generate_tangents=true

+ 19
- 0
assets/heroes/5.obj.import View File

@ -0,0 +1,19 @@
[remap]
importer="wavefront_obj"
type="Mesh"
path="res://.import/5.obj-aae555f5fa1f112fdc160f94735bf9d5.mesh"
[deps]
files=[ "res://.import/5.obj-aae555f5fa1f112fdc160f94735bf9d5.mesh" ]
source_file="res://assets/heroes/5.obj"
source_md5="5a020906bcd263a5302ebe5074b43c01"
dest_files=[ "res://.import/5.obj-aae555f5fa1f112fdc160f94735bf9d5.mesh", "res://.import/5.obj-aae555f5fa1f112fdc160f94735bf9d5.mesh" ]
dest_md5="bb5b4b3ca681eb185284560d7f4a8aed"
[params]
generate_tangents=true

+ 19
- 0
assets/heroes/5_head.obj.import View File

@ -0,0 +1,19 @@
[remap]
importer="wavefront_obj"
type="Mesh"
path="res://.import/5_head.obj-99b3a2eaf8ae9e841b6fdcc8d4884ea7.mesh"
[deps]
files=[ "res://.import/5_head.obj-99b3a2eaf8ae9e841b6fdcc8d4884ea7.mesh" ]
source_file="res://assets/heroes/5_head.obj"
source_md5="453157b7ed836fe44c392ad6dda3ff67"
dest_files=[ "res://.import/5_head.obj-99b3a2eaf8ae9e841b6fdcc8d4884ea7.mesh", "res://.import/5_head.obj-99b3a2eaf8ae9e841b6fdcc8d4884ea7.mesh" ]
dest_md5="a2bc2ff9d1a92c3be2c8477eceb08768"
[params]
generate_tangents=true

+ 19
- 0
assets/heroes/5_portal.obj.import View File

@ -0,0 +1,19 @@
[remap]
importer="wavefront_obj"
type="Mesh"
path="res://.import/5_portal.obj-a337ed5122c40b180597dd9794ecfe6d.mesh"
[deps]
files=[ "res://.import/5_portal.obj-a337ed5122c40b180597dd9794ecfe6d.mesh" ]
source_file="res://assets/heroes/5_portal.obj"
source_md5="bc944713e3a053455322914a39987891"
dest_files=[ "res://.import/5_portal.obj-a337ed5122c40b180597dd9794ecfe6d.mesh", "res://.import/5_portal.obj-a337ed5122c40b180597dd9794ecfe6d.mesh" ]
dest_md5="b63a25154e6cdd3e7bcb1a3fe4e0e04a"
[params]
generate_tangents=true

+ 19
- 0
assets/levels/0.obj.import View File

@ -0,0 +1,19 @@
[remap]
importer="wavefront_obj"
type="Mesh"
path="res://.import/0.obj-75904c05129c42580cc5d5c2ce0f88f4.mesh"
[deps]
files=[ "res://.import/0.obj-75904c05129c42580cc5d5c2ce0f88f4.mesh" ]
source_file="res://assets/levels/0.obj"
source_md5="c43e5185ee65f03ac94dc947611d85d5"
dest_files=[ "res://.import/0.obj-75904c05129c42580cc5d5c2ce0f88f4.mesh", "res://.import/0.obj-75904c05129c42580cc5d5c2ce0f88f4.mesh" ]
dest_md5="23c015582e544d38c3302925e86550ca"
[params]
generate_tangents=true

+ 19
- 0
assets/levels/1.obj.import View File

@ -0,0 +1,19 @@
[remap]
importer="wavefront_obj"
type="Mesh"
path="res://.import/1.obj-8c0967187ed7a9d970c8667286d96ec8.mesh"
[deps]
files=[ "res://.import/1.obj-8c0967187ed7a9d970c8667286d96ec8.mesh" ]
source_file="res://assets/levels/1.obj"
source_md5="c76ce309215e4ab659d00d70f85051c1"
dest_files=[ "res://.import/1.obj-8c0967187ed7a9d970c8667286d96ec8.mesh", "res://.import/1.obj-8c0967187ed7a9d970c8667286d96ec8.mesh" ]
dest_md5="772c79044dd30ef6a01e2c1b99e3f78c"
[params]
generate_tangents=true

+ 1065
- 0
assets/levels/2.dae.import
File diff suppressed because it is too large
View File


+ 19
- 0
assets/levels/2.obj.import View File

@ -0,0 +1,19 @@
[remap]
importer="wavefront_obj"
type="Mesh"
path="res://.import/2.obj-3a5433501168477746c24182726a90c2.mesh"
[deps]
files=[ "res://.import/2.obj-3a5433501168477746c24182726a90c2.mesh" ]
source_file="res://assets/levels/2.obj"
source_md5="9c1795f0c017f636969954e503a75157"
dest_files=[ "res://.import/2.obj-3a5433501168477746c24182726a90c2.mesh", "res://.import/2.obj-3a5433501168477746c24182726a90c2.mesh" ]
dest_md5="557048f3ebad19044a3c342d9c06e870"
[params]
generate_tangents=true

+ 19
- 0
assets/maze-high-obj.obj.import View File

@ -0,0 +1,19 @@
[remap]
importer="wavefront_obj"
type="Mesh"
path="res://.import/maze-high-obj.obj-24db734e0c48b4dd09ff2d9426ff3915.mesh"
[deps]
files=[ "res://.import/maze-high-obj.obj-24db734e0c48b4dd09ff2d9426ff3915.mesh" ]
source_file="res://assets/maze-high-obj.obj"
source_md5="6957a6487d30265864dc3d40baf411a2"
dest_files=[ "res://.import/maze-high-obj.obj-24db734e0c48b4dd09ff2d9426ff3915.mesh", "res://.import/maze-high-obj.obj-24db734e0c48b4dd09ff2d9426ff3915.mesh" ]
dest_md5="ce1017fcf90646333644720dd66b599f"
[params]
generate_tangents=true

+ 19
- 0
assets/maze.obj.import View File

@ -0,0 +1,19 @@
[remap]
importer="wavefront_obj"
type="Mesh"
path="res://.import/maze.obj-70de96fca66f7b42f2e7948110e529ab.mesh"
[deps]
files=[ "res://.import/maze.obj-70de96fca66f7b42f2e7948110e529ab.mesh" ]
source_file="res://assets/maze.obj"
source_md5="f35f5a0e67714a456ed725761a30cd8e"
dest_files=[ "res://.import/maze.obj-70de96fca66f7b42f2e7948110e529ab.mesh", "res://.import/maze.obj-70de96fca66f7b42f2e7948110e529ab.mesh" ]
dest_md5="611ce2fc213387da9af0b853967a2f25"
[params]
generate_tangents=true

+ 32
- 0
assets/objective-left.png.import View File

@ -0,0 +1,32 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/objective-left.png-587402b851e8944e16eb289e1b058974.stex"
[deps]
source_file="res://assets/objective-left.png"
source_md5="c172ead10f0d4193e46622fe62668f31"
dest_files=[ "res://.import/objective-left.png-587402b851e8944e16eb289e1b058974.stex" ]
dest_md5="09403856c115d79b27429585b5a7b0f5"
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

+ 32
- 0
assets/objective-right.png.import View File

@ -0,0 +1,32 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/objective-right.png-d18195ff55e7aff72b594ff190053ce4.stex"
[deps]
source_file="res://assets/objective-right.png"
source_md5="2725f8f335a4f2ceb2562ef44343830d"
dest_files=[ "res://.import/objective-right.png-d18195ff55e7aff72b594ff190053ce4.stex" ]
dest_md5="c3fa2e979e2fdea8132655a82686526d"
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

+ 19
- 0
assets/objective.obj.import View File

@ -0,0 +1,19 @@
[remap]
importer="wavefront_obj"
type="Mesh"
path="res://.import/objective.obj-d3a42ffdae3ada4606dd452051061b51.mesh"
[deps]
files=[ "res://.import/objective.obj-d3a42ffdae3ada4606dd452051061b51.mesh" ]
source_file="res://assets/objective.obj"
source_md5="a00bec3114f9259f2ae795c28f75e9c9"
dest_files=[ "res://.import/objective.obj-d3a42ffdae3ada4606dd452051061b51.mesh", "res://.import/objective.obj-d3a42ffdae3ada4606dd452051061b51.mesh" ]
dest_md5="56ab97d8a864679c68c7c7d9c1d38dd8"
[params]
generate_tangents=true

+ 19
- 0
assets/player.obj.import View File

@ -0,0 +1,19 @@
[remap]
importer="wavefront_obj"
type="Mesh"
path="res://.import/player.obj-9552f61e8059d9a4dd660ae96ad6a512.mesh"
[deps]
files=[ "res://.import/player.obj-9552f61e8059d9a4dd660ae96ad6a512.mesh" ]
source_file="res://assets/player.obj"
source_md5="7074ae8221d3b083f4f95e70e1ee446f"
dest_files=[ "res://.import/player.obj-9552f61e8059d9a4dd660ae96ad6a512.mesh", "res://.import/player.obj-9552f61e8059d9a4dd660ae96ad6a512.mesh" ]
dest_md5="0ca70d88338dbaa80a9676388d516d63"
[params]
generate_tangents=true

+ 16
- 0
assets/theme.tres View File

@ -0,0 +1,16 @@
[gd_resource type="Theme" load_steps=3 format=2]
[ext_resource path="res://assets/DejaVuSansMono.ttf" type="DynamicFontData" id=1]
[sub_resource type="DynamicFont" id=1]
size = 18
use_mipmaps = false
use_filter = false
font_data = ExtResource( 1 )
_sections_unfolded = [ "Font", "Settings" ]
[resource]
default_font = SubResource( 1 )

+ 32
- 0
docs/2018-02-14-heroes.png.import View File

@ -0,0 +1,32 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/2018-02-14-heroes.png-66ce877f0c90a512065fa1c503625ab1.stex"
[deps]
source_file="res://docs/2018-02-14-heroes.png"
source_md5="98144251e8505d9c53c0ba6cf451448e"
dest_files=[ "res://.import/2018-02-14-heroes.png-66ce877f0c90a512065fa1c503625ab1.stex" ]
dest_md5="b9c1300d34876a596a8e284f821d7bc9"
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

+ 32
- 0
icon.png.import View File

@ -0,0 +1,32 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex"
[deps]
source_file="res://icon.png"
source_md5="7febcf604d750bd224f744362be04a8a"
dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ]
dest_md5="e86d0a8edb5d32d9447a249948fdcf57"
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

+ 3
- 0
plans.md View File

@ -8,6 +8,7 @@ Big TODOs:
- ^ I think you need more abilities for heroes, that combine well - ^ I think you need more abilities for heroes, that combine well
- Like, you could combine PAZIENZA with [destroys buildings] - Like, you could combine PAZIENZA with [destroys buildings]
- Start making maps and figuring out what works / what you like - Start making maps and figuring out what works / what you like
- Make just one new main level with the lessons you've learned from this one
- I'd love to do a payload map! - I'd love to do a payload map!
- More platforming for everyone (It's industria only rn tbh) - More platforming for everyone (It's industria only rn tbh)
- Give portals a tilted wall to fuck with acceleration - Give portals a tilted wall to fuck with acceleration
@ -25,6 +26,8 @@ Smaller TODOs:
- Ira is OP? - Ira is OP?
- Nerfed - 5 walls - Nerfed - 5 walls
- Make motion more reactive? - Make motion more reactive?
- Remember some player settings, probably in a player.json or something
- I'm mostly thinking of nickname, but also SR eventually
Bugs: Bugs:


+ 14
- 0
project.godot View File

@ -17,10 +17,16 @@ config/icon="res://icon.png"
[autoload] [autoload]
util="*res://scripts/util.gd" util="*res://scripts/util.gd"
networking="*res://scripts/networking.gd"
[editor_plugins]
enabled=PoolStringArray( "open-external-editor" )
[input] [input]
move_forwards=[ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":44,"unicode":0,"echo":false,"script":null) move_forwards=[ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":44,"unicode":0,"echo":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":58,"unicode":0,"echo":false,"script":null)
] ]
move_backwards=[ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":79,"unicode":0,"echo":false,"script":null) move_backwards=[ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":79,"unicode":0,"echo":false,"script":null)
] ]
@ -54,6 +60,14 @@ hero_5_confirm_portal=[ Object(InputEventMouseButton,"resource_local_to_scene":f
] ]
hero_5_remove_portal=[ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":2,"pressed":false,"doubleclick":false,"script":null) hero_5_remove_portal=[ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":2,"pressed":false,"doubleclick":false,"script":null)
] ]
primary_ability=[ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":46,"unicode":0,"echo":false,"script":null)
]
hero_0_boost=[ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":1,"pressed":false,"doubleclick":false,"script":null)
]
primary_mouse=[ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":1,"pressed":false,"doubleclick":false,"script":null)
]
enable_cheats=[ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":true,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":45,"unicode":0,"echo":false,"script":null)
]
[network] [network]


+ 167
- 0
scenes/ability_icon.tscn View File

@ -0,0 +1,167 @@
[gd_scene load_steps=4 format=2]
[ext_resource path="res://scripts/ability_icon.gd" type="Script" id=1]
[sub_resource type="StyleBoxFlat" id=2]
content_margin_left = -1.0
content_margin_right = -1.0
content_margin_top = -1.0
content_margin_bottom = -1.0
bg_color = Color( 0.042572, 0.351562, 0.315353, 1 )
draw_center = true
border_width_left = 0
border_width_top = 0
border_width_right = 0
border_width_bottom = 0
border_color = Color( 0.8, 0.8, 0.8, 1 )
border_blend = false
corner_radius_top_left = 0
corner_radius_top_right = 0
corner_radius_bottom_right = 0
corner_radius_bottom_left = 0
corner_detail = 8
expand_margin_left = 0.0
expand_margin_right = 0.0
expand_margin_top = 0.0
expand_margin_bottom = 0.0
shadow_color = Color( 0, 0, 0, 0.6 )
shadow_size = 0
anti_aliasing = true
anti_aliasing_size = 1
[sub_resource type="StyleBoxFlat" id=1]
content_margin_left = -1.0
content_margin_right = -1.0
content_margin_top = -1.0
content_margin_bottom = -1.0
bg_color = Color( 0.73822, 0.921875, 0.814265, 0.403333 )
draw_center = true
border_width_left = 0
border_width_top = 0
border_width_right = 0
border_width_bottom = 0
border_color = Color( 0.8, 0.8, 0.8, 1 )
border_blend = false
corner_radius_top_left = 0
corner_radius_top_right = 0
corner_radius_bottom_right = 0
corner_radius_bottom_left = 0
corner_detail = 8
expand_margin_left = 0.0
expand_margin_right = 0.0
expand_margin_top = 0.0
expand_margin_bottom = 0.0
shadow_color = Color( 0, 0, 0, 0.6 )
shadow_size = 0
anti_aliasing = true
anti_aliasing_size = 1
[node name="Ability" type="Control"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_right = 30.0
margin_bottom = 30.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 0
script = ExtResource( 1 )
cost = 1
ability_name = "Ability"
display_progress = true
action = ""
[node name="Bar" type="ProgressBar" parent="." index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = -25.0
margin_top = -25.0
margin_right = 25.0
margin_bottom = 25.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 0
custom_styles/fg = SubResource( 2 )
custom_styles/bg = SubResource( 1 )
min_value = 0.0
max_value = 100.0
step = 1.0
page = 0.0
value = 0.0
exp_edit = false
rounded = false
percent_visible = false
[node name="Available" type="ColorRect" parent="." index="1"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = -30.0
margin_top = -30.0
margin_right = 20.0
margin_bottom = 20.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 0
color = Color( 0.347443, 0.898438, 0.549761, 1 )
[node name="Name" type="Label" parent="." index="2"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = -72.0
margin_top = -44.0
margin_right = 70.0
margin_bottom = -30.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
custom_colors/font_color = Color( 0.00357056, 0.0703125, 0.04372, 1 )
text = "<Name>"
align = 1
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[node name="Button" type="Label" parent="." index="3"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = -72.0
margin_top = 29.0
margin_right = 70.0
margin_bottom = 43.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
custom_colors/font_color = Color( 0.00357056, 0.0703125, 0.04372, 1 )
text = "<Button>"
align = 1
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1

+ 1
- 1
scenes/ai.tscn View File

@ -2,7 +2,7 @@
[ext_resource path="res://scripts/ai.gd" type="Script" id=1] [ext_resource path="res://scripts/ai.gd" type="Script" id=1]
[node name="Node" type="Node" index="0"]
[node name="Node" type="Node"]
script = ExtResource( 1 ) script = ExtResource( 1 )


+ 232
- 0
scenes/custom_game.tscn View File

@ -0,0 +1,232 @@
[gd_scene load_steps=5 format=2]
[ext_resource path="res://assets/theme.tres" type="Theme" id=1]
[ext_resource path="res://scripts/custom_game.gd" type="Script" id=2]
[ext_resource path="res://assets/DejaVuSansMono.ttf" type="DynamicFontData" id=3]
[sub_resource type="DynamicFont" id=1]
size = 30
use_mipmaps = false
use_filter = false
font_data = ExtResource( 3 )
[node name="CustomGame" type="Control"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_right = 40.0
margin_bottom = 40.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
theme = ExtResource( 1 )
script = ExtResource( 2 )
[node name="VSeparator" type="VSeparator" parent="." index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 498.0
margin_top = 140.0
margin_right = 518.0
margin_bottom = 481.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
[node name="Label" type="Label" parent="." index="1"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 54.0
margin_top = 66.0
margin_right = 395.0
margin_bottom = 102.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
custom_fonts/font = SubResource( 1 )
text = "Custom Game"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[node name="Server" type="Button" parent="." index="2"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 73.0
margin_top = 195.0
margin_right = 366.0
margin_bottom = 252.0
rect_pivot_offset = Vector2( 0, 0 )
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
toggle_mode = false
enabled_focus_mode = 2
shortcut = null
group = null
text = "Host Game"
flat = false
align = 1
[node name="Client" type="Button" parent="." index="3"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 588.0
margin_top = 258.0
margin_right = 890.0
margin_bottom = 315.0
rect_pivot_offset = Vector2( 0, 0 )
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
toggle_mode = false
enabled_focus_mode = 2
shortcut = null
group = null
text = "Join Game"
flat = false
align = 1
[node name="IPLabel" type="Label" parent="." index="4"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 592.0
margin_top = 205.0
margin_right = 625.0
margin_bottom = 227.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
text = "IP:"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[node name="IP" type="TextEdit" parent="." index="5"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 632.0
margin_top = 203.0
margin_right = 891.0
margin_bottom = 232.0
rect_pivot_offset = Vector2( 0, 0 )
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
text = "127.0.0.1"
readonly = false
highlight_current_line = false
syntax_highlighting = false
show_line_numbers = false
highlight_all_occurrences = false
override_selected_font_color = false
context_menu_enabled = true
smooth_scrolling = false
v_scroll_speed = 80.0
hiding_enabled = 0
wrap_lines = false
caret_block_mode = false
caret_blink = false
caret_blink_speed = 0.65
caret_moving_by_right_click = true
[node name="Label2" type="Label" parent="." index="6"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 72.0
margin_top = 145.0
margin_right = 171.0
margin_bottom = 167.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
text = "Host game"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[node name="Label3" type="Label" parent="." index="7"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 577.0
margin_top = 147.0
margin_right = 617.0
margin_bottom = 169.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
text = "Join Game"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[node name="Back" type="Button" parent="." index="8"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 437.0
margin_top = 509.0
margin_right = 581.0
margin_bottom = 537.0
rect_pivot_offset = Vector2( 0, 0 )
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
toggle_mode = false
enabled_focus_mode = 2
shortcut = null
group = null
text = "Back to menu"
flat = false
align = 1

+ 1
- 2
scenes/hero_select.tscn View File

@ -3,7 +3,7 @@
[ext_resource path="res://scripts/hero_select_screen.gd" type="Script" id=1] [ext_resource path="res://scripts/hero_select_screen.gd" type="Script" id=1]
[ext_resource path="res://scripts/hero_select.gd" type="Script" id=2] [ext_resource path="res://scripts/hero_select.gd" type="Script" id=2]
[node name="HeroSelect" type="ColorRect" index="0"]
[node name="HeroSelect" type="ColorRect"]
pause_mode = 2 pause_mode = 2
anchor_left = 0.0 anchor_left = 0.0
@ -17,7 +17,6 @@ size_flags_horizontal = 1
size_flags_vertical = 1 size_flags_vertical = 1
color = Color( 0.097229, 0.104696, 0.105469, 1 ) color = Color( 0.097229, 0.104696, 0.105469, 1 )
script = ExtResource( 1 ) script = ExtResource( 1 )
_sections_unfolded = [ "Anchor", "Margin", "Material", "Pause", "Visibility" ]
[node name="Hero" type="OptionButton" parent="." index="0"] [node name="Hero" type="OptionButton" parent="." index="0"]


+ 18
- 4
scenes/heroes/0.tscn View File

@ -1,11 +1,12 @@
[gd_scene load_steps=5 format=2]
[gd_scene load_steps=6 format=2]
[ext_resource path="res://scenes/player.tscn" type="PackedScene" id=1] [ext_resource path="res://scenes/player.tscn" type="PackedScene" id=1]
[ext_resource path="res://scripts/heroes/0.gd" type="Script" id=2] [ext_resource path="res://scripts/heroes/0.gd" type="Script" id=2]
[ext_resource path="res://assets/heroes/0_head.obj" type="ArrayMesh" id=3] [ext_resource path="res://assets/heroes/0_head.obj" type="ArrayMesh" id=3]
[ext_resource path="res://assets/heroes/0.obj" type="ArrayMesh" id=4] [ext_resource path="res://assets/heroes/0.obj" type="ArrayMesh" id=4]
[ext_resource path="res://scenes/ability_icon.tscn" type="PackedScene" id=5]
[node name="RigidBody" index="0" instance=ExtResource( 1 )]
[node name="RigidBody" instance=ExtResource( 1 )]
script = ExtResource( 2 ) script = ExtResource( 2 )
@ -13,16 +14,29 @@ script = ExtResource( 2 )
transform = Transform( 0.376731, 0, 6.23012e-08, -6.13772e-08, 1.03258e-14, 0.382402, 0, -0.389018, 1.01502e-14, 0, 0.104562, -0.0173855 ) transform = Transform( 0.376731, 0, 6.23012e-08, -6.13772e-08, 1.03258e-14, 0.382402, 0, -0.389018, 1.01502e-14, 0, 0.104562, -0.0173855 )
mesh = ExtResource( 3 ) mesh = ExtResource( 3 )
material/0 = null
[node name="MainMesh" parent="Yaw" index="1"] [node name="MainMesh" parent="Yaw" index="1"]
transform = Transform( 0.409321, 0, 0, 0, -7.39614e-08, -0.453971, 0, 0.389055, -6.33852e-08, 0.0432051, 0.588691, 0.0666541 ) transform = Transform( 0.409321, 0, 0, 0, -7.39614e-08, -0.453971, 0, 0.389055, -6.33852e-08, 0.0432051, 0.588691, 0.0666541 )
mesh = ExtResource( 4 ) mesh = ExtResource( 4 )
material/0 = null
[node name="Crosshair" parent="MasterOnly" index="0"] [node name="Crosshair" parent="MasterOnly" index="0"]
text = "" text = ""
[node name="Boost" parent="MasterOnly" index="1" instance=ExtResource( 5 )]
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = -91.0
margin_top = -118.0
margin_right = -80.0
margin_bottom = -109.0
cost = 2
ability_name = "Speed Boost"
display_progress = false
action = "hero_0_boost"

+ 18
- 2
scenes/heroes/1.tscn View File

@ -1,18 +1,20 @@
[gd_scene load_steps=6 format=2]
[gd_scene load_steps=7 format=2]
[ext_resource path="res://scenes/player.tscn" type="PackedScene" id=1] [ext_resource path="res://scenes/player.tscn" type="PackedScene" id=1]
[ext_resource path="res://scripts/heroes/1.gd" type="Script" id=2] [ext_resource path="res://scripts/heroes/1.gd" type="Script" id=2]
[ext_resource path="res://assets/heroes/1_head.obj" type="ArrayMesh" id=3] [ext_resource path="res://assets/heroes/1_head.obj" type="ArrayMesh" id=3]
[ext_resource path="res://assets/heroes/1.obj" type="ArrayMesh" id=4] [ext_resource path="res://assets/heroes/1.obj" type="ArrayMesh" id=4]
[ext_resource path="res://scenes/ability_icon.tscn" type="PackedScene" id=5]
[sub_resource type="CapsuleShape" id=1] [sub_resource type="CapsuleShape" id=1]
radius = 0.5 radius = 0.5
height = 0.5 height = 0.5
[node name="RigidBody" index="0" instance=ExtResource( 1 )]
[node name="RigidBody" instance=ExtResource( 1 )]
script = ExtResource( 2 ) script = ExtResource( 2 )
looked_at_charge_suck = 25
[node name="Body" parent="." index="0"] [node name="Body" parent="." index="0"]
@ -28,6 +30,20 @@ mesh = ExtResource( 3 )
transform = Transform( 1, 0, 0, 0, -1.54624e-07, -0.949072, 0, 1, -1.62921e-07, 0, 0.725089, 0 ) transform = Transform( 1, 0, 0, 0, -1.54624e-07, -0.949072, 0, 1, -1.62921e-07, 0, 0.725089, 0 )
mesh = ExtResource( 4 ) mesh = ExtResource( 4 )
[node name="PlaceWall" parent="MasterOnly" index="3" instance=ExtResource( 5 )]
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = -93.0
margin_top = -112.0
margin_right = -63.0
margin_bottom = -82.0
cost = 15
ability_name = "Place Wall"
action = "hero_1_place_wall"
[node name="TPCamera" parent="." index="5"] [node name="TPCamera" parent="." index="5"]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.17139, 0 ) transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.17139, 0 )


+ 1
- 3
scenes/heroes/1_wall.tscn View File

@ -13,7 +13,7 @@ subdivide_depth = 0
extents = Vector3( 1.5, 1.5, 0.25 ) extents = Vector3( 1.5, 1.5, 0.25 )
[node name="StaticBody" type="StaticBody" index="0"]
[node name="StaticBody" type="StaticBody"]
input_ray_pickable = true input_ray_pickable = true
input_capture_on_drag = false input_capture_on_drag = false
@ -40,13 +40,11 @@ lod_max_hysteresis = 0.0
mesh = SubResource( 1 ) mesh = SubResource( 1 )
skeleton = NodePath("..") skeleton = NodePath("..")
material/0 = null material/0 = null
_sections_unfolded = [ "Transform" ]
[node name="CollisionShape" type="CollisionShape" parent="." index="1"] [node name="CollisionShape" type="CollisionShape" parent="." index="1"]
transform = Transform( 1, 0, 0, 0, -1.62921e-07, -1, 0, 1, -1.62921e-07, 0, 0, -1.5 ) transform = Transform( 1, 0, 0, 0, -1.62921e-07, -1, 0, 1, -1.62921e-07, 0, 0, -1.5 )
shape = SubResource( 2 ) shape = SubResource( 2 )
disabled = true disabled = true
_sections_unfolded = [ "Transform" ]

+ 0
- 1
scenes/heroes/2.tscn View File

@ -51,7 +51,6 @@ reverb_bus_enable = false
reverb_bus_name = "Master" reverb_bus_name = "Master"
reverb_bus_amount = 0.0 reverb_bus_amount = 0.0
reverb_bus_uniformity = 0.0 reverb_bus_uniformity = 0.0
_sections_unfolded = [ "Audio Bus", "Collision", "Pause", "Reverb Bus", "Transform", "Visibility" ]
[node name="CollisionShape" type="CollisionShape" parent="Area" index="0"] [node name="CollisionShape" type="CollisionShape" parent="Area" index="0"]


+ 0
- 1
scenes/heroes/3.tscn View File

@ -9,7 +9,6 @@
contacts_reported = 3 contacts_reported = 3
script = ExtResource( 2 ) script = ExtResource( 2 )
_sections_unfolded = [ "Angular", "Axis Lock", "Collision", "Linear", "Pause", "Transform", "Visibility", "collision" ]
[node name="RotatedHead" parent="Yaw/Pitch" index="0"] [node name="RotatedHead" parent="Yaw/Pitch" index="0"]


+ 17
- 3
scenes/heroes/4.tscn View File

@ -1,12 +1,13 @@
[gd_scene load_steps=6 format=2]
[gd_scene load_steps=7 format=2]
[ext_resource path="res://scenes/player.tscn" type="PackedScene" id=1] [ext_resource path="res://scenes/player.tscn" type="PackedScene" id=1]
[ext_resource path="res://scripts/heroes/4.gd" type="Script" id=2] [ext_resource path="res://scripts/heroes/4.gd" type="Script" id=2]
[ext_resource path="res://assets/heroes/4_head.obj" type="ArrayMesh" id=3] [ext_resource path="res://assets/heroes/4_head.obj" type="ArrayMesh" id=3]
[ext_resource path="res://assets/heroes/4_beam.obj" type="ArrayMesh" id=4] [ext_resource path="res://assets/heroes/4_beam.obj" type="ArrayMesh" id=4]
[ext_resource path="res://assets/heroes/4.obj" type="ArrayMesh" id=5] [ext_resource path="res://assets/heroes/4.obj" type="ArrayMesh" id=5]
[ext_resource path="res://scenes/ability_icon.tscn" type="PackedScene" id=6]
[node name="RigidBody" index="0" instance=ExtResource( 1 )]
[node name="RigidBody" instance=ExtResource( 1 )]
script = ExtResource( 2 ) script = ExtResource( 2 )
@ -29,10 +30,23 @@ lod_max_hysteresis = 0.0
mesh = ExtResource( 4 ) mesh = ExtResource( 4 )
skeleton = NodePath("..") skeleton = NodePath("..")
material/0 = null material/0 = null
_sections_unfolded = [ "Transform" ]
[node name="MainMesh" parent="Yaw" index="1"] [node name="MainMesh" parent="Yaw" index="1"]
mesh = ExtResource( 5 ) mesh = ExtResource( 5 )
[node name="Destroy" parent="MasterOnly" index="2" instance=ExtResource( 6 )]
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = -109.0
margin_top = -100.0
margin_right = -98.0
margin_bottom = -91.0
cost = 0
ability_name = "Destroy"
action = "primary_ability"

+ 30
- 2
scenes/heroes/5.tscn View File

@ -1,11 +1,12 @@
[gd_scene load_steps=5 format=2]
[gd_scene load_steps=6 format=2]
[ext_resource path="res://scenes/player.tscn" type="PackedScene" id=1] [ext_resource path="res://scenes/player.tscn" type="PackedScene" id=1]
[ext_resource path="res://scripts/heroes/5.gd" type="Script" id=2] [ext_resource path="res://scripts/heroes/5.gd" type="Script" id=2]
[ext_resource path="res://assets/heroes/5_head.obj" type="ArrayMesh" id=3] [ext_resource path="res://assets/heroes/5_head.obj" type="ArrayMesh" id=3]
[ext_resource path="res://assets/heroes/5.obj" type="ArrayMesh" id=4] [ext_resource path="res://assets/heroes/5.obj" type="ArrayMesh" id=4]
[ext_resource path="res://scenes/ability_icon.tscn" type="PackedScene" id=5]
[node name="RigidBody" index="0" instance=ExtResource( 1 )]
[node name="RigidBody" instance=ExtResource( 1 )]
script = ExtResource( 2 ) script = ExtResource( 2 )
@ -19,4 +20,31 @@ mesh = ExtResource( 3 )
transform = Transform( 1, 0, 0, 0, -1.62921e-07, -1, 0, 1, -1.62921e-07, 0, 0.556542, 0 ) transform = Transform( 1, 0, 0, 0, -1.62921e-07, -1, 0, 1, -1.62921e-07, 0, 0.556542, 0 )
mesh = ExtResource( 4 ) mesh = ExtResource( 4 )
[node name="Portal" parent="MasterOnly" index="2" instance=ExtResource( 5 )]
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = -160.0
margin_top = -112.0
margin_right = -149.0
margin_bottom = -103.0
cost = 75
ability_name = "Build Portal"
action = "hero_5_place_portal"
[node name="Teleport" parent="MasterOnly" index="3" instance=ExtResource( 5 )]
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = -70.0
margin_top = -112.0
margin_right = -59.0
margin_bottom = -103.0
cost = 5
ability_name = "Teleport"

+ 1
- 3
scenes/heroes/5_portal.tscn View File

@ -58,7 +58,7 @@ distance_fade_enable = false
points = PoolVector3Array( -0.746582, -0.00657654, 0.750488, 0.75293, 0.41748, 0.750488, 0.75293, -0.00657654, 0.750488, -0.746582, -0.00657654, -0.749023, -0.746582, 0.41748, 0.750488, -0.746582, -0.00657654, 0.750488, 0.75293, -0.00657654, -0.749023, -0.746582, 0.41748, -0.749023, -0.746582, -0.00657654, -0.749023, 0.75293, -0.00657654, 0.750488, 0.75293, 0.41748, -0.749023, 0.75293, -0.00657654, -0.749023, 0.541016, -0.00657654, -0.537598, -0.746582, -0.00657654, -0.749023, -0.535156, -0.00657654, -0.537598, 0.75293, 0.41748, 0.750488, 0.541016, 0.41748, -0.537598, 0.75293, 0.41748, -0.749023, -0.535156, -0.00657654, -0.537598, 0.541016, 0.41748, -0.537598, 0.541016, -0.00657654, -0.537598, -0.535156, -0.00657654, 0.538574, -0.535156, 0.41748, -0.537598, -0.535156, -0.00657654, -0.537598, -0.746582, 0.41748, -0.749023, -0.535156, 0.41748, 0.538574, -0.746582, 0.41748, 0.750488, 0.541016, -0.00657654, 0.538574, -0.535156, 0.41748, 0.538574, -0.535156, -0.00657654, 0.538574, 0.541016, -0.00657654, -0.537598, 0.541016, 0.41748, 0.538574, 0.541016, -0.00657654, 0.538574, 0.75293, -0.00657654, -0.749023, 0.541016, -0.00657654, 0.538574, 0.75293, -0.00657654, 0.750488, -0.746582, 0.41748, 0.750488, -0.746582, 0.41748, -0.749023, 0.75293, 0.41748, -0.749023, 0.75293, 0.41748, 0.750488, -0.746582, -0.00657654, 0.750488, -0.535156, -0.00657654, 0.538574, -0.535156, 0.41748, -0.537598, 0.541016, 0.41748, 0.538574, -0.535156, 0.41748, -0.537598, -0.535156, 0.41748, 0.538574, 0.541016, 0.41748, 0.538574, 0.541016, 0.41748, -0.537598 ) points = PoolVector3Array( -0.746582, -0.00657654, 0.750488, 0.75293, 0.41748, 0.750488, 0.75293, -0.00657654, 0.750488, -0.746582, -0.00657654, -0.749023, -0.746582, 0.41748, 0.750488, -0.746582, -0.00657654, 0.750488, 0.75293, -0.00657654, -0.749023, -0.746582, 0.41748, -0.749023, -0.746582, -0.00657654, -0.749023, 0.75293, -0.00657654, 0.750488, 0.75293, 0.41748, -0.749023, 0.75293, -0.00657654, -0.749023, 0.541016, -0.00657654, -0.537598, -0.746582, -0.00657654, -0.749023, -0.535156, -0.00657654, -0.537598, 0.75293, 0.41748, 0.750488, 0.541016, 0.41748, -0.537598, 0.75293, 0.41748, -0.749023, -0.535156, -0.00657654, -0.537598, 0.541016, 0.41748, -0.537598, 0.541016, -0.00657654, -0.537598, -0.535156, -0.00657654, 0.538574, -0.535156, 0.41748, -0.537598, -0.535156, -0.00657654, -0.537598, -0.746582, 0.41748, -0.749023, -0.535156, 0.41748, 0.538574, -0.746582, 0.41748, 0.750488, 0.541016, -0.00657654, 0.538574, -0.535156, 0.41748, 0.538574, -0.535156, -0.00657654, 0.538574, 0.541016, -0.00657654, -0.537598, 0.541016, 0.41748, 0.538574, 0.541016, -0.00657654, 0.538574, 0.75293, -0.00657654, -0.749023, 0.541016, -0.00657654, 0.538574, 0.75293, -0.00657654, 0.750488, -0.746582, 0.41748, 0.750488, -0.746582, 0.41748, -0.749023, 0.75293, 0.41748, -0.749023, 0.75293, 0.41748, 0.750488, -0.746582, -0.00657654, 0.750488, -0.535156, -0.00657654, 0.538574, -0.535156, 0.41748, -0.537598, 0.541016, 0.41748, 0.538574, -0.535156, 0.41748, -0.537598, -0.535156, 0.41748, 0.538574, 0.541016, 0.41748, 0.538574, 0.541016, 0.41748, -0.537598 )
[node name="StaticBody" type="StaticBody" index="0"]
[node name="StaticBody" type="StaticBody"]
input_ray_pickable = true input_ray_pickable = true
input_capture_on_drag = false input_capture_on_drag = false
@ -69,7 +69,6 @@ bounce = 0.0
constant_linear_velocity = Vector3( 0, 0, 0 ) constant_linear_velocity = Vector3( 0, 0, 0 )
constant_angular_velocity = Vector3( 0, 0, 0 ) constant_angular_velocity = Vector3( 0, 0, 0 )
script = ExtResource( 1 ) script = ExtResource( 1 )
_sections_unfolded = [ "Collision" ]
[node name="MeshInstance" type="MeshInstance" parent="." index="0"] [node name="MeshInstance" type="MeshInstance" parent="." index="0"]
@ -86,7 +85,6 @@ lod_max_hysteresis = 0.0
mesh = ExtResource( 2 ) mesh = ExtResource( 2 )
skeleton = NodePath("..") skeleton = NodePath("..")
material/0 = SubResource( 1 ) material/0 = SubResource( 1 )
_sections_unfolded = [ "Transform", "Visibility" ]
[node name="CollisionShape" type="CollisionShape" parent="." index="1"] [node name="CollisionShape" type="CollisionShape" parent="." index="1"]


+ 1
- 12
scenes/level.tscn View File

@ -24,7 +24,6 @@ size = 16
use_mipmaps = false use_mipmaps = false
use_filter = false use_filter = false
font_data = SubResource( 3 ) font_data = SubResource( 3 )
_sections_unfolded = [ "Font", "Resource" ]
[sub_resource type="ProceduralSky" id=5] [sub_resource type="ProceduralSky" id=5]
@ -45,7 +44,6 @@ sun_angle_max = 100.0
sun_curve = 0.05 sun_curve = 0.05
sun_energy = 16.0 sun_energy = 16.0
texture_size = 2 texture_size = 2
_sections_unfolded = [ "Ground", "Sky" ]
[sub_resource type="Environment" id=6] [sub_resource type="Environment" id=6]
@ -125,9 +123,8 @@ adjustment_enabled = false
adjustment_brightness = 1.0 adjustment_brightness = 1.0
adjustment_contrast = 1.0 adjustment_contrast = 1.0
adjustment_saturation = 1.0 adjustment_saturation = 1.0
_sections_unfolded = [ "Background" ]
[node name="Level" type="Spatial" index="0"]
[node name="Level" type="Spatial"]
[node name="DirectionalLight" type="DirectionalLight" parent="." index="0"] [node name="DirectionalLight" type="DirectionalLight" parent="." index="0"]
@ -158,8 +155,6 @@ directional_shadow_max_distance = 200.0
[node name="Players" type="Spatial" parent="." index="1"] [node name="Players" type="Spatial" parent="." index="1"]
_sections_unfolded = [ "Transform", "Visibility" ]
[node name="Ball" type="RigidBody" parent="." index="2"] [node name="Ball" type="RigidBody" parent="." index="2"]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -14.4344, 6.09969, 4.40885 ) transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -14.4344, 6.09969, 4.40885 )
@ -188,13 +183,11 @@ linear_velocity = Vector3( 0, 0, 0 )
linear_damp = -1.0 linear_damp = -1.0
angular_velocity = Vector3( 0, 0, 0 ) angular_velocity = Vector3( 0, 0, 0 )
angular_damp = -1.0 angular_damp = -1.0
_sections_unfolded = [ "Collision", "Pause", "Transform", "Visibility" ]
[node name="CollisionShape" type="CollisionShape" parent="Ball" index="0"] [node name="CollisionShape" type="CollisionShape" parent="Ball" index="0"]
shape = SubResource( 1 ) shape = SubResource( 1 )
disabled = false disabled = false
_sections_unfolded = [ "Transform", "Visibility" ]
[node name="MeshInstance" type="MeshInstance" parent="Ball" index="1"] [node name="MeshInstance" type="MeshInstance" parent="Ball" index="1"]
@ -210,12 +203,10 @@ lod_max_hysteresis = 0.0
mesh = SubResource( 2 ) mesh = SubResource( 2 )
skeleton = NodePath("..") skeleton = NodePath("..")
material/0 = null material/0 = null
_sections_unfolded = [ "Geometry", "Transform", "material" ]
[node name="FullObjective" parent="." index="3" instance=ExtResource( 1 )] [node name="FullObjective" parent="." index="3" instance=ExtResource( 1 )]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -17.3706, 2.0316, 4.06596 ) transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -17.3706, 2.0316, 4.06596 )
_sections_unfolded = [ "Transform" ]
[node name="Debug" type="Label" parent="." index="4"] [node name="Debug" type="Label" parent="." index="4"]
@ -237,12 +228,10 @@ custom_fonts/font = SubResource( 4 )
percent_visible = 1.0 percent_visible = 1.0
lines_skipped = 0 lines_skipped = 0
max_lines_visible = -1 max_lines_visible = -1
_sections_unfolded = [ "Anchor", "Focus", "Grow Direction", "Hint", "Margin", "Material", "Mouse", "Pause", "Rect", "Size Flags", "Theme", "Visibility", "custom_colors", "custom_constants", "custom_fonts", "custom_styles" ]
[node name="LeftSpawn" type="Spatial" parent="." index="5"] [node name="LeftSpawn" type="Spatial" parent="." index="5"]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.96426, 9.36109 ) transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.96426, 9.36109 )
_sections_unfolded = [ "Transform" ]
[node name="RightSpawn" type="Spatial" parent="." index="6"] [node name="RightSpawn" type="Spatial" parent="." index="6"]


+ 1
- 1
scenes/levels/0.tscn
File diff suppressed because it is too large
View File


+ 1
- 3
scenes/levels/2.tscn View File

@ -53,7 +53,6 @@ uv2_triplanar = false
uv2_triplanar_sharpness = 1.0 uv2_triplanar_sharpness = 1.0
proximity_fade_enable = false proximity_fade_enable = false
distance_fade_enable = false distance_fade_enable = false
_sections_unfolded = [ "Albedo", "Metallic" ]
[sub_resource type="ConcavePolygonShape" id=2] [sub_resource type="ConcavePolygonShape" id=2]
@ -70,7 +69,7 @@ subdivide_width = 0
subdivide_height = 0 subdivide_height = 0
subdivide_depth = 0 subdivide_depth = 0
[node name="Level" index="0" instance=ExtResource( 1 )]
[node name="Level" instance=ExtResource( 1 )]
[node name="DirectionalLight" parent="." index="0"] [node name="DirectionalLight" parent="." index="0"]
@ -95,7 +94,6 @@ mesh = ExtResource( 2 )
material/0 = SubResource( 1 ) material/0 = SubResource( 1 )
material/1 = null material/1 = null
material/2 = null material/2 = null
_sections_unfolded = [ "material" ]
[node name="StaticBody" type="StaticBody" parent="MainGeometry" index="0"] [node name="StaticBody" type="StaticBody" parent="MainGeometry" index="0"]


+ 120
- 475
scenes/lobby.tscn View File

@ -1,77 +1,30 @@
[gd_scene load_steps=7 format=2]
[gd_scene load_steps=8 format=2]
[ext_resource path="res://scripts/lobby.gd" type="Script" id=1]
[ext_resource path="res://scripts/hero_select.gd" type="Script" id=2]
[ext_resource path="res://assets/theme.tres" type="Theme" id=1]
[ext_resource path="res://scripts/lobby.gd" type="Script" id=2]
[ext_resource path="res://scenes/hero_select.tscn" type="PackedScene" id=3]
[ext_resource path="res://assets/DejaVuSansMono.ttf" type="DynamicFontData" id=4]
[sub_resource type="DynamicFontData" id=1]
font_path = "res://assets/DejaVuSansMono.ttf"
_sections_unfolded = [ "Resource" ]
[sub_resource type="DynamicFont" id=2]
[sub_resource type="DynamicFont" id=1]
size = 30 size = 30
use_mipmaps = false use_mipmaps = false
use_filter = false use_filter = false
font_data = SubResource( 1 )
_sections_unfolded = [ "Extra Spacing", "Font", "Resource", "Settings" ]
font_data = ExtResource( 4 )
[sub_resource type="DynamicFontData" id=3]
[sub_resource type="DynamicFontData" id=2]
font_path = "res://assets/DejaVuSansMono.ttf" font_path = "res://assets/DejaVuSansMono.ttf"
_sections_unfolded = [ "Resource" ]
[sub_resource type="DynamicFont" id=4]
[sub_resource type="DynamicFont" id=3]
size = 16 size = 16
use_mipmaps = false use_mipmaps = false
use_filter = false use_filter = false
font_data = SubResource( 3 )
_sections_unfolded = [ "Font", "Resource", "Settings" ]
[node name="Lobby" type="Control" index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 80.0
margin_top = 99.0
margin_right = 120.0
margin_bottom = 139.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
script = ExtResource( 1 )
_sections_unfolded = [ "Anchor" ]
[node name="Title" type="Label" parent="." index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 7.0
margin_top = -72.0
margin_right = 195.0
margin_bottom = -32.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
custom_fonts/font = SubResource( 2 )
text = "VANAGLORIA"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
_sections_unfolded = [ "custom_fonts" ]
font_data = SubResource( 2 )
[node name="GameBrowser" type="Control" parent="." index="1"]
[node name="Lobby" type="Control"]
editor/display_folded = true
anchor_left = 0.0 anchor_left = 0.0
anchor_top = 0.0 anchor_top = 0.0
anchor_right = 0.0 anchor_right = 0.0
@ -83,158 +36,67 @@ mouse_filter = 0
mouse_default_cursor_shape = 0 mouse_default_cursor_shape = 0
size_flags_horizontal = 1 size_flags_horizontal = 1
size_flags_vertical = 1 size_flags_vertical = 1
theme = ExtResource( 1 )
script = ExtResource( 2 )
[node name="Play" type="Button" parent="GameBrowser" index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 9.0
margin_top = -2.0
margin_right = 405.0
margin_bottom = 53.0
rect_pivot_offset = Vector2( 0, 0 )
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
toggle_mode = false
enabled_focus_mode = 2
shortcut = null
group = null
text = "Just, Play!"
flat = false
align = 1
[node name="PickAGameLabel" type="Label" parent="GameBrowser" index="1"]
[node name="HeroSelect" parent="." index="0" instance=ExtResource( 3 )]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 10.0
margin_top = 65.0
margin_right = 114.0
margin_bottom = 79.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
text = "Or, pick a game:"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
margin_left = 30.0
margin_top = 69.0
margin_right = 30.0
margin_bottom = 69.0
color = Color( 0.097229, 0.104696, 0.105469, 0 )
[node name="GameList" type="ItemList" parent="GameBrowser" index="2"]
[node name="Hero" parent="HeroSelect" index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 8.0
margin_top = 87.0
margin_right = 411.0
margin_bottom = 208.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = true
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
items = [ "No Games Running", null, false ]
select_mode = 0
icon_mode = 1
fixed_icon_size = Vector2( 0, 0 )
margin_left = -2.0
margin_top = 41.0
margin_right = 370.0
margin_bottom = 108.0
[node name="Join" type="Button" parent="GameBrowser" index="3"]
[node name="Confirm" parent="HeroSelect" index="1"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 9.0
margin_top = 217.0
margin_right = 163.0
margin_bottom = 244.0
rect_pivot_offset = Vector2( 0, 0 )
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
toggle_mode = false
enabled_focus_mode = 2
shortcut = null
group = null
text = "Join Selected Game"
flat = false
align = 1
[node name="VSeparator" type="VSeparator" parent="." index="2"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 431.0
margin_top = -3.0
margin_right = 436.0
margin_bottom = 234.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
visible = false
[node name="PlayerSettings" type="Control" parent="." index="3"]
[node name="HeroDescription" parent="HeroSelect" index="2"]
editor/display_folded = true
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_right = 40.0
margin_bottom = 40.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
margin_left = -2.0
margin_top = 125.0
margin_right = 366.0
margin_bottom = 288.0
text = "L Let s put oeuntahoeu nthaoeu ntaoheunt aoheunt hoaenth oaentuh Let s put oeuntahoeu nthaoeu ntaoheunt aoheunt hoaenth "
[node name="PlayerSettingsLabel" type="Label" parent="PlayerSettings" index="0"]
[node name="Title" type="Label" parent="HeroSelect" index="3"]
anchor_left = 0.0 anchor_left = 0.0
anchor_top = 0.0 anchor_top = 0.0
anchor_right = 0.0 anchor_right = 0.0
anchor_bottom = 0.0 anchor_bottom = 0.0
margin_left = 459.0
margin_top = -6.0
margin_right = 564.0
margin_bottom = 13.0
margin_left = 6.0
margin_top = 9.0
margin_right = 294.0
margin_bottom = 45.0
rect_pivot_offset = Vector2( 0, 0 ) rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 2 mouse_filter = 2
mouse_default_cursor_shape = 0 mouse_default_cursor_shape = 0
size_flags_horizontal = 1 size_flags_horizontal = 1
size_flags_vertical = 4 size_flags_vertical = 4
text = "Player Settings"
custom_fonts/font = SubResource( 1 )
text = "Select your hero"
percent_visible = 1.0 percent_visible = 1.0
lines_skipped = 0 lines_skipped = 0
max_lines_visible = -1 max_lines_visible = -1
[node name="Username" type="TextEdit" parent="PlayerSettings" index="1"]
[node name="Username" type="TextEdit" parent="." index="1"]
anchor_left = 0.0 anchor_left = 0.0
anchor_top = 0.0 anchor_top = 0.0
anchor_right = 0.0 anchor_right = 0.0
anchor_bottom = 0.0 anchor_bottom = 0.0
margin_left = 457.0
margin_top = 27.0
margin_right = 636.0
margin_bottom = 47.0
margin_left = 43.0
margin_top = 391.0
margin_right = 384.0
margin_bottom = 424.0
rect_pivot_offset = Vector2( 0, 0 ) rect_pivot_offset = Vector2( 0, 0 )
focus_mode = 2 focus_mode = 2
mouse_filter = 0 mouse_filter = 0
@ -258,37 +120,40 @@ caret_blink = false
caret_blink_speed = 0.65 caret_blink_speed = 0.65
caret_moving_by_right_click = true caret_moving_by_right_click = true
[node name="HeroSelectLabel" type="Label" parent="PlayerSettings" index="2"]
[node name="Spectating" type="CheckButton" parent="." index="2"]
anchor_left = 0.0 anchor_left = 0.0
anchor_top = 0.0 anchor_top = 0.0
anchor_right = 0.0 anchor_right = 0.0
anchor_bottom = 0.0 anchor_bottom = 0.0
margin_left = 460.0
margin_top = 66.0
margin_right = 538.0
margin_bottom = 80.0
margin_left = 36.0
margin_top = 439.0
margin_right = 237.0
margin_bottom = 479.0
rect_pivot_offset = Vector2( 0, 0 ) rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 2
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 0 mouse_default_cursor_shape = 0
size_flags_horizontal = 1 size_flags_horizontal = 1
size_flags_vertical = 4
text = "Hero Select:"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
size_flags_vertical = 1
toggle_mode = true
enabled_focus_mode = 2
shortcut = null
group = null
text = "Spectating "
flat = false
align = 0
[node name="HeroSelect" type="OptionButton" parent="PlayerSettings" index="3"]
[node name="LevelSelect" type="OptionButton" parent="." index="3"]
anchor_left = 0.0 anchor_left = 0.0
anchor_top = 0.0 anchor_top = 0.0
anchor_right = 0.0 anchor_right = 0.0
anchor_bottom = 0.0 anchor_bottom = 0.0
margin_left = 457.0
margin_top = 94.0
margin_right = 645.0
margin_bottom = 114.0
rect_rotation = -0.0115615
margin_left = 45.0
margin_top = 529.0
margin_right = 411.0
margin_bottom = 570.0
rect_pivot_offset = Vector2( 0, 0 ) rect_pivot_offset = Vector2( 0, 0 )
focus_mode = 2 focus_mode = 2
mouse_filter = 0 mouse_filter = 0
@ -300,289 +165,127 @@ action_mode = 0
enabled_focus_mode = 2 enabled_focus_mode = 2
shortcut = null shortcut = null
group = null group = null
text = "Platform map"
flat = false flat = false
align = 0 align = 0
selected = -1
items = [ ]
script = ExtResource( 2 )
selected = 0
items = [ "Platform map", null, false, 0, null, "City-like thing", null, false, 1, null, "Slide", null, false, 2, null ]
[node name="TeamLabel" type="Label" parent="PlayerSettings" index="4"]
[node name="Label" type="Label" parent="LevelSelect" index="1"]
anchor_left = 0.0 anchor_left = 0.0
anchor_top = 0.0 anchor_top = 0.0
anchor_right = 0.0 anchor_right = 0.0
anchor_bottom = 0.0 anchor_bottom = 0.0
margin_left = 459.0
margin_top = 132.0
margin_right = 558.0
margin_bottom = 146.0
margin_left = -5.0
margin_top = -37.0
margin_right = 39.0
margin_bottom = -15.0
rect_pivot_offset = Vector2( 0, 0 ) rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 2 mouse_filter = 2
mouse_default_cursor_shape = 0 mouse_default_cursor_shape = 0
size_flags_horizontal = 1 size_flags_horizontal = 1
size_flags_vertical = 4 size_flags_vertical = 4
text = "Assigned team:"
text = "Map:"
percent_visible = 1.0 percent_visible = 1.0
lines_skipped = 0 lines_skipped = 0
max_lines_visible = -1 max_lines_visible = -1
[node name="Team" type="Label" parent="PlayerSettings" index="5"]
[node name="TeamLabel" type="Label" parent="." index="4"]
anchor_left = 0.0 anchor_left = 0.0
anchor_top = 0.0 anchor_top = 0.0
anchor_right = 0.0 anchor_right = 0.0
anchor_bottom = 0.0 anchor_bottom = 0.0
margin_left = 460.0
margin_top = 157.0
margin_right = 500.0
margin_bottom = 171.0
margin_left = 498.0
margin_top = 87.0
margin_right = 666.0
margin_bottom = 111.0
rect_pivot_offset = Vector2( 0, 0 ) rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 2 mouse_filter = 2
mouse_default_cursor_shape = 0 mouse_default_cursor_shape = 0
size_flags_horizontal = 1 size_flags_horizontal = 1
size_flags_vertical = 4 size_flags_vertical = 4
text = "Your team:"
percent_visible = 1.0 percent_visible = 1.0
lines_skipped = 0 lines_skipped = 0
max_lines_visible = -1 max_lines_visible = -1
[node name="HeroDescriptionLabel" type="Label" parent="PlayerSettings" index="6"]
[node name="Team" type="Label" parent="." index="5"]
anchor_left = 0.0 anchor_left = 0.0
anchor_top = 0.0 anchor_top = 0.0
anchor_right = 0.0 anchor_right = 0.0
anchor_bottom = 0.0 anchor_bottom = 0.0
margin_left = 677.0
margin_top = -5.0
margin_right = 790.0
margin_bottom = 9.0
margin_left = 625.0
margin_top = 87.0
margin_right = 665.0
margin_bottom = 111.0
rect_pivot_offset = Vector2( 0, 0 ) rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 2 mouse_filter = 2
mouse_default_cursor_shape = 0 mouse_default_cursor_shape = 0
size_flags_horizontal = 1 size_flags_horizontal = 1
size_flags_vertical = 4 size_flags_vertical = 4
text = "Hero Description:"
percent_visible = 1.0 percent_visible = 1.0
lines_skipped = 0 lines_skipped = 0
max_lines_visible = -1 max_lines_visible = -1
[node name="HeroDescription" type="RichTextLabel" parent="PlayerSettings" index="7"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 675.0
margin_top = 15.0
margin_right = 918.0
margin_bottom = 245.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = true
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
bbcode_enabled = false
bbcode_text = ""
visible_characters = -1
percent_visible = 1.0
meta_underlined = true
tab_size = 4
text = ""
scroll_active = true
scroll_following = false
selection_enabled = false
override_selected_font_color = false
[node name="HSeparator3" type="HSeparator" parent="." index="4"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 19.0
margin_top = 271.0
margin_right = 645.0
margin_bottom = 275.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
[node name="CustomGame" type="Control" parent="." index="5"]
[node name="PlayerList" type="Label" parent="." index="6"]
editor/display_folded = true
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_right = 40.0
margin_bottom = 40.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
[node name="Label" type="Label" parent="CustomGame" index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 671.0
margin_top = 275.0
margin_right = 874.0
margin_bottom = 289.0
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
margin_left = 480.0
margin_top = 130.0
margin_right = 981.0
margin_bottom = 408.0
rect_pivot_offset = Vector2( 0, 0 ) rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 2 mouse_filter = 2
mouse_default_cursor_shape = 0 mouse_default_cursor_shape = 0
size_flags_horizontal = 1 size_flags_horizontal = 1
size_flags_vertical = 4 size_flags_vertical = 4
text = "Or, host or join a custom game:"
custom_fonts/font = SubResource( 3 )
text = "Waiting for players to connect...."
percent_visible = 1.0 percent_visible = 1.0
lines_skipped = 0 lines_skipped = 0
max_lines_visible = -1 max_lines_visible = -1
[node name="Server" type="Button" parent="CustomGame" index="1"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 665.0
margin_top = 300.0
margin_right = 752.0
margin_bottom = 335.0
rect_pivot_offset = Vector2( 0, 0 )
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
toggle_mode = false
enabled_focus_mode = 2
shortcut = null
group = null
text = "Server"
flat = false
align = 1
[node name="LevelSelect" type="OptionButton" parent="CustomGame" index="2"]
[node name="Ready" type="CheckButton" parent="." index="7"]
anchor_left = 0.0 anchor_left = 0.0
anchor_top = 0.0 anchor_top = 0.0
anchor_right = 0.0 anchor_right = 0.0
anchor_bottom = 0.0 anchor_bottom = 0.0
margin_left = 770.0
margin_top = 300.0
margin_right = 895.0
margin_bottom = 335.0
margin_left = 493.0
margin_top = 436.0
margin_right = 628.0
margin_bottom = 476.0
rect_pivot_offset = Vector2( 0, 0 ) rect_pivot_offset = Vector2( 0, 0 )
focus_mode = 2 focus_mode = 2
mouse_filter = 0 mouse_filter = 0
mouse_default_cursor_shape = 0 mouse_default_cursor_shape = 0
size_flags_horizontal = 1 size_flags_horizontal = 1
size_flags_vertical = 1 size_flags_vertical = 1
toggle_mode = false
action_mode = 0
toggle_mode = true
enabled_focus_mode = 2 enabled_focus_mode = 2
shortcut = null shortcut = null
group = null group = null
text = "Platform map"
text = "Ready "
flat = false flat = false
align = 0 align = 0
selected = 0
items = [ "Platform map", null, false, 0, null, "City-like thing", null, false, 1, null, "Slide", null, false, 2, null ]
[node name="Client" type="Button" parent="CustomGame" index="3"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 667.0
margin_top = 354.0
margin_right = 753.0
margin_bottom = 393.0
rect_pivot_offset = Vector2( 0, 0 )
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
toggle_mode = false
enabled_focus_mode = 2
shortcut = null
group = null
text = "Client"
flat = false
align = 1
[node name="IPLabel" type="Label" parent="CustomGame" index="4"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 673.0
margin_top = 403.0
margin_right = 698.0
margin_bottom = 419.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
text = "IP:"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
_sections_unfolded = [ "Visibility" ]
[node name="IP" type="TextEdit" parent="CustomGame" index="5"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 707.0
margin_top = 401.0
margin_right = 851.0
margin_bottom = 419.0
rect_pivot_offset = Vector2( 0, 0 )
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
text = "127.0.0.1"
readonly = false
highlight_current_line = false
syntax_highlighting = false
show_line_numbers = false
highlight_all_occurrences = false
override_selected_font_color = false
context_menu_enabled = true
smooth_scrolling = false
v_scroll_speed = 80.0
hiding_enabled = 0
wrap_lines = false
caret_block_mode = false
caret_blink = false
caret_blink_speed = 0.65
caret_moving_by_right_click = true
[node name="Singleplayer" type="Button" parent="CustomGame" index="6"]
[node name="StartGame" type="Button" parent="." index="8"]
visible = false
anchor_left = 0.0 anchor_left = 0.0
anchor_top = 0.0 anchor_top = 0.0
anchor_right = 0.0 anchor_right = 0.0
anchor_bottom = 0.0 anchor_bottom = 0.0
margin_left = 668.0
margin_top = 431.0
margin_right = 760.0
margin_bottom = 470.0
margin_left = 496.0
margin_top = 491.0
margin_right = 618.0
margin_bottom = 531.0
rect_pivot_offset = Vector2( 0, 0 ) rect_pivot_offset = Vector2( 0, 0 )
focus_mode = 2 focus_mode = 2
mouse_filter = 0 mouse_filter = 0
@ -593,94 +296,36 @@ toggle_mode = false
enabled_focus_mode = 2 enabled_focus_mode = 2
shortcut = null shortcut = null
group = null group = null
text = "Singleplayer"
text = "Start!"
flat = false flat = false
align = 1 align = 1
[node name="VSeparator2" type="VSeparator" parent="." index="6"]
[node name="VSeparator" type="VSeparator" parent="." index="9"]
anchor_left = 0.0 anchor_left = 0.0
anchor_top = 0.0 anchor_top = 0.0
anchor_right = 0.0 anchor_right = 0.0
anchor_bottom = 0.0 anchor_bottom = 0.0
margin_left = 653.0
margin_top = 273.0
margin_right = 657.0
margin_bottom = 467.0
margin_left = 453.0
margin_top = 50.0
margin_right = 471.0
margin_bottom = 566.0
rect_pivot_offset = Vector2( 0, 0 ) rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 0 mouse_filter = 0
mouse_default_cursor_shape = 0 mouse_default_cursor_shape = 0
size_flags_horizontal = 1 size_flags_horizontal = 1
size_flags_vertical = 1 size_flags_vertical = 1
[node name="JoinedGameLobby" type="Control" parent="." index="7"]
editor/display_folded = true
visible = false
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_right = 40.0
margin_bottom = 40.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
[node name="PlayerListLabel" type="Label" parent="JoinedGameLobby" index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 14.0
margin_top = 287.0
margin_right = 136.0
margin_bottom = 301.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
text = "Connected Players:"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[node name="PlayerList" type="Label" parent="JoinedGameLobby" index="1"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
margin_left = -7.0
margin_top = 287.0
margin_right = 639.0
margin_bottom = 433.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
custom_fonts/font = SubResource( 4 )
text = "Waiting for players to connect...."
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
_sections_unfolded = [ "BBCode", "custom_fonts" ]
[node name="StartGame" type="Button" parent="JoinedGameLobby" index="2"]
[node name="Back" type="Button" parent="." index="10"]
anchor_left = 0.0 anchor_left = 0.0
anchor_top = 0.0 anchor_top = 0.0
anchor_right = 0.0 anchor_right = 0.0
anchor_bottom = 0.0 anchor_bottom = 0.0
margin_left = 13.0
margin_left = 834.0
margin_top = 443.0 margin_top = 443.0
margin_right = 135.0
margin_bottom = 483.0
margin_right = 978.0
margin_bottom = 471.0
rect_pivot_offset = Vector2( 0, 0 ) rect_pivot_offset = Vector2( 0, 0 )
focus_mode = 2 focus_mode = 2
mouse_filter = 0 mouse_filter = 0
@ -691,9 +336,9 @@ toggle_mode = false
enabled_focus_mode = 2 enabled_focus_mode = 2
shortcut = null shortcut = null
group = null group = null
text = "Start game"
text = "Exit to menu"
flat = false flat = false
align = 1 align = 1
_sections_unfolded = [ "Visibility" ]
[editable path="HeroSelect"]

+ 164
- 0
scenes/menu.tscn View File

@ -0,0 +1,164 @@
[gd_scene load_steps=5 format=2]
[ext_resource path="res://assets/theme.tres" type="Theme" id=1]
[ext_resource path="res://scripts/menu.gd" type="Script" id=2]
[sub_resource type="DynamicFontData" id=1]
font_path = "res://assets/DejaVuSansMono.ttf"
[sub_resource type="DynamicFont" id=2]
size = 30
use_mipmaps = false
use_filter = false
font_data = SubResource( 1 )
[node name="Menu" type="Control"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 1.0
anchor_bottom = 1.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
theme = ExtResource( 1 )
script = ExtResource( 2 )
[node name="Center" type="Control" parent="." index="0"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
margin_left = -20.0
margin_top = -20.0
margin_right = 20.0
margin_bottom = 20.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
[node name="Play" type="Button" parent="Center" index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = -250.0
margin_top = -140.0
margin_right = 298.0
margin_bottom = -80.0
rect_pivot_offset = Vector2( 0, 0 )
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
toggle_mode = false
enabled_focus_mode = 2
shortcut = null
group = null
text = "Quick Play"
flat = false
align = 1
[node name="CustomGame" type="Button" parent="Center" index="1"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = -252.0
margin_top = -56.0
margin_right = 300.0
margin_bottom = 5.0
rect_pivot_offset = Vector2( 0, 0 )
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
toggle_mode = false
enabled_focus_mode = 2
shortcut = null
group = null
text = "Custom Game"
flat = false
align = 1
[node name="Singleplayer" type="Button" parent="Center" index="2"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = -251.0
margin_top = 34.0
margin_right = 299.0
margin_bottom = 100.0
rect_pivot_offset = Vector2( 0, 0 )
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
toggle_mode = false
enabled_focus_mode = 2
shortcut = null
group = null
text = "Practice Range"
flat = false
align = 1
[node name="Quit" type="Button" parent="Center" index="3"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = -252.0
margin_top = 130.0
margin_right = 298.0
margin_bottom = 196.0
rect_pivot_offset = Vector2( 0, 0 )
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
toggle_mode = false
enabled_focus_mode = 2
shortcut = null
group = null
text = "Quit"
flat = false
align = 1
[node name="Title" type="Label" parent="Center" index="4"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = -72.0
margin_top = -230.0
margin_right = 116.0
margin_bottom = -190.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
custom_fonts/font = SubResource( 2 )
text = "VANAGLORIA"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1

+ 1
- 11
scenes/objective.tscn View File

@ -58,7 +58,6 @@ uv2_triplanar = false
uv2_triplanar_sharpness = 1.0 uv2_triplanar_sharpness = 1.0
proximity_fade_enable = false proximity_fade_enable = false
distance_fade_enable = false distance_fade_enable = false
_sections_unfolded = [ "Albedo" ]
[sub_resource type="CapsuleShape" id=3] [sub_resource type="CapsuleShape" id=3]
@ -71,9 +70,8 @@ size = 50
use_mipmaps = false use_mipmaps = false
use_filter = false use_filter = false
font_data = ExtResource( 3 ) font_data = ExtResource( 3 )
_sections_unfolded = [ "Extra Spacing", "Font", "Resource", "Settings" ]
[node name="FullObjective" type="Spatial" index="0"]
[node name="FullObjective" type="Spatial"]
[node name="Objective" type="RigidBody" parent="." index="0"] [node name="Objective" type="RigidBody" parent="." index="0"]
@ -103,13 +101,11 @@ linear_damp = -1.0
angular_velocity = Vector3( 0, 0, 0 ) angular_velocity = Vector3( 0, 0, 0 )
angular_damp = -1.0 angular_damp = -1.0
script = ExtResource( 1 ) script = ExtResource( 1 )
_sections_unfolded = [ "Axis Lock", "Collision", "Linear", "Transform", "Visibility" ]
[node name="CollisionShape" type="CollisionShape" parent="Objective" index="0"] [node name="CollisionShape" type="CollisionShape" parent="Objective" index="0"]
shape = SubResource( 1 ) shape = SubResource( 1 )
disabled = false disabled = false
_sections_unfolded = [ "Transform" ]
[node name="MeshInstance" type="MeshInstance" parent="Objective" index="1"] [node name="MeshInstance" type="MeshInstance" parent="Objective" index="1"]
@ -125,7 +121,6 @@ lod_max_hysteresis = 0.0
mesh = ExtResource( 2 ) mesh = ExtResource( 2 )
skeleton = NodePath("..") skeleton = NodePath("..")
material/0 = SubResource( 2 ) material/0 = SubResource( 2 )
_sections_unfolded = [ "Transform", "material" ]
[node name="HingeJoint" type="HingeJoint" parent="." index="1"] [node name="HingeJoint" type="HingeJoint" parent="." index="1"]
@ -144,7 +139,6 @@ angular_limit/relaxation = 1.0
motor/enable = false motor/enable = false
motor/target_velocity = 1.0 motor/target_velocity = 1.0
motor/max_impulse = 1.0 motor/max_impulse = 1.0
_sections_unfolded = [ "Transform", "Visibility", "angular_limit", "collision", "motor", "nodes", "params", "solver" ]
[node name="Rod" type="StaticBody" parent="." index="2"] [node name="Rod" type="StaticBody" parent="." index="2"]
@ -157,13 +151,11 @@ friction = 1.0
bounce = 0.0 bounce = 0.0
constant_linear_velocity = Vector3( 0, 0, 0 ) constant_linear_velocity = Vector3( 0, 0, 0 )
constant_angular_velocity = Vector3( 0, 0, 0 ) constant_angular_velocity = Vector3( 0, 0, 0 )
_sections_unfolded = [ "Collision", "Transform" ]
[node name="CollisionShape" type="CollisionShape" parent="Rod" index="0"] [node name="CollisionShape" type="CollisionShape" parent="Rod" index="0"]
shape = SubResource( 3 ) shape = SubResource( 3 )
disabled = false disabled = false
_sections_unfolded = [ "Transform", "Visibility" ]
[node name="HUD" type="Control" parent="." index="3"] [node name="HUD" type="Control" parent="." index="3"]
@ -217,7 +209,6 @@ align = 1
percent_visible = 1.0 percent_visible = 1.0
lines_skipped = 0 lines_skipped = 0
max_lines_visible = -1 max_lines_visible = -1
_sections_unfolded = [ "Theme" ]
[node name="RightTeam" type="Label" parent="HUD" index="2"] [node name="RightTeam" type="Label" parent="HUD" index="2"]
@ -261,6 +252,5 @@ align = 1
percent_visible = 1.0 percent_visible = 1.0
lines_skipped = 0 lines_skipped = 0
max_lines_visible = -1 max_lines_visible = -1
_sections_unfolded = [ "custom_colors", "custom_constants", "custom_fonts", "custom_styles" ]

+ 171
- 29
scenes/player.tscn View File

@ -1,8 +1,9 @@
[gd_scene load_steps=10 format=2]
[gd_scene load_steps=15 format=2]
[ext_resource path="res://scripts/player.gd" type="Script" id=1] [ext_resource path="res://scripts/player.gd" type="Script" id=1]
[ext_resource path="res://scripts/tp_camera.gd" type="Script" id=2]
[ext_resource path="res://scripts/player_name.gd" type="Script" id=3]
[ext_resource path="res://scenes/ability_icon.tscn" type="PackedScene" id=2]
[ext_resource path="res://scripts/tp_camera.gd" type="Script" id=3]
[ext_resource path="res://scripts/player_name.gd" type="Script" id=4]
[sub_resource type="CapsuleShape" id=1] [sub_resource type="CapsuleShape" id=1]
@ -12,7 +13,6 @@ height = 0.5
[sub_resource type="RayShape" id=2] [sub_resource type="RayShape" id=2]
length = 0.1 length = 0.1
_sections_unfolded = [ "Resource" ]
[sub_resource type="PrismMesh" id=3] [sub_resource type="PrismMesh" id=3]
@ -28,7 +28,97 @@ radius = 0.4
mid_height = 0.1 mid_height = 0.1
radial_segments = 64 radial_segments = 64
rings = 8 rings = 8
_sections_unfolded = [ "Resource" ]
[sub_resource type="StyleBoxFlat" id=7]
content_margin_left = -1.0
content_margin_right = -1.0
content_margin_top = -1.0
content_margin_bottom = -1.0
bg_color = Color( 0.541351, 0.855469, 0.612519, 1 )
draw_center = true
border_width_left = 0
border_width_top = 0
border_width_right = 0
border_width_bottom = 0
border_color = Color( 0.8, 0.8, 0.8, 1 )
border_blend = false
corner_radius_top_left = 0
corner_radius_top_right = 0
corner_radius_bottom_right = 0
corner_radius_bottom_left = 0
corner_detail = 8
expand_margin_left = 0.0
expand_margin_right = 0.0
expand_margin_top = 0.0
expand_margin_bottom = 0.0
shadow_color = Color( 0, 0, 0, 0.6 )
shadow_size = 0
anti_aliasing = true
anti_aliasing_size = 1
[sub_resource type="StyleBoxFlat" id=8]
content_margin_left = -1.0
content_margin_right = -1.0
content_margin_top = -1.0
content_margin_bottom = -1.0
bg_color = Color( 0.00305176, 0.0976562, 0.0111818, 1 )
draw_center = true
border_width_left = 0
border_width_top = 0
border_width_right = 0
border_width_bottom = 0
border_color = Color( 0.8, 0.8, 0.8, 1 )
border_blend = false
corner_radius_top_left = 0
corner_radius_top_right = 0
corner_radius_bottom_right = 0
corner_radius_bottom_left = 0
corner_detail = 8
expand_margin_left = 0.0
expand_margin_right = 0.0
expand_margin_top = 0.0
expand_margin_bottom = 0.0
shadow_color = Color( 0, 0, 0, 0.6 )
shadow_size = 0
anti_aliasing = true
anti_aliasing_size = 1
[sub_resource type="StyleBoxFlat" id=9]
content_margin_left = -1.0
content_margin_right = -1.0
content_margin_top = -1.0
content_margin_bottom = -1.0
bg_color = Color( 0.878769, 0.949219, 0.911242, 1 )
draw_center = true
border_width_left = 0
border_width_top = 0
border_width_right = 0
border_width_bottom = 0
border_color = Color( 0.8, 0.8, 0.8, 1 )
border_blend = false
corner_radius_top_left = 0
corner_radius_top_right = 0
corner_radius_bottom_right = 0
corner_radius_bottom_left = 0
corner_detail = 8
expand_margin_left = 0.0
expand_margin_right = 0.0
expand_margin_top = 0.0
expand_margin_bottom = 0.0
shadow_color = Color( 0, 0, 0, 0.6 )
shadow_size = 0
anti_aliasing = true
anti_aliasing_size = 1
[sub_resource type="StyleBoxEmpty" id=10]
content_margin_left = -1.0
content_margin_right = -1.0
content_margin_top = -1.0
content_margin_bottom = -1.0
[sub_resource type="CubeMesh" id=5] [sub_resource type="CubeMesh" id=5]
@ -87,9 +177,8 @@ uv2_triplanar = false
uv2_triplanar_sharpness = 1.0 uv2_triplanar_sharpness = 1.0
proximity_fade_enable = false proximity_fade_enable = false
distance_fade_enable = false distance_fade_enable = false
_sections_unfolded = [ "Flags", "Parameters", "Roughness" ]
[node name="RigidBody" type="RigidBody" index="0" groups=[
[node name="RigidBody" type="RigidBody" groups=[
"player", "player",
]] ]]
@ -119,21 +208,18 @@ linear_damp = -1.0
angular_velocity = Vector3( 0, 0, 0 ) angular_velocity = Vector3( 0, 0, 0 )
angular_damp = -1.0 angular_damp = -1.0
script = ExtResource( 1 ) script = ExtResource( 1 )
_sections_unfolded = [ "Angular", "Axis Lock", "Collision", "Linear", "Transform", "Visibility", "collision" ]
[node name="Body" type="CollisionShape" parent="." index="0"] [node name="Body" type="CollisionShape" parent="." index="0"]
transform = Transform( 1, 0, 0, 0, -1.62921e-07, -1, 0, 1, -1.62921e-07, 0, 0.75, 0 ) transform = Transform( 1, 0, 0, 0, -1.62921e-07, -1, 0, 1, -1.62921e-07, 0, 0.75, 0 )
shape = SubResource( 1 ) shape = SubResource( 1 )
disabled = false disabled = false
_sections_unfolded = [ "Pause", "Transform", "Visibility" ]
[node name="Leg" type="CollisionShape" parent="." index="1"] [node name="Leg" type="CollisionShape" parent="." index="1"]
transform = Transform( 1, 0, 0, 0, -1.62921e-07, -1, 0, 1, -1.62921e-07, 0.05, 0.1, 0 ) transform = Transform( 1, 0, 0, 0, -1.62921e-07, -1, 0, 1, -1.62921e-07, 0.05, 0.1, 0 )
shape = SubResource( 2 ) shape = SubResource( 2 )
disabled = false disabled = false
_sections_unfolded = [ "Transform", "Visibility" ]
[node name="Ray" type="RayCast" parent="." index="2"] [node name="Ray" type="RayCast" parent="." index="2"]
@ -142,16 +228,13 @@ enabled = true
exclude_parent = true exclude_parent = true
cast_to = Vector3( 0, -0.2, 0 ) cast_to = Vector3( 0, -0.2, 0 )
collision_mask = 1 collision_mask = 1
_sections_unfolded = [ "Transform", "Visibility" ]
[node name="Yaw" type="Spatial" parent="." index="3"] [node name="Yaw" type="Spatial" parent="." index="3"]
_sections_unfolded = [ "Transform" ]
[node name="Pitch" type="Spatial" parent="Yaw" index="0"] [node name="Pitch" type="Spatial" parent="Yaw" index="0"]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.19053, 0 ) transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.19053, 0 )
_sections_unfolded = [ "Transform" ]
[node name="RotatedHead" type="MeshInstance" parent="Yaw/Pitch" index="0"] [node name="RotatedHead" type="MeshInstance" parent="Yaw/Pitch" index="0"]
@ -168,7 +251,6 @@ lod_max_hysteresis = 0.0
mesh = SubResource( 3 ) mesh = SubResource( 3 )
skeleton = NodePath("..") skeleton = NodePath("..")
material/0 = null material/0 = null
_sections_unfolded = [ "Transform", "material" ]
[node name="MainMesh" type="MeshInstance" parent="Yaw" index="1"] [node name="MainMesh" type="MeshInstance" parent="Yaw" index="1"]
@ -185,7 +267,6 @@ lod_max_hysteresis = 0.0
mesh = SubResource( 4 ) mesh = SubResource( 4 )
skeleton = NodePath("..") skeleton = NodePath("..")
material/0 = null material/0 = null
_sections_unfolded = [ "Transform", "material" ]
[node name="MasterOnly" type="Node" parent="." index="4"] [node name="MasterOnly" type="Node" parent="." index="4"]
@ -210,35 +291,99 @@ align = 1
percent_visible = 1.0 percent_visible = 1.0
lines_skipped = 0 lines_skipped = 0
max_lines_visible = -1 max_lines_visible = -1
_sections_unfolded = [ "Anchor", "Margin", "custom_colors" ]
[node name="SwitchCharge" type="Label" parent="MasterOnly" index="1"]
[node name="ChargeBar" type="ProgressBar" parent="MasterOnly" index="1"]
anchor_left = 0.5
anchor_top = 1.0
anchor_right = 0.5
anchor_bottom = 1.0
margin_left = -484.0
margin_top = -41.0
margin_right = 483.0
margin_bottom = -25.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 0
custom_styles/fg = SubResource( 7 )
custom_styles/bg = SubResource( 8 )
min_value = 0.0
max_value = 100.0
step = 1.0
page = 0.0
value = 0.0
exp_edit = false
rounded = false
percent_visible = false
[node name="Extra" type="ProgressBar" parent="MasterOnly/ChargeBar" index="0"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
margin_left = -484.0
margin_top = -8.0
margin_right = 484.0
margin_bottom = 8.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 0
custom_styles/fg = SubResource( 9 )
custom_styles/bg = SubResource( 10 )
min_value = 0.0
max_value = 100.0
step = 1.0
page = 0.0
value = 0.0
exp_edit = false
rounded = false
percent_visible = false
[node name="ChargeText" type="Label" parent="MasterOnly/ChargeBar" index="1"]
anchor_left = 0.5 anchor_left = 0.5
anchor_top = 1.0 anchor_top = 1.0
anchor_right = 0.5 anchor_right = 0.5
anchor_bottom = 1.0 anchor_bottom = 1.0
margin_left = -62.0
margin_top = -98.0
margin_right = 61.0
margin_bottom = -84.0
margin_left = -61.5
margin_top = -14.0
margin_right = 61.5
rect_pivot_offset = Vector2( 0, 0 ) rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 2 mouse_filter = 2
mouse_default_cursor_shape = 0 mouse_default_cursor_shape = 0
size_flags_horizontal = 1 size_flags_horizontal = 1
size_flags_vertical = 4 size_flags_vertical = 4
custom_colors/font_color = Color( 0.289062, 0.289062, 0.289062, 1 )
custom_colors/font_color = Color( 0.456299, 0.689711, 0.695312, 1 )
custom_colors/font_color_shadow = Color( 0.0868835, 0.304688, 0.304688, 1 )
text = "0%"
align = 1 align = 1
percent_visible = 1.0 percent_visible = 1.0
lines_skipped = 0 lines_skipped = 0
max_lines_visible = -1 max_lines_visible = -1
_sections_unfolded = [ "custom_colors" ]
[node name="SwitchHero" parent="MasterOnly" index="2" instance=ExtResource( 2 )]
visible = false
anchor_left = 0.5
anchor_top = 1.0
anchor_right = 0.5
anchor_bottom = 1.0
margin_top = -107.0
margin_bottom = -98.0
cost = 100
ability_name = "Switch Hero"
display_progress = false
action = "switch_hero"
[node name="TPCamera" type="Spatial" parent="." index="5"] [node name="TPCamera" type="Spatial" parent="." index="5"]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.56913, 0 ) transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.56913, 0 )
script = ExtResource( 2 )
_sections_unfolded = [ "Transform" ]
script = ExtResource( 3 )
cam = NodePath("Camera") cam = NodePath("Camera")
pivot = NodePath("Pivot") pivot = NodePath("Pivot")
@ -265,7 +410,6 @@ enabled = true
exclude_parent = true exclude_parent = true
cast_to = Vector3( 0, 0, -500 ) cast_to = Vector3( 0, 0, -500 )
collision_mask = 13 collision_mask = 13
_sections_unfolded = [ "Transform" ]
[node name="MaterialSettings" type="MeshInstance" parent="." index="6"] [node name="MaterialSettings" type="MeshInstance" parent="." index="6"]
@ -282,7 +426,6 @@ lod_max_hysteresis = 0.0
mesh = SubResource( 5 ) mesh = SubResource( 5 )
skeleton = NodePath("..") skeleton = NodePath("..")
material/0 = SubResource( 6 ) material/0 = SubResource( 6 )
_sections_unfolded = [ "material" ]
[node name="NamePosition" type="Spatial" parent="." index="7"] [node name="NamePosition" type="Spatial" parent="." index="7"]
@ -306,7 +449,6 @@ align = 1
percent_visible = 1.0 percent_visible = 1.0
lines_skipped = 0 lines_skipped = 0
max_lines_visible = -1 max_lines_visible = -1
script = ExtResource( 3 )
_sections_unfolded = [ "custom_colors" ]
script = ExtResource( 4 )

+ 87
- 0
scenes/singleplayer_lobby.tscn View File

@ -0,0 +1,87 @@
[gd_scene load_steps=4 format=2]
[ext_resource path="res://scenes/lobby.tscn" type="PackedScene" id=1]
[ext_resource path="res://assets/DejaVuSansMono.ttf" type="DynamicFontData" id=2]
[sub_resource type="DynamicFont" id=1]
size = 40
use_mipmaps = false
use_filter = false
font_data = ExtResource( 2 )
[node name="Lobby" instance=ExtResource( 1 )]
[node name="Label" type="Label" parent="." index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 602.0
margin_top = 276.0
margin_right = 938.0
margin_bottom = 324.0
rect_pivot_offset = Vector2( 0, 0 )
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
custom_fonts/font = SubResource( 1 )
text = "Practice Range"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[node name="HeroSelect" parent="." index="1"]
margin_top = 62.0
margin_bottom = 62.0
[node name="Username" parent="." index="2"]
visible = false
margin_top = 308.0
margin_bottom = 341.0
[node name="Spectating" parent="." index="3"]
visible = false
[node name="LevelSelect" parent="." index="4"]
margin_top = 401.0
margin_bottom = 442.0
items = [ "Platform map", null, false, 0, null, "City-like thing", null, false, 1, null, "Slide", null, false, 2, null ]
[node name="TeamLabel" parent="." index="5"]
visible = false
[node name="Team" parent="." index="6"]
visible = false
[node name="PlayerList" parent="." index="7"]
visible = false
[node name="Ready" parent="." index="8"]
visible = false
[node name="StartGame" parent="." index="9"]
visible = true
margin_left = 41.0
margin_top = 486.0
margin_right = 163.0
margin_bottom = 526.0
text = "Play!"
[node name="VSeparator" parent="." index="10"]
visible = false
[editable path="HeroSelect"]

+ 0
- 8
scenes/test-level.tscn View File

@ -29,7 +29,6 @@ size = 16
use_mipmaps = false use_mipmaps = false
use_filter = false use_filter = false
font_data = SubResource( 4 ) font_data = SubResource( 4 )
_sections_unfolded = [ "Font", "Resource" ]
[node name="world" type="Spatial"] [node name="world" type="Spatial"]
@ -63,7 +62,6 @@ directional_shadow_max_distance = 200.0
[node name="players" type="Spatial" parent="." index="1"] [node name="players" type="Spatial" parent="." index="1"]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 11.4634, 0 ) transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 11.4634, 0 )
_sections_unfolded = [ "Transform", "Visibility" ]
[node name="Maze" type="MeshInstance" parent="." index="2"] [node name="Maze" type="MeshInstance" parent="." index="2"]
@ -125,13 +123,11 @@ linear_velocity = Vector3( 0, 0, 0 )
linear_damp = -1.0 linear_damp = -1.0
angular_velocity = Vector3( 0, 0, 0 ) angular_velocity = Vector3( 0, 0, 0 )
angular_damp = -1.0 angular_damp = -1.0
_sections_unfolded = [ "Collision", "Pause", "Transform", "Visibility" ]
[node name="CollisionShape" type="CollisionShape" parent="Ball" index="0"] [node name="CollisionShape" type="CollisionShape" parent="Ball" index="0"]
shape = SubResource( 2 ) shape = SubResource( 2 )
disabled = false disabled = false
_sections_unfolded = [ "Transform", "Visibility" ]
[node name="MeshInstance" type="MeshInstance" parent="Ball" index="1"] [node name="MeshInstance" type="MeshInstance" parent="Ball" index="1"]
@ -147,12 +143,10 @@ lod_max_hysteresis = 0.0
mesh = SubResource( 3 ) mesh = SubResource( 3 )
skeleton = NodePath("..") skeleton = NodePath("..")
material/0 = null material/0 = null
_sections_unfolded = [ "Geometry", "Transform", "material" ]
[node name="FullObjective" parent="." index="4" instance=ExtResource( 2 )] [node name="FullObjective" parent="." index="4" instance=ExtResource( 2 )]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -91.3336, 2.0316, 4.06596 ) transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -91.3336, 2.0316, 4.06596 )
_sections_unfolded = [ "Transform" ]
[node name="Debug" type="Label" parent="." index="5"] [node name="Debug" type="Label" parent="." index="5"]
@ -174,12 +168,10 @@ custom_fonts/font = SubResource( 5 )
percent_visible = 1.0 percent_visible = 1.0
lines_skipped = 0 lines_skipped = 0
max_lines_visible = -1 max_lines_visible = -1
_sections_unfolded = [ "Anchor", "Focus", "Grow Direction", "Hint", "Margin", "Material", "Mouse", "Pause", "Rect", "Size Flags", "Theme", "Visibility", "custom_colors", "custom_constants", "custom_fonts", "custom_styles" ]
[node name="LeftSpawn" type="Spatial" parent="." index="6"] [node name="LeftSpawn" type="Spatial" parent="." index="6"]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.96426, 9.36109 ) transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.96426, 9.36109 )
_sections_unfolded = [ "Transform" ]
[node name="RightSpawn" type="Spatial" parent="." index="7"] [node name="RightSpawn" type="Spatial" parent="." index="7"]


+ 1
- 3
scenes/update.tscn View File

@ -9,9 +9,8 @@ size = 50
use_mipmaps = false use_mipmaps = false
use_filter = false use_filter = false
font_data = ExtResource( 2 ) font_data = ExtResource( 2 )
_sections_unfolded = [ "Extra Spacing", "Font", "Resource", "Settings" ]
[node name="Control" type="Control" index="0"]
[node name="Control" type="Control"]
anchor_left = 0.0 anchor_left = 0.0
anchor_top = 0.0 anchor_top = 0.0
@ -98,6 +97,5 @@ align = 1
percent_visible = 1.0 percent_visible = 1.0
lines_skipped = 0 lines_skipped = 0
max_lines_visible = -1 max_lines_visible = -1
_sections_unfolded = [ "custom_colors", "custom_fonts" ]

+ 51
- 0
scripts/ability_icon.gd View File

@ -0,0 +1,51 @@
extends Control
onready var hero = get_node("../..")
onready var bar = get_node("Bar")
onready var available = get_node("Available")
export var cost = 1
export var ability_name = "Ability"
export var display_progress = true
export var action = ""
# This is intended to be public
var disabled = false
func _ready():
get_node("Name").text = ability_name
var description
if action:
var primary = InputMap.get_action_list(action)[0]
if primary is InputEventMouseButton:
if primary.button_index == BUTTON_LEFT:
description = "Click"
elif primary.button_index == BUTTON_RIGHT:
description = "Right Click"
else:
description = "Scroll Click"
else:
description = primary.as_text()
else:
description = ""
get_node("Button").text = description
func is_pressed():
return Input.is_action_pressed(action)
func _process(delta):
if action and Input.is_action_pressed(action):
available.rect_position = Vector2(-25, -25) # Centered / not offset
else:
available.rect_position = Vector2(-30, -30)
if disabled:
available.hide()
bar.value = 0
else:
if display_progress:
if cost == 0:
bar.value = 100 if hero.charge > 0 else 0
else:
bar.value = 100 * hero.charge / cost
if hero.charge > cost:
available.show()
else:
available.hide()

+ 3
- 3
scripts/ai.gd View File

@ -24,8 +24,8 @@ func _physics_process(delta):
func set_spawn(): func set_spawn():
get_node("..").set_translation(str2var(recording.spawn)) get_node("..").set_translation(str2var(recording.spawn))
print(recording.switch_charge)
get_node("..").switch_charge = str2var(recording.switch_charge)
print(recording.charge)
get_node("..").charge = str2var(recording.charge)
func read_recording(): func read_recording():
@ -80,7 +80,7 @@ func play_keys():
# events[0][0] is first event's TIME # events[0][0] is first event's TIME
if recording.events.size() == 0: if recording.events.size() == 0:
get_node("..").spawn() # This may cause spawn twice, I hope this isn't a problem get_node("..").spawn() # This may cause spawn twice, I hope this isn't a problem
# get_node("..").switch_charge = 0 # This needs to reset so the recording is accurate
# get_node("..").charge = 0 # This needs to reset so the recording is accurate
read_recording() read_recording()
while float(recording.events[0][0]) <= time: while float(recording.events[0][0]) <= time:
# events[0][1] is first event's EVENT # events[0][1] is first event's EVENT


+ 14
- 0
scripts/custom_game.gd View File

@ -0,0 +1,14 @@
extends Control
func _ready():
get_node("Server").connect("pressed", self, "_start_server")
get_node("Client").connect("pressed", self, "_start_client")
get_node("Back").connect("pressed", get_tree(), "change_scene", ["res://scenes/menu.tscn"])
func _start_server():
# Custom Game can assume we're playing as well
networking.start_server()
func _start_client():
var ip = get_node("IP").text
networking.start_client(ip)

+ 14
- 3
scripts/hero_select.gd View File

@ -10,15 +10,26 @@ const hero_names = [
] ]
const hero_text = [ const hero_text = [
"DILIGENCE.\n\nWallride by jumping on walls.\n\nYour speed builds immensely as your Switch Charge increases.",
"DILIGENCE.\n\nWallride by jumping on walls.\n\nHold left click to go faster (but spend charge).",
"WRATH.\n\nPress E and click (or just click) to build a wall.\n\nRight click to destroy one.", "WRATH.\n\nPress E and click (or just click) to build a wall.\n\nRight click to destroy one.",
"LUST.\n\nYou attract nearby heroes.\n\nPress E to switch to repelling them.", "LUST.\n\nYou attract nearby heroes.\n\nPress E to switch to repelling them.",
"GENEROSITY.\n\nMake contact with a friend to boost their speed.\n\nPress E to separate.", "GENEROSITY.\n\nMake contact with a friend to boost their speed.\n\nPress E to separate.",
"PATIENCE.\n\nHold left mouse button on an enemy to slow them down.",
"PRIDE.\n\nClick to build portal. Click again to build its partner.\n\nYou can build multiple portal sets.",
"PATIENCE.\n\nHold left mouse button on an enemy to slow them down.\n\nPress E to delete someone else's building (costs charge).",
"PRIDE.\n\nDrag on enemies to bully them around.\n\nClick to build a portal. Click again to build its partner (costs charge).",
] ]
func _ready(): func _ready():
for hero_index in range(hero_names.size()): for hero_index in range(hero_names.size()):
add_item(hero_names[hero_index], hero_index) add_item(hero_names[hero_index], hero_index)
connect("item_selected", self, "set_hero")
func set_hero(hero):
select(hero)
networking.set_info_from_server("hero", hero)
func random_hero():
var hero = randi() % hero_names.size()
set_hero(hero)
return hero

+ 13
- 2
scripts/heroes/0.gd View File

@ -12,15 +12,26 @@ var wallride_forgiveness = .3
func _ready(): func _ready():
._ready() ._ready()
walk_speed *= 0.8 walk_speed *= 0.8
air_accel *= 2
air_accel *= 1.5
jump_speed *= 1 jump_speed *= 1
air_speed_build *= 2 air_speed_build *= 2
# Since movement is the only ability of this hero, it builds charge more # Since movement is the only ability of this hero, it builds charge more
movement_charge *= 2 movement_charge *= 2
func control_player(state): func control_player(state):
var original_speed = walk_speed
var original_accel = air_accel
var boost_strength = 2
var boost_drain = 25 # Recall increased charge must be factored in
var cost = boost_drain * state.step
if get_node("MasterOnly/Boost").is_pressed() and charge > cost:
walk_speed *= 2
air_accel *= 3
build_charge(-cost)
.control_player(state) .control_player(state)
wallride(state) wallride(state)
walk_speed = original_speed
air_accel = original_accel
func wallride(state): func wallride(state):
@ -49,7 +60,7 @@ func wallride(state):
apply_impulse(Vector3(), air_accel * aim[2] * get_mass()) apply_impulse(Vector3(), air_accel * aim[2] * get_mass())
# Allow jumping (for wall hopping!) # Allow jumping (for wall hopping!)
if Input.is_action_just_pressed("jump"): if Input.is_action_just_pressed("jump"):
var build_factor = 1 + switch_charge * wallride_leap_build
var build_factor = 1 + charge * wallride_leap_build
var jump_impulse = build_factor * wallride_leap_side * last_wall_normal var jump_impulse = build_factor * wallride_leap_side * last_wall_normal
jump_impulse.y += build_factor * wallride_leap_height jump_impulse.y += build_factor * wallride_leap_height
set_gravity_scale(1) # Jumping requires gravity set_gravity_scale(1) # Jumping requires gravity


+ 20
- 1
scripts/heroes/1.gd View File

@ -1,6 +1,9 @@
extends "res://scripts/player.gd" extends "res://scripts/player.gd"
onready var placement = preload("res://scripts/placement.gd").new(self, "res://scenes/heroes/1_wall.tscn") onready var placement = preload("res://scripts/placement.gd").new(self, "res://scenes/heroes/1_wall.tscn")
onready var place_wall_ability = get_node("MasterOnly/PlaceWall")
export var looked_at_charge_suck = 25 # charge / sec
# --- Godot overrides --- # --- Godot overrides ---
@ -12,7 +15,10 @@ func _ready():
func _process(delta): func _process(delta):
if is_network_master(): if is_network_master():
placement.place_input()
var can_build = charge > place_wall_ability.cost
if can_build:
if placement.place_input():
build_charge(-place_wall_ability.cost)
func _exit_tree(): func _exit_tree():
._exit_tree() ._exit_tree()
@ -28,3 +34,16 @@ func spawn():
# --- Own --- # --- Own ---
# Passive: suck the charge out of people who look at us!
# This is a special method called by player when any object is looked at
func on_looked_at(who, delta):
# Why do we check this if we can't look at ourselves? Walls call this method from their looked_at
# Also, why not use util.is_friendly? Because we're not master, we're slave (looker is master)
if who.player_info.is_right_team != player_info.is_right_team:
var subtracted = who.build_charge(-looked_at_charge_suck * delta)
build_charge(-subtracted)
# We rset our charge because otherwise it won't be acknowledged
# because we're not master
# The *PICKER* is master, we're slave! Well, let's flip that for a mo'
rset("charge", charge)

+ 4
- 1
scripts/heroes/1_wall.gd View File

@ -5,7 +5,7 @@ var being_touched = 0
func _process(delta): func _process(delta):
if being_touched > 0: if being_touched > 0:
maker_node.switch_charge += touch_charge * delta
maker_node.build_charge(touch_charge * delta)
func init(maker): func init(maker):
@ -34,3 +34,6 @@ func count_bodies(with, player, delta):
if player != maker_node: if player != maker_node:
being_touched += delta being_touched += delta
func on_looked_at(who, delta):
maker_node.on_looked_at(who, delta)

+ 1
- 1
scripts/heroes/2.gd View File

@ -15,7 +15,7 @@ func _process(delta):
get_node("MasterOnly/Crosshair").set_text("\\/") get_node("MasterOnly/Crosshair").set_text("\\/")
var overlapping = get_node("Area").get_overlapping_bodies().size() var overlapping = get_node("Area").get_overlapping_bodies().size()
switch_charge += delta * overlap_charge * overlapping
build_charge(delta * overlap_charge * overlapping)
sync func switch_gravity(): sync func switch_gravity():
var area = get_node("Area") var area = get_node("Area")


+ 8
- 5
scripts/heroes/3.gd View File

@ -37,9 +37,12 @@ func _process(delta):
rpc("unmerge") rpc("unmerge")
if merged: if merged:
# Subtract and then add, so we can continously add this # Subtract and then add, so we can continously add this
switch_charge -= boost_charge
boost_charge = merged.switch_charge - original_charge
switch_charge += boost_charge
# We don't use build_charge because this is delicate math
charge -= boost_charge
boost_charge = merged.charge - original_charge
charge += boost_charge
# Network the changes
build_charge(0)
func control_player(state): func control_player(state):
if !merged: if !merged:
@ -85,12 +88,12 @@ func set_boosted(node, is_boosted):
node.walk_speed *= ratio node.walk_speed *= ratio
node.air_accel *= ratio node.air_accel *= ratio
if is_boosted: if is_boosted:
original_charge = node.switch_charge
original_charge = node.charge
boost_charge = 0 boost_charge = 0
sync func merge(node_name): sync func merge(node_name):
set_boosting(true) set_boosting(true)
var other = $"/root/Level/Players".get_node(node_name)
var other = util.get_player(node_name)
set_boosted(other, true) set_boosted(other, true)
merged = other merged = other


+ 16
- 3
scripts/heroes/4.gd View File

@ -2,6 +2,8 @@
extends "res://scripts/player.gd" extends "res://scripts/player.gd"
onready var destroy_ability = get_node("MasterOnly/Destroy")
var stun_charge = 1 var stun_charge = 1
var velocity_charge = 10 # This one is instantaneous, so it gets quita weight var velocity_charge = 10 # This one is instantaneous, so it gets quita weight
@ -28,13 +30,24 @@ func _process(delta):
get_node("TPCamera").cam_view_sensitivity *= sens_factor get_node("TPCamera").cam_view_sensitivity *= sens_factor
get_node("TPCamera").cam_smooth_movement = true get_node("TPCamera").cam_smooth_movement = true
var looking_at = pick()
if looking_at and looking_at.has_method("destroy"):
destroy_ability.cost = looking_at.destroy_cost
destroy_ability.disabled = false
if Input.is_action_just_pressed("primary_ability"):
if charge > looking_at.destroy_cost:
build_charge(-looking_at.destroy_cost)
looking_at.rpc("destroy")
else:
destroy_ability.disabled = true
if stun: if stun:
var players = get_node("/root/Level/Players").get_children() var players = get_node("/root/Level/Players").get_children()
var player = pick_from(players) var player = pick_from(players)
if player != -1: if player != -1:
# We get charge for just stunning, plus charge for how much linear velocity we cut out # We get charge for just stunning, plus charge for how much linear velocity we cut out
switch_charge += stun_charge * delta
switch_charge += velocity_charge * players[player].get_linear_velocity().length() * delta
build_charge(stun_charge * delta)
build_charge(velocity_charge * players[player].linear_velocity.length() * delta)
rpc("stun", players[player].get_name(), get_node("TPCamera/Camera/Ray").get_collision_point()) rpc("stun", players[player].get_name(), get_node("TPCamera/Camera/Ray").get_collision_point())
is_stunning = true is_stunning = true
@ -47,7 +60,7 @@ func _process(delta):
sync func stun(net_id, position): sync func stun(net_id, position):
# Stun the thing! # Stun the thing!
var player = get_node("/root/Level/Players/%s" % net_id)
var player = util.get_player(net_id)
player.set_linear_velocity(Vector3()) player.set_linear_velocity(Vector3())
# Show the beam! # Show the beam!


+ 43
- 2
scripts/heroes/5.gd View File

@ -1,11 +1,18 @@
extends "res://scripts/player.gd" extends "res://scripts/player.gd"
onready var placement = preload("res://scripts/placement.gd").new(self, "res://scenes/heroes/5_portal.tscn") onready var placement = preload("res://scripts/placement.gd").new(self, "res://scenes/heroes/5_portal.tscn")
onready var portal_ability = get_node("MasterOnly/Portal")
onready var teleport_ability = get_node("MasterOnly/Teleport")
var radius = 15 var radius = 15
# The spaces make the bracket centered, rather than on of the dots # The spaces make the bracket centered, rather than on of the dots
var first_crosshair = " [..." var first_crosshair = " [..."
var second_crosshair = "...] " var second_crosshair = "...] "
var no_portal_crosshair = "+"
var flicking = null
var flick_charge = 3
var flick_strength = 4
# --- Godot overrides --- # --- Godot overrides ---
@ -14,13 +21,22 @@ func _ready():
placement.confirm_action = "hero_5_confirm_portal" placement.confirm_action = "hero_5_confirm_portal"
placement.delete_action = "hero_5_remove_portal" placement.delete_action = "hero_5_remove_portal"
placement.max_placed = 100 placement.max_placed = 100
set_process_input(true)
func _process(delta): func _process(delta):
if is_network_master(): if is_network_master():
placement.place_input(radius)
var is_second = placement.placed.size() % 2 != 0 var is_second = placement.placed.size() % 2 != 0
var crosshair = second_crosshair if is_second else first_crosshair
var portal_crosshair = second_crosshair if is_second else first_crosshair
var crosshair = no_portal_crosshair if charge < portal_ability.cost else portal_crosshair
get_node("MasterOnly/Crosshair").set_text(crosshair) get_node("MasterOnly/Crosshair").set_text(crosshair)
var can_build = charge > portal_ability.cost
if placement.place_input(radius, can_build, true) and is_second:
build_charge(-portal_ability.cost)
teleport_ability.disabled = placement.placed.size() <= 1
func _input(event):
flick_input()
func _exit_tree(): func _exit_tree():
._exit_tree() ._exit_tree()
@ -31,3 +47,28 @@ func _exit_tree():
# --- Own --- # --- Own ---
func flick_input():
if Input.is_action_just_pressed("primary_mouse"):
var pick = pick_by_friendly(false)
if pick:
flicking = pick
if flicking and Input.is_action_just_released("primary_mouse"):
var aim = get_node("Yaw/Pitch").get_global_transform().basis
var forwards = -aim[2]
var distance = (flicking.translation - translation).length()
forwards *= distance
var towards = translation + forwards
var gravity = PhysicsServer.area_get_param(get_world().get_space(), PhysicsServer.AREA_PARAM_GRAVITY_VECTOR)
# Automatically account for gravity, so as to make UI more intuitive
towards -= gravity
rpc("flick", flicking.get_name(), towards)
flicking = null
build_charge(flick_charge)
sync func flick(player_id, towards):
var who = util.get_player(player_id)
if who.is_network_master():
var direction = towards - who.translation
var impulse = direction.normalized() * flick_strength * who.get_mass()
who.apply_impulse(Vector3(), impulse)

+ 12
- 11
scripts/heroes/5_portal.gd View File

@ -1,6 +1,6 @@
extends "res://scripts/placeable.gd" extends "res://scripts/placeable.gd"
var portal_charge = 15
var portal_charge = -5
var other var other
var index var index
@ -26,8 +26,8 @@ func _exit_tree():
func init(maker): func init(maker):
var maker_portals = maker.placement.placed
index = maker_portals.size() # No -1, because we haven't actually been added to the array yet
index = maker.placement.placed.size()
# If index is odd, we're the second (1, 3...), if even, first (0, 4...) # If index is odd, we're the second (1, 3...), if even, first (0, 4...)
var second = index % 2 != 0 var second = index % 2 != 0
var is_friend = util.is_friendly(maker) var is_friend = util.is_friendly(maker)
@ -57,12 +57,13 @@ func player_collided(with, player):
func portal(player): func portal(player):
if player.player_info.is_right_team == maker_node.player_info.is_right_team: if player.player_info.is_right_team == maker_node.player_info.is_right_team:
if other: if other:
var spawn_distance = 1.75
# Find a sane place to spawn
# -Z is in the direction of the portal
# X is enough away from the portal to avoid infinite loop
# With both axes, gravity could never bring us to hit the portal
var to = other.to_global(Vector3(spawn_distance,0,-spawn_distance))
player.set_translation(to)
maker_node.switch_charge += portal_charge
if maker_node.charge > -portal_charge:
var spawn_distance = 1.75
# Find a sane place to spawn
# -Z is in the direction of the portal
# X is enough away from the portal to avoid infinite loop
# With both axes, gravity could never bring us to hit the portal
var to = other.to_global(Vector3(spawn_distance,0,-spawn_distance))
player.set_translation(to)
maker_node.build_charge(portal_charge)

+ 97
- 257
scripts/lobby.gd View File

@ -1,274 +1,114 @@
extends "res://scripts/args.gd"
extends Control
# class member variables go here, for example:
# var a = 2
# var b = "textvar"
var SERVER_PORT = 54672
var MAX_PLAYERS = 10
var player_info = {}
var my_info = {}
var begun = false
var server_playing = true
var global_server_ip = "nv.cosinegaming.com"
var players_done = []
func setup_options():
var opts = Options.new()
opts.set_banner(('A non-violent MOBA inspired by Overwatch and Zineth'))
opts.add('-singleplayer', false, 'Whether to run singeplayer, starting immediately')
opts.add('-server', false, 'Whether to run as server')
opts.add('-client', false, 'Immediately connect as client')
opts.add('-silent', false, 'If the server is not playing, merely serving')
opts.add('-hero', 'r', 'Your choice of hero (index)')
opts.add('-level', 'r', 'Your choice of level (index) - server only!')
opts.add('-start-game', false, 'Join as a client and immediately start the game')
opts.add('-ai', true, 'Run this client as AI')
opts.add('-no-record', true, "Don't record this play for AI later")
opts.add('-h', false, "Print help")
return opts
func option_sel(button_name, option):
var button = get_node(button_name)
if option == "r":
option = randi() % button.get_item_count()
else:
option = int(option)
button.select(option)
onready var hero_select = get_node("HeroSelect/Hero")
onready var level_select = get_node("LevelSelect")
onready var start_game_button = get_node("StartGame")
onready var ready_button = get_node("Ready")
func _ready(): func _ready():
randomize()
get_node("GameBrowser/Play").connect("pressed", self, "connect_global_server")
get_node("PlayerSettings/HeroSelect").connect("item_selected", self, "select_hero")
get_node("PlayerSettings/Username").connect("text_changed", self, "resend_name")
get_node("JoinedGameLobby/StartGame").connect("pressed", self, "start_game")
get_node("CustomGame/Server").connect("pressed", self, "_server_init")
get_node("CustomGame/Client").connect("pressed", self, "_client_init")
get_node("CustomGame/Singleplayer").connect("pressed", self, "_singleplayer_init")
get_node("CustomGame/LevelSelect").connect("item_selected", self, "select_level")
var o = setup_options()
o.parse()
if o.get_value("-silent"):
server_playing = false # TODO: Uncaps :(
if o.get_value("-hero"):
var hero = o.get_value("-hero")
option_sel("PlayerSettings/HeroSelect", hero)
# For some reason, calling option_sel doesn't trigger the actual selection
select_hero(get_node("PlayerSettings/HeroSelect").get_selected_id())
if o.get_value("-level"):
option_sel("CustomGame/LevelSelect", o.get_value("-level"))
if o.get_value("-server"):
call_deferred("_server_init")
if o.get_value("-client"):
call_deferred("_client_init")
if o.get_value("-start-game"):
my_info.start_game = true
call_deferred("_client_init")
if o.get_value("-singleplayer"):
call_deferred("_singleplayer_init")
if o.get_value("-ai"):
my_info.is_ai = true
if not o.get_value("-no-record") and not o.get_value("-ai"):
my_info.record = true
if o.get_value('-h'):
o.print_help()
quit()
get_tree().connect("network_peer_connected", self, "_player_connected")
get_tree().connect("network_peer_disconnected", self, "_player_disconnected")
get_tree().connect("connected_to_server", self, "_connected_ok")
func connect_global_server():
_client_init(global_server_ip)
func _client_init(ip=null):
collect_info()
var peer = NetworkedMultiplayerENet.new()
if not ip:
ip = get_node("CustomGame/IP").get_text()
ip = IP.resolve_hostname(ip)
peer.create_client(ip, SERVER_PORT)
get_tree().set_network_peer(peer)
get_node("CustomGame/Client").set_text("Clienting!")
func _singleplayer_init():
collect_info()
var peer = NetworkedMultiplayerENet.new()
peer.create_server(SERVER_PORT, 1)
get_tree().set_network_peer(peer)
player_info[1] = my_info
start_game()
func _server_init():
collect_info()
var peer = NetworkedMultiplayerENet.new()
peer.create_server(SERVER_PORT, MAX_PLAYERS)
get_tree().set_network_peer(peer)
get_node("CustomGame/Server").set_text("Serving!")
get_node("JoinedGameLobby").show()
if server_playing:
player_info[1] = my_info
# Connect (to networking)
get_node("Username").connect("text_changed", self, "_send_name")
get_node("Spectating").connect("toggled", self, "_set_info_callback", ["spectating"])
ready_button.connect("toggled", self, "_set_info_callback", ["ready"])
start_game_button.connect("pressed", networking, "start_game")
# Connect (from networking)
networking.connect("info_updated", self, "_render_player_list")
get_tree().connect("connected_to_server", self, "_connected")
# Connect (static)
get_node("Back").connect("pressed", self, "_exit_to_menu")
var spectating = util.args.get_value("-silent")
get_node("Spectating").pressed = spectating
# Shown, maybe, in _check_begun
start_game_button.hide()
if get_tree().is_network_server():
start_game_button.show()
func _player_connected(id):
pass
if get_tree().is_network_server():
# We put level in our players dict because it's automatically broadcast to other players
var level = util.args.get_value("-level")
if level == "r":
level = randi() % level_select.get_item_count()
level = int(level)
_set_level(level)
level_select.show()
level_select.select(level)
level_select.connect("item_selected", self, "_set_level")
else:
level_select.hide()
func _player_disconnected(id):
if get_tree().is_network_server(): if get_tree().is_network_server():
rpc("unregister_player", id)
call_deferred("render_player_list")
_connected()
func _connected_ok():
rpc("register_player", get_tree().get_network_unique_id(), my_info)
if "start_game" in my_info and my_info.start_game:
rpc_id(1, "start_game")
get_node("JoinedGameLobby").show()
func _connected():
func collect_info():
if not "username" in my_info:
my_info.username = get_node("PlayerSettings/Username").get_text()
if not "hero" in my_info:
my_info.hero = get_node("PlayerSettings/HeroSelect").get_selected_id()
if not "is_right_team" in my_info:
my_info.is_right_team = false # Server assigns team, wait for that
my_info.version = util.version
_send_name()
networking.set_info_from_server("ready", false)
networking.set_info_from_server("spectating", util.args.get_value("-silent"))
networking.set_info_from_server("begun", false)
if util.args.get_value("-hero") == "r":
hero_select.random_hero()
else:
hero_select.set_hero(int(util.args.get_value("-hero")))
remote func register_player(new_peer, info):
var p_version = info.version.split(".")
var version_split = util.version.split(".")
if p_version[0] != version_split[0]:
# TODO: Fail gracefully
return
player_info[new_peer] = info
render_player_list()
if (get_tree().is_network_server()):
var right_team_count = 0
# Send current players' info to new player
for old_peer in player_info:
# Send new player, old player's info
rpc_id(new_peer, "register_player", old_peer, player_info[old_peer])
if old_peer != new_peer:
# We need to assign team later, so count current
if player_info[old_peer].is_right_team:
right_team_count += 1
# You'd think this part could be met with a simple `rpc(`, but actually it can't
# My best guess is this is because we haven't registered the names yet, but I'm not sure (TODO)
if old_peer != 1:
# Send old player, new player's info (not us, no infinite loop)
rpc_id(old_peer, "register_player", new_peer, info)
if begun:
rpc_id(old_peer, "spawn_player", new_peer)
rpc_id(old_peer, "begin_player_deferred", new_peer) # Spawning is deferred
if not server_playing:
# We didn't catch this in player_info
rpc_id(1, "spawn_player", new_peer)
rpc_id(1, "begin_player_deferred", new_peer) # Spawning is deferred
var assign_right_team = right_team_count * 2 < player_info.size()
rpc("assign_team", new_peer, assign_right_team)
if not begun and player_info.size() == MAX_PLAYERS:
start_game()
if begun:
rpc_id(new_peer, "pre_configure_game", my_info.level)
rpc_id(new_peer, "post_configure_game")
if util.args.get_value("-start-game"):
networking.start_game()
sync func unregister_player(peer):
player_info.erase(peer)
get_node("/root/Level/Players/%d" % peer).queue_free()
func _set_level(level):
networking.level = level
func select_hero(hero):
var description = get_node("PlayerSettings/HeroSelect").hero_text[hero]
get_node("PlayerSettings/HeroDescription").set_text(description)
rpc("set_hero", get_tree().get_network_unique_id(), hero)
# Because of the annoying way callbacks work (automatic parameter, optional parameter)
# We need a utility function for making these kinds of callbacks for set_info
func _set_info_callback(value, key):
networking.set_info_from_server(key, value)
sync func set_hero(peer, hero): sync func set_hero(peer, hero):
player_info[peer].hero = hero
render_player_list()
func resend_name():
var name = get_node("PlayerSettings/Username").get_text()
rpc("set_name", get_tree().get_network_unique_id(), name)
sync func set_name(peer, name):
player_info[peer].username = name
render_player_list()
sync func assign_team(peer, is_right_team):
player_info[peer].is_right_team = is_right_team
if peer == get_tree().get_network_unique_id():
if is_right_team:
get_node("PlayerSettings/Team").set_text("Right Team")
else:
get_node("PlayerSettings/Team").set_text("Left Team")
render_player_list()
func render_player_list():
if has_node("PlayerSettings"):
var list = ""
var hero_names = get_node("PlayerSettings/HeroSelect").hero_names
for p in player_info:
list += "%-15s" % player_info[p].username
list += "%-20s" % hero_names[player_info[p].hero]
if player_info[p].is_right_team:
list += "Right Team"
else:
list += "Left Team"
networking.players[peer].hero = hero
_render_player_list()
func _send_name():
var name = get_node("Username").text
networking.set_info_from_server("username", name)
func _check_begun():
if networking.players.has(1) and networking.players[1].has("begun"):
var game_started = networking.players[1].begun
if game_started:
start_game_button.show()
start_game_button.text = "Join game"
# The "Ready" toggle doesn't really make sense on a started game
ready_button.hide()
func _render_player_list():
_check_begun()
var list = ""
var hero_names = hero_select.hero_names
for p in networking.players:
var player = networking.players[p]
# A spectating server is just a dedicated server, ignore it
if p and player.has("spectating") and not (player.spectating and p == 1):
var username = player.username if player.has("username") else "Loading..."
list += "%-15s " % username
var hero = hero_names[player.hero] if player.has("hero") else "Loading..."
list += "%-10s " % hero
var team = "Loading..."
if player.has("is_right_team"):
if player.is_right_team:
team = "Right Team"
else:
team = "Left Team"
list += "%-11s" % team
var ready_text = "Ready" if player.has("ready") and player.ready else ""
list += "%-6s" % ready_text
if player.has("spectating") and player.spectating:
list += "Spectating"
list += "\n" list += "\n"
get_node("JoinedGameLobby/PlayerList").set_text(list)
sync func start_game():
my_info.level = get_node("CustomGame/LevelSelect").get_selected_id()
rpc("pre_configure_game", my_info.level)
sync func done_preconfiguring(who):
players_done.append(who)
if players_done.size() == player_info.size():
# We call deferred in case singleplayer has placing the player in queue still
call_deferred("rpc", "post_configure_game")
sync func spawn_player(p):
var hero = player_info[p].hero
var player = load("res://scenes/heroes/" + str(hero) + ".tscn").instance()
player.set_name(str(p))
player.set_network_master(p)
player.player_info = player_info[p]
get_node("/root/Level/Players").call_deferred("add_child", player)
sync func pre_configure_game(level):
begun = true
my_info.level = level # Remember the level for future player registration
var self_peer_id = get_tree().get_network_unique_id()
# Remove the interface so as to not fuck with things
# But we still need the lobby alive to deal with networking!
for element in get_node("/root/Lobby").get_children():
element.queue_free()
var world = load("res://scenes/levels/%d.tscn" % level).instance()
get_node("/root").add_child(world)
# Load all players (including self)
for p in player_info:
player_info[p].level = level
spawn_player(p)
rpc_id(1, "done_preconfiguring", self_peer_id)
func begin_player(peer):
get_node("/root/Level/Players/%d" % peer).begin()
remote func begin_player_deferred(peer):
call_deferred("begin_player", peer)
sync func reset_state():
players_done = []
get_node("/root/Level").queue_free()
get_node("PlayerList").set_text(list)
sync func post_configure_game():
# Begin all players (including self)
for p in player_info:
begin_player_deferred(p)
func _exit_to_menu():
get_tree().network_peer.close_connection()
get_tree().change_scene("res://scenes/menu.tscn")

+ 105
- 0
scripts/matchmaking.gd View File

@ -0,0 +1,105 @@
extends Node
var SERVER_TO_SERVER_PORT = 54671
var MATCHMAKING_PORT = 54672
var GAME_SIZE = 6
# Number of games we can make without blowing up the computer
var MAX_GAMES = 50 # Based on how many ports I decided to forward
var next_port = 54673
# Filled with queue info which contains
# { "netid" }
var skirmishing_players = []
var skirmish
# To avoid the confusion of the gameSERVERS being CLIENTS,
# we just call them games whenever possible
# var games = []
var game_connections = []
var game_streams = []
# Matchmaker to game servers
var matchmaker_to_games
enum messages {
ready_to_connect,
}
onready var lobby = get_node("..")
func _ready():
# By default, having this node doesn't do naything
# You must call start_matchmaker to enable it
# If not called, don't call _process (= don't matchmake)
set_process(false)
func start_matchmaker():
# Actually run the matchmaker
set_process(true)
# Setup skirmish server
skirmish = spawn_server(true)
# Set up communication between GAMESERVERS
# This is necessary for eg, when a player leaves to backfill
matchmaker_to_games = TCP_Server.new()
if matchmaker_to_games.listen(SERVER_TO_SERVER_PORT):
print("Error, could not listen")
# Use ENet for matchmaker because we can (makes client code cleaner)
var matchmaker_to_players = NetworkedMultiplayerENet.new()
print("Starting matchmaker on port " + str(MATCHMAKING_PORT))
matchmaker_to_players.create_server(MATCHMAKING_PORT, MAX_GAMES)
get_tree().set_network_peer(matchmaker_to_players)
matchmaker_to_players.connect("peer_connected", self, "queue")
func _process(delta):
# Manage connection to GAMESERVERS (not clients)
if matchmaker_to_games.is_connection_available(): # check if a gameserver's trying to connect
var game = matchmaker_to_games.take_connection() # accept connection
game_connections.append(game) # store the connection
var stream = PacketPeerStream.new()
stream.set_stream_peer(game) # bind peerstream to new client
game_streams.append(stream) # make new data transfer object for game
for stream in game_streams:
if stream.get_available_packet_count():
var message = stream.get_var()
if message == messages.ready_to_connect:
var port = stream.get_var()
print("Server " + str(port) + " has requested connection")
skirmish_to_game(port, GAME_SIZE)
func queue(netid):
print("Player " + str(netid) + " connected.")
add_to_game(netid, skirmish)
skirmishing_players.append(netid)
check_queue()
func add_to_game(netid, port):
networking.rpc_id(netid, "reconnect", networking.global_server_ip, port)
func skirmish_to_game(port, count=1):
for i in range(count):
if not skirmishing_players.size():
return false
print(skirmishing_players[0])
print("to")
print(port)
add_to_game(skirmishing_players[0], port)
return true
func check_queue():
# Prefer making a full game to backfilling
if skirmishing_players.size() >= GAME_SIZE:
spawn_server()
# games.append(port)
func spawn_server(skirmish=false):
var args = ['-port='+str(next_port)]
if skirmish:
# Begin skirmish immediately, so players "join" instead of "ready"
args.append("-start-game")
OS.execute("util/server.sh", args, false)
next_port += 1
return (next_port - 1) # Return original port

+ 56
- 0
scripts/menu.gd View File

@ -0,0 +1,56 @@
extends Control
func _ready():
randomize()
_gui_setup()
_arg_actions()
# GUI
func _gui_setup():
get_node("Center/Play").connect("pressed", self, "_find_game")
get_node("Center/CustomGame").connect("pressed", self, "_custom_game")
get_node("Center/Singleplayer").connect("pressed", self, "_singleplayer")
get_node("Center/Quit").connect("pressed", get_tree(), "quit")
func _find_game():
var ip = networking.global_server_ip
# var ip = util.args.get_value("-ip")
var port = networking.matchmaking.MATCHMAKING_PORT
networking.start_client(ip, port)
func _custom_game():
get_tree().change_scene("res://scenes/custom_game.tscn")
func _singleplayer():
networking.start_server()
get_tree().change_scene("res://scenes/singleplayer_lobby.tscn")
# Command line
func _option_sel(button_name, option):
var button = get_node(button_name)
if option == "r":
option = randi() % button.get_item_count()
else:
option = int(option)
button.select(option)
func _arg_actions():
var o = util.args
# if o.get_value("-ai"):
# my_info.is_ai = true
# if not o.get_value("-no-record") and not o.get_value("-ai"):
# my_info.record = true
if o.get_value("-server"):
networking.start_server()
if o.get_value("-matchmaker"):
networking.matchmaking.start_matchmaker()
if o.get_value("-client"):
networking.start_client()
if o.get_value("-singleplayer"):
_singleplayer()
if o.get_value('-h'):
o.print_help()
get_tree().quit()

+ 202
- 0
scripts/networking.gd View File

@ -0,0 +1,202 @@
extends Node
# Public variables
# ================
onready var matchmaking = preload("res://scripts/matchmaking.gd").new()
remote var players = {}
var global_server_ip = "nv.cosinegaming.com"
var matchmaker_tcp
var level
signal info_updated
# Public methods
# ==============
func start_client(ip="", port=0):
if not ip:
ip = util.args.get_value("-ip")
ip = IP.resolve_hostname(ip)
if not port:
port = util.args.get_value("-port")
var peer = NetworkedMultiplayerENet.new()
print("Connecting to " + ip + ":" + str(port))
peer.create_client(ip, port)
get_tree().set_network_peer(peer)
get_tree().change_scene("res://scenes/lobby.tscn")
remote func reconnect(ip, port):
# Reset previously known players
players = {}
start_client(ip, port)
func start_server(port=0):
if not port:
port = util.args.get_value("-port")
var peer = NetworkedMultiplayerENet.new()
print("Starting server on port " + str(port))
peer.create_server(port, matchmaking.GAME_SIZE)
get_tree().set_network_peer(peer)
# As soon as we're listening, let the matchmaker know
_connect_to_matchmaker(port)
_register_player(get_tree().get_network_unique_id())
if util.args.get_value("-silent"):
set_info("spectating", true)
get_tree().change_scene("res://scenes/lobby.tscn")
master func set_info(key, value, peer=0):
if not peer:
peer = get_tree().get_network_unique_id()
rpc("_set_info", str(key), value, peer)
# When connectivity is not yet guaranteed, the only one we know is always
# connected to everyone is the server. So in initial handshakes, it's better to
# tell the server what to tell everyone to do
func set_info_from_server(key, value, peer=0):
if not peer:
peer = get_tree().get_network_unique_id()
rpc_id(1, "set_info", key, value, peer)
func start_game():
rpc_id(1, "_start_game")
sync func reset_state():
for p in players:
players[p].begun = false
# TODO: Do I in fact want to unready everyone automatically?
players[p].ready = false
get_node("/root/Level").queue_free()
# Private methods
# ===============
func _ready():
add_child(matchmaking)
get_tree().connect("network_peer_disconnected", self, "_unregister_player")
get_tree().connect("network_peer_connected", self, "_register_player")
get_tree().connect("connected_to_server", self, "_on_connect")
connect("info_updated", self, "_check_info")
remote func _register_player(new_peer):
if get_tree().is_network_server():
# I tell new player about all the existing people
_send_all_info(new_peer)
set_info("is_right_team", _right_team_next(), new_peer)
sync func _unregister_player(peer):
players.erase(peer)
var p = util.get_player(peer)
if p:
p.queue_free()
emit_signal("info_updated")
func _connect_to_matchmaker(game_port):
var matchmaker_peer = StreamPeerTCP.new()
matchmaker_peer.connect_to_host("127.0.0.1", matchmaking.SERVER_TO_SERVER_PORT)
var matchmaker_tcp = PacketPeerStream.new()
matchmaker_tcp.set_stream_peer(matchmaker_peer)
matchmaker_tcp.put_var(matchmaking.messages.ready_to_connect)
matchmaker_tcp.put_var(game_port)
master func _start_game():
rpc("_pre_configure_game", level)
func _send_all_info(new_peer):
for p in players:
if p != new_peer:
for key in players[p]:
var val = players[p][key]
# TODO: This broadcasts every connected peer,
# which isn't really a problem but it's lazy
set_info(key, val, p)
func _right_team_next():
var right_team_count = 0
for p in players:
var player = players[p]
if player.has("is_right_team") and player.is_right_team:
right_team_count += 1
return (right_team_count <= players.size() / 2)
sync func _set_info(key, value, peer):
if not players.has(peer):
players[peer] = {}
players[peer][key] = value
emit_signal("info_updated")
func _on_connect():
_register_player(get_tree().get_network_unique_id())
emit_signal("info_updated")
func _check_info():
# Check for "everyone is ready"
# Only have 1 person check this, might as well be server
if get_tree().is_network_server():
var ready = true
var all_done = true
for p in players:
if not players[p].has("spectating") or not players[p].spectating:
if not players[p].has("ready") or not players[p].ready:
ready = false
if not players[p].has("begun") or not players[p].begun:
all_done = false
if all_done:
rpc("_post_configure_game")
elif ready:
# If we're all done, then we don't need to even check a start_game
start_game()
sync func _spawn_player(p):
var hero = 0
if players[p].has("hero"):
hero = players[p].hero
var player = load("res://scenes/heroes/" + str(hero) + ".tscn").instance()
player.set_name(str(p))
player.set_network_master(p)
player.player_info = players[p]
get_node("/root/Level/Players").add_child(player)
func _begin_player(p):
var player = util.get_player(p)
player.begin()
sync func _pre_configure_game(level):
var self_peer_id = get_tree().get_network_unique_id()
var self_begun = players[self_peer_id].begun
if not self_begun:
get_node("/root/Lobby").hide()
var world = load("res://scenes/levels/%d.tscn" % level).instance()
get_node("/root").add_child(world)
# Load all players (including self)
for p in players:
if not players[p].spectating:
var existing_player = util.get_player(p)
if not self_begun or not existing_player:
_spawn_player(p)
for p in players:
if not players[p].spectating:
# Begin requires all players
_begin_player(p)
# Why do we check first? Weird error. It's because set_info triggers a
# start_game if everyone is ready
# This causes a stack overflow if we call it from here repeatedly
# So we only change it once, only start_game twice, and avoida segfault
if not self_begun:
set_info("begun", true)
sync func _post_configure_game():
# Begin all players (including self)
# TODO: What do? Maybe, unpause game?
pass

+ 4
- 0
scripts/placeable.gd View File

@ -2,6 +2,7 @@ extends StaticBody
var maker_node var maker_node
var material var material
var destroy_cost = 20
func _ready(): func _ready():
get_node("CollisionShape").disabled = true get_node("CollisionShape").disabled = true
@ -21,6 +22,9 @@ func place():
get_node("CollisionShape").disabled = false get_node("CollisionShape").disabled = false
material.flags_transparent = false material.flags_transparent = false
sync func destroy():
maker_node.placement.remove_placed(get_name())
func make_last(): func make_last():
material.flags_transparent = true material.flags_transparent = true
material.albedo_color.a = 0.9 material.albedo_color.a = 0.9


+ 11
- 9
scripts/placement.gd View File

@ -31,12 +31,12 @@ master func request_placed():
for node in placed: for node in placed:
rpc_id(get_tree().get_rpc_sender_id(), "slave_place", node.transform) rpc_id(get_tree().get_rpc_sender_id(), "slave_place", node.transform)
func place_input(radius=-1):
func place_input(radius=-1, can_build=true, require_ghost=false):
# We allow you to just click to place, without needing to press E # We allow you to just click to place, without needing to press E
var confirm = Input.is_action_just_pressed(confirm_action) var confirm = Input.is_action_just_pressed(confirm_action)
if Input.is_action_just_pressed(start_action) or (confirm and not is_placing):
if can_build and Input.is_action_just_pressed(start_action) or (confirm and not is_placing and not require_ghost):
# Press button twice to cancel # Press button twice to cancel
if is_placing: if is_placing:
# We changed our mind, delete the placing wall # We changed our mind, delete the placing wall
@ -50,9 +50,9 @@ func place_input(radius=-1):
if Input.is_action_just_pressed(delete_action): if Input.is_action_just_pressed(delete_action):
var pick = player.pick_from(placed) var pick = player.pick_from(placed)
if pick != -1: if pick != -1:
rpc("remove_placed", pick)
rpc("remove_placed", placed[pick].get_name())
if is_placing or confirm:
if is_placing:
position_placement(placing_node) position_placement(placing_node)
if radius > 0: # A radius is specified if radius > 0: # A radius is specified
var distance = placing_node.get_translation() - player.get_translation() var distance = placing_node.get_translation() - player.get_translation()
@ -62,10 +62,12 @@ func place_input(radius=-1):
else: else:
placing_node.within_range() placing_node.within_range()
if confirm:
if can_build and (confirm and not require_ghost) or (confirm and is_placing):
# Order matters here: confirm_placement resets placing_node so we have to do anything with it first # Order matters here: confirm_placement resets placing_node so we have to do anything with it first
rpc("slave_place", placing_node.transform) rpc("slave_place", placing_node.transform)
confirm_placement(placing_node) confirm_placement(placing_node)
return true
return false
func confirm_placement(node, tf=null): func confirm_placement(node, tf=null):
if tf: if tf:
@ -123,14 +125,14 @@ slave func slave_place(tf):
var node = create() var node = create()
confirm_placement(node, tf) confirm_placement(node, tf)
sync func remove_placed(index):
placed[index].queue_free()
placed.remove(index)
sync func remove_placed(name):
var what = get_node("/root/Level").get_node(name)
placed.erase(what)
what.queue_free()
func create(): func create():
var node = scene.instance() var node = scene.instance()
player.get_node("/root/Level").add_child(node) player.get_node("/root/Level").add_child(node)
# We have to call_deferred because we're `load`ing instead of `preload`ing. TODO: preload?
node.init(player) node.init(player)
return node return node

+ 103
- 55
scripts/player.gd View File

@ -3,42 +3,43 @@
extends RigidBody extends RigidBody
signal spawn
# Set by lobby. Contains player metadata (hero, nickname, etc)
var player_info
# Basic movement settings
# These are all public out here because they are customized by heroes
# Walking speed and jumping height are defined later. # Walking speed and jumping height are defined later.
var walk_speed = 0.8 # Actually acceleration; m/s/s var walk_speed = 0.8 # Actually acceleration; m/s/s
var jump_speed = 5 # m/s var jump_speed = 5 # m/s
var air_accel = .1 # m/s/s var air_accel = .1 # m/s/s
var floor_friction = 1-0.08 var floor_friction = 1-0.08
var air_friction = 1-0.03 var air_friction = 1-0.03
var player_info # Set by lobby
var walk_speed_build = 0.006 # `walk_speed` per `switch_charge`
var air_speed_build = 0.006 # `air_accel` per `switch_charge`
var walk_speed_build = 0.006 # `walk_speed` per `charge`
var air_speed_build = 0.006 # `air_accel` per `charge`
sync var switch_charge = 0
var switch_charge_cap = 200 # While switching is always at 100, things like speed boost might go higher!
sync var charge = 0
var charge_cap = 200 # While switching is always at 100, things like speed boost might go higher!
var movement_charge = 0.15 # In percent per meter (except when heroes change that) var movement_charge = 0.15 # In percent per meter (except when heroes change that)
var fall_height = -400 # This is essentially the respawn timer
var switch_height = -150 # At this point, stop adding to switch_charge. This makes falls not charge you too much
# Nodes
onready var switch_text = get_node("MasterOnly/ChargeBar/ChargeText")
onready var switch_bar = get_node("MasterOnly/ChargeBar")
onready var switch_bar_extra = get_node("MasterOnly/ChargeBar/Extra")
onready var switch_hero_action = get_node("MasterOnly/SwitchHero")
onready var tp_camera = get_node("TPCamera")
onready var master_only = get_node("MasterOnly")
onready var debug_node = get_node("/root/Level/Debug")
var debug_node
var recording var recording
var ai_instanced = false
slave var slave_transform = Basis()
slave var slave_lin_v = Vector3()
slave var slave_ang_v = Vector3()
var tp_camera = "TPCamera"
var master_only = "MasterOnly"
var master_player
var friend_color = Color("#4ab0e5") # Blue var friend_color = Color("#4ab0e5") # Blue
var enemy_color = Color("#f04273") # Red var enemy_color = Color("#f04273") # Red
var ai_instanced = false
signal spawn
# These meshes get colored with friendliness
var colored_meshes = [ var colored_meshes = [
"Yaw/MainMesh", "Yaw/MainMesh",
"Yaw/Pitch/RotatedHead", "Yaw/Pitch/RotatedHead",
@ -47,18 +48,18 @@ var colored_meshes = [
func _ready(): func _ready():
set_process_input(true) set_process_input(true)
debug_node = get_node("/root/Level/Debug")
if is_network_master(): if is_network_master():
get_node("TPCamera/Camera/Ray").add_exception(self) get_node("TPCamera/Camera/Ray").add_exception(self)
get_node(tp_camera).set_enabled(true)
spawn()
tp_camera.set_enabled(true)
tp_camera.cam_view_sensitivity = 0.05
if "is_ai" in player_info and player_info.is_ai and not ai_instanced: if "is_ai" in player_info and player_info.is_ai and not ai_instanced:
add_child(preload("res://scenes/ai.tscn").instance()) add_child(preload("res://scenes/ai.tscn").instance())
ai_instanced = true ai_instanced = true
spawn()
else: else:
get_node("PlayerName").set_text(player_info.username) get_node("PlayerName").set_text(player_info.username)
# Remove HUD # Remove HUD
remove_child(get_node(master_only))
remove_child(master_only)
func _input(event): func _input(event):
if is_network_master(): if is_network_master():
@ -69,30 +70,45 @@ func _input(event):
quit() quit()
if "record" in player_info: if "record" in player_info:
recording.events.append([recording.time, event_to_obj(event)]) recording.events.append([recording.time, event_to_obj(event)])
if Input.is_action_just_pressed("enable_cheats"):
charge = 199
func _process(delta): func _process(delta):
# All player code not caused by input, and not causing movement # All player code not caused by input, and not causing movement
if is_network_master(): if is_network_master():
# Check falling (cancel charge and respawn)
var fall_height = -400 # This is essentially the respawn timer
var switch_height = -150 # At this point, stop adding to charge. This makes falls not charge you too much
var vel = get_linear_velocity() var vel = get_linear_velocity()
if translation.y < switch_height: if translation.y < switch_height:
vel.y = 0 # Don't gain charge from falling when below switch_height vel.y = 0 # Don't gain charge from falling when below switch_height
switch_charge += movement_charge * vel.length() * delta
var switch_node = get_node("MasterOnly/SwitchCharge")
switch_node.set_text("%d%%" % int(switch_charge)) # We truncate, rather than round, so that switch is displayed AT 100%
if switch_charge >= 100:
# Let switch_charge keep building, because we use it for walk_speed and things
switch_node.set_text("100%% (%.f)\nQ - Switch hero" % switch_charge)
if switch_charge > switch_charge_cap:
# There is however a cap
switch_charge = switch_charge_cap
build_charge(movement_charge * vel.length() * delta)
if get_translation().y < fall_height: if get_translation().y < fall_height:
rpc("spawn") rpc("spawn")
# Update charge GUI
switch_text.set_text("%d%%" % int(charge)) # We truncate, rather than round, so that switch is displayed AT 100%
if charge >= 100:
switch_hero_action.show()
else:
switch_hero_action.hide()
if charge > charge_cap:
# There is however a cap
charge = charge_cap
switch_bar.value = charge
switch_bar_extra.value = charge - 100
# AI recording
if "record" in player_info: if "record" in player_info:
recording.time += delta recording.time += delta
rset_unreliable("switch_charge", switch_charge)
# on_looked_at is a special method for objects that need to respond to being looked at
# This was the best way to implement Hero 1's passive ability,
# But it'll probably come in handy more often so I made it kinda universal
var looking_at = pick()
if looking_at and looking_at.has_method("on_looked_at"):
looking_at.on_looked_at(self, delta)
func _integrate_forces(state): func _integrate_forces(state):
if is_network_master(): if is_network_master():
@ -109,6 +125,27 @@ func _exit_tree():
# Functions # Functions
# ========= # =========
# Build all charge with a multiplier for ~~balance~~
func build_charge(amount):
# If we used build_charge to cost charge, don't mess with it!
if amount > 0:
var losing_advantage = 1.2
var uncapped_advantage = 1.3
var obj = get_node("/root/Level/FullObjective/Objective")
if (obj.left > obj.right) == player_info.is_right_team:
# Is losing (left winning, we're on right or vice versa)
amount *= losing_advantage
if obj.right_active != player_info.is_right_team and obj.active:
# Point against us (right active and left, or vice versa)
amount *= uncapped_advantage
else:
# Only build down to 0
amount = max(amount, -charge)
charge += amount
if is_network_master():
rset_unreliable("charge", charge)
return amount
sync func spawn(): sync func spawn():
emit_signal("spawn") emit_signal("spawn")
if "record" in player_info: if "record" in player_info:
@ -126,12 +163,12 @@ sync func spawn():
placement.z += rand_range(0, z_varies) placement.z += rand_range(0, z_varies)
recording = { "time": 0, "states": [], "events": [], "spawn": Vector3() } recording = { "time": 0, "states": [], "events": [], "spawn": Vector3() }
recording.spawn = var2str(placement) recording.spawn = var2str(placement)
recording.switch_charge = var2str(switch_charge)
recording.charge = var2str(charge)
set_transform(Basis()) set_transform(Basis())
set_translation(placement) set_translation(placement)
set_linear_velocity(Vector3()) set_linear_velocity(Vector3())
get_node(tp_camera).cam_yaw = 0
get_node(tp_camera).cam_pitch = 0
tp_camera.cam_yaw = 0
tp_camera.cam_pitch = 0
func event_to_obj(event): func event_to_obj(event):
var d = {} var d = {}
@ -152,10 +189,13 @@ func event_to_obj(event):
return d return d
func begin(): func begin():
master_player = util.get_master_player()
_set_color()
func _set_color():
var master_player = util.get_master_player()
# Set color to blue (teammate) or red (enemy) # Set color to blue (teammate) or red (enemy)
var color var color
if master_player and master_player.player_info.is_right_team == player_info.is_right_team:
if master_player.player_info.is_right_team == player_info.is_right_team:
color = friend_color color = friend_color
else: else:
color = enemy_color color = enemy_color
@ -177,8 +217,8 @@ func toggle_mouse_capture():
# Update visual yaw + pitch components to match camera # Update visual yaw + pitch components to match camera
func set_rotation(): func set_rotation():
get_node("Yaw").set_rotation(Vector3(0, deg2rad(get_node(tp_camera).cam_yaw), 0))
get_node("Yaw/Pitch").set_rotation(Vector3(deg2rad(-get_node(tp_camera).cam_pitch), 0, 0))
get_node("Yaw").set_rotation(Vector3(0, deg2rad(tp_camera.cam_yaw), 0))
get_node("Yaw/Pitch").set_rotation(Vector3(deg2rad(-tp_camera.cam_pitch), 0, 0))
func record_status(status): func record_status(status):
if "record" in player_info: if "record" in player_info:
@ -190,16 +230,16 @@ slave func set_status(s):
set_transform(s[0]) set_transform(s[0])
set_linear_velocity(s[1]) set_linear_velocity(s[1])
set_angular_velocity(s[2]) set_angular_velocity(s[2])
get_node(tp_camera).cam_yaw = s[3]
get_node(tp_camera).cam_pitch = s[4]
tp_camera.cam_yaw = s[3]
tp_camera.cam_pitch = s[4]
func get_status(): func get_status():
return [ return [
get_transform(), get_transform(),
get_linear_velocity(), get_linear_velocity(),
get_angular_velocity(), get_angular_velocity(),
get_node(tp_camera).cam_yaw,
get_node(tp_camera).cam_pitch,
tp_camera.cam_yaw,
tp_camera.cam_pitch,
] ]
func control_player(state): func control_player(state):
@ -234,7 +274,7 @@ func control_player(state):
var floor_velocity = Vector3() var floor_velocity = Vector3()
var object = ray.get_collider() var object = ray.get_collider()
var accel = (1 + switch_charge * walk_speed_build) * walk_speed
var accel = (1 + charge * walk_speed_build) * walk_speed
state.apply_impulse(Vector3(), direction * accel * get_mass()) state.apply_impulse(Vector3(), direction * accel * get_mass())
var lin_v = state.get_linear_velocity() var lin_v = state.get_linear_velocity()
lin_v.x *= floor_friction lin_v.x *= floor_friction
@ -245,7 +285,7 @@ func control_player(state):
state.apply_impulse(Vector3(), normal * jump_speed * get_mass()) state.apply_impulse(Vector3(), normal * jump_speed * get_mass())
else: else:
var accel = (1 + switch_charge * air_speed_build) * air_accel
var accel = (1 + charge * air_speed_build) * air_accel
state.apply_impulse(Vector3(), direction * accel * get_mass()) state.apply_impulse(Vector3(), direction * accel * get_mass())
var lin_v = state.get_linear_velocity() var lin_v = state.get_linear_velocity()
lin_v.x *= air_friction lin_v.x *= air_friction
@ -255,7 +295,7 @@ func control_player(state):
state.integrate_forces() state.integrate_forces()
func switch_hero_interface(): func switch_hero_interface():
if switch_charge >= 100:
if charge >= 100:
# Interface needs the mouse! # Interface needs the mouse!
toggle_mouse_capture() toggle_mouse_capture()
# Pause so if we have walls and such nothing funny happens # Pause so if we have walls and such nothing funny happens
@ -280,7 +320,6 @@ sync func switch_hero(hero):
get_node("/root/Level/Players").call_deferred("add_child", new_hero) get_node("/root/Level/Players").call_deferred("add_child", new_hero)
# We must wait until after _ready is called, so that we don't end up at spawn # We must wait until after _ready is called, so that we don't end up at spawn
new_hero.call_deferred("set_status", get_status()) new_hero.call_deferred("set_status", get_status())
new_hero.call_deferred("begin")
queue_free() queue_free()
func write_recording(): func write_recording():
@ -297,10 +336,19 @@ func quit():
# These aren't used by vanilla player, but are used by heroes in common # These aren't used by vanilla player, but are used by heroes in common
func pick_from(group):
func pick():
var look_ray = get_node("TPCamera/Camera/Ray") var look_ray = get_node("TPCamera/Camera/Ray")
var looking_at = look_ray.get_collider()
var result = group.find(looking_at)
return result
return look_ray.get_collider()
func pick_from(group):
return group.find(pick())
func pick_player():
var players = get_node("/root/Level/Players").get_children()
return players[pick_from(players)]
func pick_by_friendly(pick_friendlies):
var pick = pick_player()
if (pick.player_info.is_right_team == player_info.is_right_team) == pick_friendlies:
return pick
else:
return null
# ========= # =========

+ 0
- 1
scripts/tp_camera.gd View File

@ -101,7 +101,6 @@ func cam_update():
if cam_ray_result.size() != 0: if cam_ray_result.size() != 0:
var a = (cam_ray_result.position-pivot.get_global_transform().origin).normalized(); var a = (cam_ray_result.position-pivot.get_global_transform().origin).normalized();
var b = pivot.get_global_transform().origin.distance_to(cam_ray_result.position); var b = pivot.get_global_transform().origin.distance_to(cam_ray_result.position);
#pos = cam_ray_result.position;
pos = pivot.get_global_transform().origin+a*max(b-0.1, 0); pos = pivot.get_global_transform().origin+a*max(b-0.1, 0);
else: else:
pos = cam_pos; pos = cam_pos;


+ 1
- 1
scripts/update.gd View File

@ -51,5 +51,5 @@ func restart():
get_tree().quit() get_tree().quit()
func completed(): func completed():
get_tree().change_scene("res://scenes/lobby.tscn")
get_tree().change_scene("res://scenes/menu.tscn")

+ 31
- 1
scripts/util.gd View File

@ -10,8 +10,19 @@ extends Node
# 1.0.0 will be the reddit release # 1.0.0 will be the reddit release
var version = "0.0.0" var version = "0.0.0"
var args
onready var Options = preload("res://scripts/args.gd").new().Options
func _ready():
args = _get_args()
func get_master_player(): func get_master_player():
var path = "/root/Level/Players/%d" % get_tree().get_network_unique_id()
return get_player(get_tree().get_network_unique_id())
func get_player(netid):
# We not %d? Because sometimes we need to do get_player(thing.get_name())
var path = "/root/Level/Players/%s" % str(netid)
if has_node(path): if has_node(path):
return get_node(path) return get_node(path)
else: else:
@ -24,3 +35,22 @@ func is_friendly(player):
else: else:
return true # Doesn't matter, we're headless return true # Doesn't matter, we're headless
func _get_args():
var opts = Options.new()
opts.set_banner(('A non-violent MOBA inspired by Overwatch and Zineth'))
opts.add('-singleplayer', false, 'Whether to run singeplayer, starting immediately')
opts.add('-server', false, 'Whether to run as server')
opts.add('-matchmaker', false, 'Whether to be the sole matchmaker')
opts.add('-client', false, 'Immediately connect as client')
opts.add('-silent', false, 'If the server is not playing, merely serving')
opts.add('-ip', '127.0.0.1', 'The ip to connect to (client only!)')
opts.add('-port', 54673, 'The port to run a server on or connect to')
opts.add('-hero', 'r', 'Your choice of hero (index)')
opts.add('-level', 'r', 'Your choice of level (index) - server only!')
opts.add('-start-game', false, 'Join as a client and immediately start the game')
opts.add('-ai', true, 'Run this client as AI')
opts.add('-no-record', true, "Don't record this play for AI later")
opts.add('-h', false, "Print help")
opts.parse()
return opts

+ 23
- 0
util/clear_editor_state.py View File

@ -0,0 +1,23 @@
#!/usr/bin/python3
from pathlib import Path
# Current working directory
cwd = Path.cwd()
for path in cwd.glob('**/*.tscn'):
result = []
with path.open() as f:
for line in f.readlines():
if line.startswith('_sections_unfolded'):
# Skip lines that start with _sections_unfolded
continue
elif line.startswith('[node') and 'parent=' not in line:
# Root node, remove 'index="0"'
result.append(line.replace(' index="0"', ''))
else:
# Add line as is
result.append(line)
with path.open('w') as f:
f.writelines(result)

+ 1
- 0
util/matchmaker.sh View File

@ -0,0 +1 @@
godot-server -matchmaker

+ 1
- 1
util/server.sh View File

@ -1,2 +1,2 @@
godot-server -level=2 -silent -server -start-game
godot-server -level=2 -silent -server "$@"

+ 1
- 1
util/start-multiple.sh View File

@ -10,5 +10,5 @@ fi
util/open-multiple.sh $count "$@" util/open-multiple.sh $count "$@"
sleep 1 sleep 1
godot -start-game "$@" &
godot -client -start-game "$@" &

Loading…
Cancel
Save