Browse Source

[Hero 5] Add ability: drag enemies in a direction

The impulse is fairly weak, but it has no cooldown (of course). As long
as you can reliably click on them, you can keep dragging them around.
This builds charge.

Portal now COSTS charge, rather than gaining it, so that you bully
people until you can build a portal.
master
Luna 7 years ago
parent
commit
fc262870c4
10 changed files with 81 additions and 34 deletions
  1. +2
    -0
      project.godot
  2. +1
    -1
      scripts/hero_select.gd
  3. +1
    -1
      scripts/heroes/0.gd
  4. +2
    -2
      scripts/heroes/1_wall.gd
  5. +1
    -2
      scripts/heroes/4.gd
  6. +35
    -2
      scripts/heroes/5.gd
  7. +12
    -14
      scripts/heroes/5_portal.gd
  8. +4
    -2
      scripts/placeable.gd
  9. +7
    -6
      scripts/placement.gd
  10. +16
    -4
      scripts/player.gd

+ 2
- 0
project.godot View File

@ -59,6 +59,8 @@ primary_ability=[ Object(InputEventKey,"resource_local_to_scene":false,"resource
]
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)
]
[rendering]


+ 1
- 1
scripts/hero_select.gd View File

@ -15,7 +15,7 @@ const hero_text = [
"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.",
"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\nClick to build portal. Click again to build its partner.\n\nYou can build multiple portal sets.",
"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():


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

@ -24,7 +24,7 @@ func control_player(state):
var boost_strength = 2
var boost_drain = 25 # Recall increased charge must be factored in
var cost = boost_drain * state.step
if Input.is_action_pressed("primary_action") and switch_charge > cost:
if Input.is_action_pressed("hero_0_boost") and switch_charge > cost:
walk_speed *= 2
air_accel *= 2
switch_charge -= cost


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

@ -7,7 +7,7 @@ func _process(delta):
if being_touched > 0:
maker_node.switch_charge += touch_charge * delta
func init(maker):
func init(maker, index):
for player in get_node("/root/Level/Players").get_children():
player.connect("body_entered", self, "count_bodies", [player, 1])
@ -27,7 +27,7 @@ func init(maker):
mat.albedo_color = color
get_node("MeshInstance").set_surface_material(0, mat)
.init(maker)
.init(maker, index)
func count_bodies(with, player, delta):
if with == self:


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

@ -29,8 +29,7 @@ func _process(delta):
get_node("TPCamera").cam_smooth_movement = true
if Input.is_action_just_pressed("primary_ability"):
var look_ray = get_node("TPCamera/Camera/Ray")
var looking_at = look_ray.get_collider()
var looking_at = pick()
if looking_at.has_method("destroy"):
if switch_charge > looking_at.destroy_cost:
switch_charge -= looking_at.destroy()


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

@ -6,6 +6,12 @@ var radius = 15
# The spaces make the bracket centered, rather than on of the dots
var first_crosshair = " [..."
var second_crosshair = "...] "
var no_portal_crosshair = "+"
var portal_cost = 20
var flicking = null
var flick_charge = 3
var flick_strength = 4
# --- Godot overrides ---
@ -17,10 +23,30 @@ func _ready():
func _process(delta):
if is_network_master():
placement.place_input(radius)
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 switch_charge < portal_cost else portal_crosshair
get_node("MasterOnly/Crosshair").set_text(crosshair)
if switch_charge > portal_cost or is_second:
if placement.place_input(radius, true) and is_second:
switch_charge -= portal_cost
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
switch_charge += flick_charge
func _exit_tree():
._exit_tree()
@ -31,3 +57,10 @@ func _exit_tree():
# --- Own ---
sync func flick(player_id, towards):
var who = $"/root/Level/Players".get_node(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
- 14
scripts/heroes/5_portal.gd View File

@ -1,8 +1,7 @@
extends "res://scripts/placeable.gd"
var portal_charge = 15
var portal_charge = -5
var other
var index
var enemy_colors = [
Color("#d14013"),
@ -24,10 +23,8 @@ func _exit_tree():
maker_node.placement.placed.remove(index - 1)
other.queue_free()
func init(maker):
func init(maker, index):
var maker_portals = maker.placement.placed
index = maker_portals.size() # No -1, because we haven't actually been added to the array yet
# If index is odd, we're the second (1, 3...), if even, first (0, 4...)
var second = index % 2 != 0
var is_friend = util.is_friendly(maker)
@ -40,7 +37,7 @@ func init(maker):
mat.albedo_color = color
get_node("MeshInstance").set_surface_material(0, mat)
.init(maker)
.init(maker, index)
func place():
.place()
@ -57,12 +54,13 @@ func player_collided(with, player):
func portal(player):
if player.player_info.is_right_team == maker_node.player_info.is_right_team:
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.switch_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.switch_charge += portal_charge

+ 4
- 2
scripts/placeable.gd View File

@ -3,12 +3,14 @@ extends StaticBody
var maker_node
var material
var destroy_cost = 20
var index
func _ready():
get_node("CollisionShape").disabled = true
func init(maker):
func init(maker, index):
maker_node = maker
self.index = index
material = get_node("MeshInstance").get_surface_material(0)
if not material:
@ -23,7 +25,7 @@ func place():
material.flags_transparent = false
func destroy():
queue_free()
maker_node.placement.remove_placed(index)
return destroy_cost
func make_last():


+ 7
- 6
scripts/placement.gd View File

@ -31,12 +31,12 @@ master func request_placed():
for node in placed:
rpc_id(get_tree().get_rpc_sender_id(), "slave_place", node.transform)
func place_input(radius=-1):
func place_input(radius=-1, require_ghost=false):
# We allow you to just click to place, without needing to press E
var confirm = Input.is_action_just_pressed(confirm_action)
if Input.is_action_just_pressed(start_action) or (confirm and not is_placing):
if Input.is_action_just_pressed(start_action) or (confirm and not is_placing and not require_ghost):
# Press button twice to cancel
if is_placing:
# We changed our mind, delete the placing wall
@ -52,7 +52,7 @@ func place_input(radius=-1):
if pick != -1:
rpc("remove_placed", pick)
if is_placing or confirm:
if is_placing:
position_placement(placing_node)
if radius > 0: # A radius is specified
var distance = placing_node.get_translation() - player.get_translation()
@ -62,10 +62,12 @@ func place_input(radius=-1):
else:
placing_node.within_range()
if confirm:
if (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
rpc("slave_place", placing_node.transform)
confirm_placement(placing_node)
return true
return false
func confirm_placement(node, tf=null):
if tf:
@ -130,7 +132,6 @@ sync func remove_placed(index):
func create():
var node = scene.instance()
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, placed.size())
return node

+ 16
- 4
scripts/player.gd View File

@ -297,10 +297,22 @@ func quit():
# 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 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
# =========

Loading…
Cancel
Save