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) 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] [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.", "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.\n\nPress E to delete someone else's building (costs charge).", "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(): func _ready():


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

@ -24,7 +24,7 @@ func control_player(state):
var boost_strength = 2 var boost_strength = 2
var boost_drain = 25 # Recall increased charge must be factored in var boost_drain = 25 # Recall increased charge must be factored in
var cost = boost_drain * state.step 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 walk_speed *= 2
air_accel *= 2 air_accel *= 2
switch_charge -= cost switch_charge -= cost


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

@ -7,7 +7,7 @@ func _process(delta):
if being_touched > 0: if being_touched > 0:
maker_node.switch_charge += touch_charge * delta maker_node.switch_charge += touch_charge * delta
func init(maker):
func init(maker, index):
for player in get_node("/root/Level/Players").get_children(): for player in get_node("/root/Level/Players").get_children():
player.connect("body_entered", self, "count_bodies", [player, 1]) player.connect("body_entered", self, "count_bodies", [player, 1])
@ -27,7 +27,7 @@ func init(maker):
mat.albedo_color = color mat.albedo_color = color
get_node("MeshInstance").set_surface_material(0, mat) get_node("MeshInstance").set_surface_material(0, mat)
.init(maker)
.init(maker, index)
func count_bodies(with, player, delta): func count_bodies(with, player, delta):
if with == self: 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 get_node("TPCamera").cam_smooth_movement = true
if Input.is_action_just_pressed("primary_ability"): 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 looking_at.has_method("destroy"):
if switch_charge > looking_at.destroy_cost: if switch_charge > looking_at.destroy_cost:
switch_charge -= looking_at.destroy() 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 # 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 portal_cost = 20
var flicking = null
var flick_charge = 3
var flick_strength = 4
# --- Godot overrides --- # --- Godot overrides ---
@ -17,10 +23,30 @@ func _ready():
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 switch_charge < portal_cost else portal_crosshair
get_node("MasterOnly/Crosshair").set_text(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(): func _exit_tree():
._exit_tree() ._exit_tree()
@ -31,3 +57,10 @@ func _exit_tree():
# --- Own --- # --- 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" extends "res://scripts/placeable.gd"
var portal_charge = 15
var portal_charge = -5
var other var other
var index
var enemy_colors = [ var enemy_colors = [
Color("#d14013"), Color("#d14013"),
@ -24,10 +23,8 @@ func _exit_tree():
maker_node.placement.placed.remove(index - 1) maker_node.placement.placed.remove(index - 1)
other.queue_free() 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...) # 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)
@ -40,7 +37,7 @@ func init(maker):
mat.albedo_color = color mat.albedo_color = color
get_node("MeshInstance").set_surface_material(0, mat) get_node("MeshInstance").set_surface_material(0, mat)
.init(maker)
.init(maker, index)
func place(): func place():
.place() .place()
@ -57,12 +54,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.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 maker_node
var material var material
var destroy_cost = 20 var destroy_cost = 20
var index
func _ready(): func _ready():
get_node("CollisionShape").disabled = true get_node("CollisionShape").disabled = true
func init(maker):
func init(maker, index):
maker_node = maker maker_node = maker
self.index = index
material = get_node("MeshInstance").get_surface_material(0) material = get_node("MeshInstance").get_surface_material(0)
if not material: if not material:
@ -23,7 +25,7 @@ func place():
material.flags_transparent = false material.flags_transparent = false
func destroy(): func destroy():
queue_free()
maker_node.placement.remove_placed(index)
return destroy_cost return destroy_cost
func make_last(): func make_last():


+ 7
- 6
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, 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 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
@ -52,7 +52,7 @@ func place_input(radius=-1):
if pick != -1: if pick != -1:
rpc("remove_placed", pick) rpc("remove_placed", pick)
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 (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:
@ -130,7 +132,6 @@ sync func remove_placed(index):
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, placed.size())
return node 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 # 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
# ========= # =========

Loading…
Cancel
Save