2020-07-11 23:36:22 +02:00
|
|
|
# Copyright Péter Magyar relintai@gmail.com
|
|
|
|
# MIT License, functionality from this class needs to be protable to the entity spell system
|
|
|
|
|
|
|
|
# Copyright (c) 2019-2020 Péter Magyar
|
|
|
|
|
|
|
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
# of this software and associated documentation files (the "Software"), to deal
|
|
|
|
# in the Software without restriction, including without limitation the rights
|
|
|
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
# copies of the Software, and to permit persons to whom the Software is
|
|
|
|
# furnished to do so, subject to the following conditions:
|
|
|
|
#
|
|
|
|
# The above copyright notice and this permission notice shall be included in all
|
|
|
|
# copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
|
# SOFTWARE.
|
|
|
|
|
2020-07-15 16:26:14 +02:00
|
|
|
extends Node2D
|
2020-07-11 23:36:22 +02:00
|
|
|
|
|
|
|
export(String) var world_path : String = "../.."
|
|
|
|
export(NodePath) var character_skeleton_path : NodePath = "Character"
|
|
|
|
|
|
|
|
const BASE_SPEED = 60.0
|
|
|
|
|
|
|
|
const MOUSE_TARGET_MAX_OFFSET : int = 10
|
|
|
|
|
2020-07-15 00:41:25 +02:00
|
|
|
var input_direction : Vector2
|
2020-07-11 23:36:22 +02:00
|
|
|
|
2020-07-15 00:41:25 +02:00
|
|
|
var target_position : Vector2
|
|
|
|
var path : PoolVector2Array
|
|
|
|
var current_movement_target : Vector2
|
2020-07-11 23:36:22 +02:00
|
|
|
|
|
|
|
var camera : Camera2D
|
|
|
|
|
|
|
|
var last_mouse_over : Entity = null
|
|
|
|
|
2020-07-15 18:57:45 +02:00
|
|
|
var world : Node2D = null
|
2020-07-11 23:36:22 +02:00
|
|
|
|
|
|
|
var _controlled : bool = false
|
|
|
|
|
|
|
|
var sleep : bool = false
|
|
|
|
var sleep_recheck_timer : float = 0
|
|
|
|
var dead : bool = false
|
|
|
|
var death_timer : float = 0
|
|
|
|
|
|
|
|
var entity : Entity
|
|
|
|
var character_skeleton : CharacterSkeleton2D
|
|
|
|
|
2020-07-12 19:34:44 +02:00
|
|
|
var visibility_update_timer : float = randi()
|
2020-07-11 23:36:22 +02:00
|
|
|
|
2020-07-15 16:26:14 +02:00
|
|
|
var tile_size : int = 32
|
2020-07-15 00:41:25 +02:00
|
|
|
|
2020-07-15 21:34:14 +02:00
|
|
|
var nameplate : Node
|
|
|
|
|
2020-07-11 23:36:22 +02:00
|
|
|
func _enter_tree() -> void:
|
2020-07-15 18:57:45 +02:00
|
|
|
world = get_node(world_path) as Node2D
|
2020-07-15 16:26:14 +02:00
|
|
|
tile_size = get_node("/root/Main").get_tile_size()
|
|
|
|
|
2020-07-11 23:36:22 +02:00
|
|
|
camera = get_node_or_null("Camera") as Camera2D
|
2020-07-15 16:26:14 +02:00
|
|
|
|
|
|
|
set_process_input(false)
|
|
|
|
set_process_unhandled_input(false)
|
2020-07-11 23:36:22 +02:00
|
|
|
|
|
|
|
character_skeleton = get_node(character_skeleton_path)
|
|
|
|
entity = get_node("..")
|
|
|
|
entity.set_character_skeleton(character_skeleton)
|
|
|
|
# entity.connect("notification_ccast", self, "on_notification_ccast")
|
|
|
|
entity.connect("diesd", self, "on_diesd")
|
|
|
|
entity.connect("isc_controlled_changed", self, "on_c_controlled_changed")
|
|
|
|
owner = entity
|
|
|
|
|
|
|
|
on_c_controlled_changed(entity.c_is_controlled)
|
|
|
|
|
|
|
|
transform = entity.get_transform_2d(true)
|
|
|
|
|
2020-07-15 21:34:14 +02:00
|
|
|
func set_visibility(val : bool) -> void:
|
|
|
|
if val:
|
|
|
|
show()
|
2020-07-11 23:36:22 +02:00
|
|
|
|
2020-07-15 21:34:14 +02:00
|
|
|
if nameplate:
|
|
|
|
nameplate.show()
|
|
|
|
elif !val:
|
|
|
|
hide()
|
2020-07-11 23:36:22 +02:00
|
|
|
|
2020-07-15 21:34:14 +02:00
|
|
|
if nameplate:
|
|
|
|
nameplate.hide()
|
2020-07-12 19:34:44 +02:00
|
|
|
|
2020-07-11 23:36:22 +02:00
|
|
|
func _unhandled_input(event: InputEvent) -> void:
|
2020-07-15 16:26:14 +02:00
|
|
|
#Not sure why yet, but _unhandled_input gets called even after set_process_unhandled_input(false)
|
|
|
|
if !entity.c_is_controlled:
|
|
|
|
return
|
2020-07-15 00:41:25 +02:00
|
|
|
|
2020-07-15 16:26:14 +02:00
|
|
|
if event.is_action_pressed("left"):
|
|
|
|
try_move(-1, 0)
|
2020-07-15 21:34:14 +02:00
|
|
|
get_tree().set_input_as_handled()
|
2020-07-15 16:26:14 +02:00
|
|
|
return
|
|
|
|
elif event.is_action_pressed("right"):
|
|
|
|
try_move(1, 0)
|
2020-07-15 21:34:14 +02:00
|
|
|
get_tree().set_input_as_handled()
|
2020-07-15 16:26:14 +02:00
|
|
|
return
|
|
|
|
elif event.is_action_pressed("up"):
|
|
|
|
try_move(0, -1)
|
2020-07-15 21:34:14 +02:00
|
|
|
get_tree().set_input_as_handled()
|
2020-07-15 16:26:14 +02:00
|
|
|
return
|
|
|
|
elif event.is_action_pressed("down"):
|
|
|
|
try_move(0, 1)
|
2020-07-15 21:34:14 +02:00
|
|
|
get_tree().set_input_as_handled()
|
|
|
|
return
|
|
|
|
elif event.is_action_pressed("wait"):
|
|
|
|
world.player_moved()
|
|
|
|
get_tree().set_input_as_handled()
|
2020-07-15 16:26:14 +02:00
|
|
|
return
|
2020-07-11 23:36:22 +02:00
|
|
|
|
2020-07-15 00:41:25 +02:00
|
|
|
if event is InputEventMouseMotion and event.device != -1:
|
2020-07-15 21:34:14 +02:00
|
|
|
cmouseover(event.position)
|
|
|
|
get_tree().set_input_as_handled()
|
2020-07-11 23:36:22 +02:00
|
|
|
|
|
|
|
if event is InputEventMouseButton:
|
2020-07-15 00:41:25 +02:00
|
|
|
if event.button_index == BUTTON_WHEEL_DOWN and event.device != -1:
|
|
|
|
if camera == null:
|
|
|
|
return
|
2020-07-11 23:36:22 +02:00
|
|
|
|
2020-07-15 00:41:25 +02:00
|
|
|
if camera.zoom.x >= 1:
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
camera.zoom += Vector2(event.factor, event.factor) * 0.01
|
|
|
|
elif event.button_index == BUTTON_WHEEL_UP and event.device != -1:
|
|
|
|
if camera == null:
|
|
|
|
return
|
|
|
|
|
|
|
|
if camera.zoom.x <= 0.2:
|
|
|
|
return
|
2020-07-11 23:36:22 +02:00
|
|
|
else:
|
2020-07-15 00:41:25 +02:00
|
|
|
camera.zoom -= Vector2(event.factor, event.factor) * 0.01
|
|
|
|
elif event.button_index == BUTTON_LEFT and event.device != -1:
|
|
|
|
if event.pressed:
|
2020-07-15 21:51:24 +02:00
|
|
|
#https://github.com/godotengine/godot/issues/32222
|
|
|
|
var pos = event.position - get_viewport_transform().origin
|
|
|
|
pos *= camera.zoom
|
|
|
|
|
|
|
|
pos -= transform.origin
|
|
|
|
|
|
|
|
if pos.length() < tile_size / 2:
|
|
|
|
#wait
|
|
|
|
world.player_moved()
|
|
|
|
return
|
|
|
|
|
|
|
|
var mx : int = 0
|
|
|
|
var my : int = 0
|
|
|
|
|
|
|
|
if abs(pos.x) > tile_size / 2:
|
|
|
|
if pos.x >= 0:
|
|
|
|
mx = 1
|
|
|
|
else:
|
|
|
|
mx = -1
|
|
|
|
|
|
|
|
if abs(pos.y) > tile_size / 2:
|
|
|
|
if pos.y >= 0:
|
|
|
|
my = 1
|
|
|
|
else:
|
|
|
|
my = -1
|
|
|
|
|
|
|
|
try_move(mx, my)
|
2020-07-11 23:36:22 +02:00
|
|
|
|
|
|
|
# if not event.pressed and event.button_index == BUTTON_LEFT and event.device != -1:
|
|
|
|
# if mouse_down_delta.length() < MOUSE_TARGET_MAX_OFFSET:
|
|
|
|
# target(event.position)
|
|
|
|
|
|
|
|
if event.pressed and event.button_index == BUTTON_RIGHT and event.device != -1:
|
|
|
|
target(event.position)
|
2020-07-15 21:51:24 +02:00
|
|
|
|
2020-07-15 21:34:14 +02:00
|
|
|
get_tree().set_input_as_handled()
|
2020-07-11 23:36:22 +02:00
|
|
|
|
|
|
|
|
|
|
|
if event is InputEventScreenTouch and event.pressed:
|
2020-07-15 21:51:24 +02:00
|
|
|
if !target(event.position):
|
|
|
|
#https://github.com/godotengine/godot/issues/32222
|
|
|
|
var pos = event.position - get_viewport_transform().origin
|
|
|
|
pos *= camera.zoom
|
|
|
|
|
|
|
|
pos -= transform.origin
|
|
|
|
|
|
|
|
if pos.length() < tile_size / 2:
|
|
|
|
#wait
|
|
|
|
world.player_moved()
|
|
|
|
return
|
|
|
|
|
|
|
|
var mx : int = 0
|
|
|
|
var my : int = 0
|
|
|
|
|
|
|
|
if abs(pos.x) > tile_size / 2:
|
|
|
|
if pos.x >= 0:
|
|
|
|
mx = 1
|
|
|
|
else:
|
|
|
|
mx = -1
|
|
|
|
|
|
|
|
if abs(pos.y) > tile_size / 2:
|
|
|
|
if pos.y >= 0:
|
|
|
|
my = 1
|
|
|
|
else:
|
|
|
|
my = -1
|
|
|
|
|
|
|
|
try_move(mx, my)
|
|
|
|
|
2020-07-15 21:34:14 +02:00
|
|
|
get_tree().set_input_as_handled()
|
2020-07-11 23:36:22 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
2020-07-15 16:26:14 +02:00
|
|
|
func try_move(dx, dy):
|
2020-07-15 21:34:14 +02:00
|
|
|
var state : int = entity.getc_state()
|
|
|
|
|
|
|
|
if state & EntityEnums.ENTITY_STATE_TYPE_FLAG_ROOT != 0 or state & EntityEnums.ENTITY_STATE_TYPE_FLAG_STUN != 0:
|
|
|
|
return
|
|
|
|
|
2020-07-15 16:26:14 +02:00
|
|
|
var tp : Vector2 = get_tile_position()
|
|
|
|
tp.x += dx
|
|
|
|
tp.y += dy
|
|
|
|
|
|
|
|
if !world.is_position_walkable(tp.x, tp.y):
|
|
|
|
return
|
|
|
|
|
|
|
|
#todo
|
|
|
|
#world.can_interact
|
|
|
|
|
|
|
|
set_tile_position(tp)
|
|
|
|
|
2020-07-15 18:57:45 +02:00
|
|
|
if entity.c_is_controlled:
|
|
|
|
world.player_moved()
|
|
|
|
|
2020-07-15 21:34:14 +02:00
|
|
|
func move_towards_target():
|
|
|
|
var state : int = entity.getc_state()
|
2020-07-15 16:26:14 +02:00
|
|
|
|
2020-07-15 21:34:14 +02:00
|
|
|
if state & EntityEnums.ENTITY_STATE_TYPE_FLAG_ROOT != 0 or state & EntityEnums.ENTITY_STATE_TYPE_FLAG_STUN != 0:
|
|
|
|
return
|
|
|
|
|
|
|
|
var t : Entity = entity.getc_target()
|
|
|
|
|
|
|
|
if !t:
|
|
|
|
return
|
|
|
|
|
|
|
|
var bp : Vector2 = t.get_body().get_tile_position()
|
|
|
|
|
|
|
|
var my_point = world.nav_graph.get_closest_point(get_tile_position())
|
|
|
|
var target_point = world.nav_graph.get_closest_point(bp)
|
|
|
|
var path = world.nav_graph.get_point_path(my_point, target_point)
|
|
|
|
|
|
|
|
if path:
|
|
|
|
assert(path.size() > 1)
|
|
|
|
|
|
|
|
var move_tile = Vector2(path[1].x, path[1].y)
|
|
|
|
|
|
|
|
if move_tile == bp:
|
|
|
|
return
|
|
|
|
|
|
|
|
for e in world.enemies:
|
|
|
|
if e.get_body().get_tile_position() == move_tile:
|
|
|
|
return
|
|
|
|
|
|
|
|
set_tile_position(move_tile)
|
|
|
|
|
|
|
|
func get_tile_position() -> Vector2:
|
|
|
|
return Vector2(int(transform.origin.x / tile_size), int(transform.origin.y / tile_size))
|
2020-07-15 16:26:14 +02:00
|
|
|
|
|
|
|
func set_tile_position(pos : Vector2) -> void:
|
|
|
|
transform.origin = pos * tile_size + Vector2(tile_size / 2, tile_size / 2)
|
|
|
|
|
2020-07-15 21:51:24 +02:00
|
|
|
func target(position : Vector2) -> bool:
|
2020-07-15 21:34:14 +02:00
|
|
|
#https://github.com/godotengine/godot/issues/32222
|
|
|
|
position = position - get_viewport_transform().origin
|
|
|
|
position *= camera.zoom
|
|
|
|
|
|
|
|
var pos : Vector2 = world.pixel_to_tile(position.x, position.y)
|
|
|
|
var enemy : Entity = world.get_enemy_at_tile(pos.x, pos.y)
|
|
|
|
|
|
|
|
if enemy:
|
|
|
|
if entity.getc_target() != enemy:
|
|
|
|
entity.target_crequest_change(enemy.get_path())
|
2020-07-15 21:51:24 +02:00
|
|
|
return true
|
2020-07-15 21:34:14 +02:00
|
|
|
else:
|
|
|
|
entity.target_crequest_change(NodePath())
|
2020-07-15 21:51:24 +02:00
|
|
|
|
|
|
|
return false
|
2020-07-15 21:34:14 +02:00
|
|
|
|
|
|
|
func cmouseover(position : Vector2):
|
|
|
|
#https://github.com/godotengine/godot/issues/32222
|
|
|
|
position = position - get_viewport_transform().origin
|
|
|
|
position *= camera.zoom
|
|
|
|
|
|
|
|
var pos : Vector2 = world.pixel_to_tile(position.x, position.y)
|
|
|
|
var enemy : Entity = world.get_enemy_at_tile(pos.x, pos.y)
|
|
|
|
|
|
|
|
if enemy:
|
|
|
|
if last_mouse_over != null and last_mouse_over != entity:
|
|
|
|
if is_instance_valid(last_mouse_over):
|
|
|
|
last_mouse_over.notification_cmouse_exit()
|
|
|
|
|
|
|
|
last_mouse_over = null
|
|
|
|
|
|
|
|
if last_mouse_over == null:
|
|
|
|
entity.notification_cmouse_enter()
|
|
|
|
last_mouse_over = entity
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
if last_mouse_over != null:
|
|
|
|
last_mouse_over.notification_cmouse_exit()
|
|
|
|
last_mouse_over = null
|
2020-07-11 23:36:22 +02:00
|
|
|
|
|
|
|
|
|
|
|
func on_c_controlled_changed(val):
|
|
|
|
#create camera and pivot if true
|
|
|
|
_controlled = val
|
|
|
|
|
|
|
|
if val:
|
|
|
|
camera = Camera2D.new()
|
2020-07-13 20:52:10 +02:00
|
|
|
camera.zoom = get_node("/root/Main").get_world_scale()
|
2020-07-11 23:36:22 +02:00
|
|
|
add_child(camera)
|
|
|
|
camera.current = true
|
|
|
|
|
|
|
|
var uiscn : PackedScene = ResourceLoader.load("res://ui/player_ui/player_ui.tscn")
|
|
|
|
var ui = uiscn.instance()
|
2020-07-13 01:47:44 +02:00
|
|
|
add_child(ui)
|
2020-07-11 23:36:22 +02:00
|
|
|
|
2020-07-15 16:26:14 +02:00
|
|
|
# set_process_input(true)
|
2020-07-11 23:36:22 +02:00
|
|
|
set_process_unhandled_input(true)
|
2020-07-15 21:34:14 +02:00
|
|
|
|
|
|
|
set_visibility(true)
|
2020-07-11 23:36:22 +02:00
|
|
|
else:
|
|
|
|
if camera:
|
|
|
|
camera.queue_free()
|
|
|
|
camera = null
|
2020-07-15 16:26:14 +02:00
|
|
|
|
|
|
|
# set_process_input(false)
|
2020-07-11 23:36:22 +02:00
|
|
|
set_process_unhandled_input(false)
|
2020-07-13 01:47:44 +02:00
|
|
|
var nameplatescn : PackedScene = ResourceLoader.load("res://ui/nameplates/NamePlate.tscn")
|
2020-07-15 21:34:14 +02:00
|
|
|
nameplate = nameplatescn.instance()
|
2020-07-13 01:47:44 +02:00
|
|
|
get_parent().add_child(nameplate)
|
2020-07-11 23:36:22 +02:00
|
|
|
|
2020-07-15 21:34:14 +02:00
|
|
|
set_visibility(false)
|
2020-07-11 23:36:22 +02:00
|
|
|
|
|
|
|
|
|
|
|
remote func sset_position(pposition : Vector2) -> void:
|
|
|
|
if multiplayer.network_peer and multiplayer.is_network_server():
|
|
|
|
entity.vrpc("cset_position", position)
|
|
|
|
|
|
|
|
if _controlled:
|
|
|
|
cset_position(position)
|
|
|
|
|
|
|
|
remote func cset_position(pposition : Vector2) -> void:
|
|
|
|
pposition = pposition
|
|
|
|
|