A team game with an emphasis on movement (with no shooting), inspired by Overwatch and Zineth
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

138 lines
3.8 KiB

  1. extends Node # Networking functionality
  2. var player
  3. var is_placing = false
  4. var placing_node
  5. var placed = []
  6. var max_placed = 5
  7. var start_action
  8. var confirm_action
  9. var delete_action
  10. var scene
  11. signal start_placement
  12. signal confirm_placement
  13. func _init(parent, scene_path):
  14. player = parent
  15. player.add_child(self)
  16. # Set the network master to the player's network master, which happens to be its name
  17. # This allows it to use master, slave keywords appropriately
  18. var net_id = int(player.get_name())
  19. set_name("Placement") # We need to share common name for networking
  20. set_network_master(net_id)
  21. scene = load(scene_path)
  22. rpc("request_placed")
  23. master func request_placed():
  24. for node in placed:
  25. rpc_id(get_tree().get_rpc_sender_id(), "slave_place", node.transform)
  26. func place_input(radius=-1, can_build=true, require_ghost=false):
  27. # We allow you to just click to place, without needing to press E
  28. var confirm = Input.is_action_just_pressed(confirm_action)
  29. if can_build and Input.is_action_just_pressed(start_action) or (confirm and not is_placing and not require_ghost):
  30. # Press button twice to cancel
  31. if is_placing:
  32. # We changed our mind, delete the placing wall
  33. placing_node.queue_free()
  34. is_placing = false
  35. else:
  36. # Make a floating placement wall
  37. placing_node = create()
  38. is_placing = true
  39. if Input.is_action_just_pressed(delete_action):
  40. var pick = player.pick_from(placed)
  41. if pick != -1:
  42. rpc("remove_placed", placed[pick].get_name())
  43. if is_placing:
  44. position_placement(placing_node)
  45. if radius > 0: # A radius is specified
  46. var distance = placing_node.get_translation() - player.get_translation()
  47. if distance.length() > radius:
  48. placing_node.out_of_range()
  49. confirm = false
  50. else:
  51. placing_node.within_range()
  52. if can_build and (confirm and not require_ghost) or (confirm and is_placing):
  53. # Order matters here: confirm_placement resets placing_node so we have to do anything with it first
  54. rpc("slave_place", placing_node.transform)
  55. confirm_placement(placing_node)
  56. return true
  57. return false
  58. func confirm_placement(node, tf=null):
  59. if tf:
  60. node.set_transform(tf)
  61. node.place()
  62. placed.append(node)
  63. check_count()
  64. placing_node = null
  65. is_placing = false
  66. func check_count():
  67. # If we've made max_walls, remove the first we made
  68. if placed.size() > max_placed:
  69. placed[0].queue_free()
  70. placed.pop_front()
  71. # When placing, make the about-to-disappear wall translucent
  72. if placed.size() >= max_placed:
  73. placed[0].make_last()
  74. # Find the point we're looking at, and put the wall there
  75. func position_placement(node):
  76. var aim = player.get_node("Yaw/Pitch").get_global_transform().basis
  77. var look_ray = player.get_node("TPCamera/Camera/Ray")
  78. var pos = look_ray.get_collision_point()
  79. node.set_translation(pos)
  80. var normal = look_ray.get_collision_normal()
  81. var towards = normal + pos
  82. var up = aim[2] # Wall should be horizontal to my view
  83. # This helps nearly horizontal walls be easier to make flat
  84. # We have two methods I'm deciding between
  85. var use_method_two = true
  86. if not use_method_two:
  87. # Method one: only allow horizontal or vertical, based on whether the surface faces you
  88. var on_wall_margin = 0.75
  89. if normal.dot(Vector3(0,1,0)) < on_wall_margin:
  90. var margin = 0.8
  91. if up.dot(normal) > margin: # The wall is facing us
  92. # We want flat
  93. up = Vector3(0,1,0)
  94. else:
  95. # We want straight
  96. up.y = 0
  97. else:
  98. # Method two: Make y more aggressive than other dimensions
  99. up.y = 3 * tanh(up.y)
  100. up = up.normalized()
  101. node.look_at(towards, up)
  102. func clear():
  103. for node in placed:
  104. node.queue_free()
  105. placed = []
  106. slave func slave_place(tf):
  107. var node = create()
  108. confirm_placement(node, tf)
  109. sync func remove_placed(name):
  110. var what = get_node("/root/Level").get_node(name)
  111. placed.erase(what)
  112. what.queue_free()
  113. func create():
  114. var node = scene.instance()
  115. player.get_node("/root/Level").add_child(node)
  116. node.init(player)
  117. return node