diff options
| author | tpart <tpart120@proton.me> | 2025-06-18 22:29:59 +0200 | 
|---|---|---|
| committer | tpart <tpart120@proton.me> | 2025-06-18 22:30:03 +0200 | 
| commit | 05fe59c831a5f1b7f0666d617f275a86a6ce4d35 (patch) | |
| tree | 9f0e0c16e390486611dbbbe3b7ac2748339d011c /client | |
| parent | dc86da97ca960ce2ecebb3fde3c4122a56529bb8 (diff) | |
| download | hurrycurry-05fe59c831a5f1b7f0666d617f275a86a6ce4d35.tar hurrycurry-05fe59c831a5f1b7f0666d617f275a86a6ce4d35.tar.bz2 hurrycurry-05fe59c831a5f1b7f0666d617f275a86a6ce4d35.tar.zst | |
Consider players interact targets; Rewrite a lot of interact target code; Fix #321
Diffstat (limited to 'client')
| -rw-r--r-- | client/game.gd | 24 | ||||
| -rw-r--r-- | client/menu/communicate/chat/chat_open.gd | 2 | ||||
| -rw-r--r-- | client/menu/ingame.gd | 2 | ||||
| -rw-r--r-- | client/menu/lobby.gd | 2 | ||||
| -rw-r--r-- | client/menu/rating/rating.gd | 2 | ||||
| -rw-r--r-- | client/menu/scene_transition.tscn | 24 | ||||
| -rw-r--r-- | client/player/controllable_player.gd | 82 | ||||
| -rw-r--r-- | client/player/player.gd | 3 | 
8 files changed, 90 insertions, 51 deletions
| diff --git a/client/game.gd b/client/game.gd index c112eb37..f159077e 100644 --- a/client/game.gd +++ b/client/game.gd @@ -44,7 +44,7 @@ enum JoinState {  	JOINED,  } -var player_id: float = -1 +var my_player_id: float = -1  var item_names: Array = []  var item_index_by_name: Dictionary = {}  var tile_names: Array = [] @@ -86,7 +86,7 @@ func _ready():  func handle_packet(p):  	match p.type: -		"joined": player_id = p.id +		"joined": my_player_id = p.id  		"data":  			item_names = p["data"]["item_names"]  			tile_names = p["data"]["tile_names"] @@ -111,7 +111,7 @@ func handle_packet(p):  			data_updated.emit()  		"add_player":  			var player_instance: Player -			if p.id == player_id: +			if p.id == my_player_id:  				player_instance = ControllablePlayer.new(p.id, p.name, p.position, p.character, p.class, self)  				in_lobby_updated.connect(player_instance.onscreen_controls.in_lobby_updated)  				player_instance.onscreen_controls.in_lobby_updated(in_lobby) @@ -130,7 +130,7 @@ func handle_packet(p):  			if player.is_customer and player.current_item_message != null:  				tutorial_queue.erase(player.current_item_message)  			pinned_items.clear_item(p.id) -			if p.id == player_id: +			if p.id == my_player_id:  				set_join_state(JoinState.SPECTATING)  				follow_camera.target = $Center  			for h in player.hand: @@ -142,10 +142,10 @@ func handle_packet(p):  		"movement":  			var player_instance: Player = players[p.player]  			player_instance.update_position(p.pos, p.rot, p.boost) -			if p.player == player_id: last_position = p.pos +			if p.player == my_player_id: last_position = p.pos  		"movement_sync": -			if not players.has(player_id): return -			var player_instance: ControllablePlayer = players[player_id] +			if not players.has(my_player_id): return +			var player_instance: ControllablePlayer = players[my_player_id]  			player_instance.position_ = last_position  		"move_item":  			if "player" in p.from and "player" in p.to: @@ -240,7 +240,7 @@ func handle_packet(p):  							else:  								tutorial_running = true  								update_tutorial_running.emit(tutorial_running) -								mp.send_chat(player_id, "/start-tutorial %s" % item_name) +								mp.send_chat(my_player_id, "/start-tutorial %s" % item_name)  				elif "text" in p.message or "translation" in p.message:  					var data = TextMessage.new()  					data.timeout_initial = timeout_initial @@ -291,7 +291,7 @@ func handle_packet(p):  			if p.time_remaining != null:  				overlay.update(p.demands_failed, p.demands_completed, p.points, p.time_remaining)  		"tutorial_ended": -			if p.player != player_id: return +			if p.player != my_player_id: return  			tutorial_running = false  			update_tutorial_running.emit(tutorial_running) @@ -310,7 +310,7 @@ func handle_packet(p):  				if not tutorial_queue.is_empty() and not Global.get_setting("gameplay.tutorial_disabled"):  					tutorial_running = true  					update_tutorial_running.emit(tutorial_running) -					mp.send_chat(player_id, "/start-tutorial %s" % tutorial_queue.pop_front()) +					mp.send_chat(my_player_id, "/start-tutorial %s" % tutorial_queue.pop_front())  			else:  				tutorial_queue.clear()  		"menu": @@ -327,7 +327,7 @@ func handle_packet(p):  			else:  				popup_message.display_server_msg(mstr)  		"server_hint": -			if p.player != player_id: return +			if p.player != my_player_id: return  			var message = p.get("message")  			var position_ = p.get("position") @@ -369,7 +369,7 @@ func toggle_join():  			push_error("Join/Leave action already toggled.")  		JoinState.JOINED:  			set_join_state(JoinState.WAITING) -			mp.send_leave(player_id) +			mp.send_leave(my_player_id)  func _process(delta):  	update_center() diff --git a/client/menu/communicate/chat/chat_open.gd b/client/menu/communicate/chat/chat_open.gd index af691f39..41d4727e 100644 --- a/client/menu/communicate/chat/chat_open.gd +++ b/client/menu/communicate/chat/chat_open.gd @@ -37,7 +37,7 @@ func _ready() -> void:  func _input(event: InputEvent) -> void:  	if Input.is_action_just_pressed("chat"):  		if line.text != "": -			game.mp.send_chat(game.player_id, line.text) +			game.mp.send_chat(game.my_player_id, line.text)  		exit()  	super(event) diff --git a/client/menu/ingame.gd b/client/menu/ingame.gd index 85c03ad4..b08ff2ab 100644 --- a/client/menu/ingame.gd +++ b/client/menu/ingame.gd @@ -66,7 +66,7 @@ func _on_quit_pressed():  	quit()  func _on_lobby_pressed(): -	game.mp.send_chat(game.player_id, "/end") +	game.mp.send_chat(game.my_player_id, "/end")  	exit()  func _on_leave_pressed(): diff --git a/client/menu/lobby.gd b/client/menu/lobby.gd index 0cdabfdd..4c226936 100644 --- a/client/menu/lobby.gd +++ b/client/menu/lobby.gd @@ -169,7 +169,7 @@ func _on_start_pressed():  				for i in range(bot_counts[k]):  					start_msg += "\ncreate-bot %s" % k -		game.mp.send_chat(game.player_id, start_msg) +		game.mp.send_chat(game.my_player_id, start_msg)  		Sound.play_music("stop") # TODO: Game music enter  func _on_game_join_state_updated(state: Game.JoinState): diff --git a/client/menu/rating/rating.gd b/client/menu/rating/rating.gd index 83df08fa..17ac9512 100644 --- a/client/menu/rating/rating.gd +++ b/client/menu/rating/rating.gd @@ -63,4 +63,4 @@ func _on_button_timer_timeout() -> void:  func _on_scoreboard_pressed() -> void:  	exit() -	game.mp.send_chat(game.player_id, "/scoreboard %s" % Global.last_map_name) +	game.mp.send_chat(game.my_player_id, "/scoreboard %s" % Global.last_map_name) diff --git a/client/menu/scene_transition.tscn b/client/menu/scene_transition.tscn index 59956ac6..235830bf 100644 --- a/client/menu/scene_transition.tscn +++ b/client/menu/scene_transition.tscn @@ -3,34 +3,34 @@  [ext_resource type="Script" uid="uid://ciml1u2x4f1ci" path="res://menu/scene_transition.gd" id="1_fpbwj"]  [ext_resource type="Shader" uid="uid://bmxrbbw18xq7u" path="res://menu/text_loading_anim.gdshader" id="2_g21ck"] -[sub_resource type="Animation" id="Animation_e6dcd"] -resource_name = "fade" +[sub_resource type="Animation" id="Animation_g21ck"] +length = 0.001  tracks/0/type = "value"  tracks/0/imported = false  tracks/0/enabled = true  tracks/0/path = NodePath("black:color")  tracks/0/interp = 1 -tracks/0/loop_wrap = true +tracks/0/loop_wrap = false  tracks/0/keys = { -"times": PackedFloat32Array(0, 1), -"transitions": PackedFloat32Array(1, 1), +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1),  "update": 0, -"values": [Color(0, 0, 0, 0), Color(0, 0, 0, 1)] +"values": [Color(0, 0, 0, 1)]  } -[sub_resource type="Animation" id="Animation_g21ck"] -length = 0.001 +[sub_resource type="Animation" id="Animation_e6dcd"] +resource_name = "fade"  tracks/0/type = "value"  tracks/0/imported = false  tracks/0/enabled = true  tracks/0/path = NodePath("black:color")  tracks/0/interp = 1 -tracks/0/loop_wrap = false +tracks/0/loop_wrap = true  tracks/0/keys = { -"times": PackedFloat32Array(0), -"transitions": PackedFloat32Array(1), +"times": PackedFloat32Array(0, 1), +"transitions": PackedFloat32Array(1, 1),  "update": 0, -"values": [Color(0, 0, 0, 1)] +"values": [Color(0, 0, 0, 0), Color(0, 0, 0, 1)]  }  [sub_resource type="AnimationLibrary" id="AnimationLibrary_00tv0"] diff --git a/client/player/controllable_player.gd b/client/player/controllable_player.gd index fbc09859..126e4c10 100644 --- a/client/player/controllable_player.gd +++ b/client/player/controllable_player.gd @@ -23,6 +23,7 @@ const PLAYER_FRICTION = 15  const BOOST_FACTOR = 2.5  const BOOST_DURATION = 0.3  const BOOST_RESTORE = 0.5 +const MAX_PLAYER_INTERACT_DIST := 1.9  var onscreen_controls = preload("res://player/onscreen_controls/controls.tscn").instantiate() @@ -38,7 +39,10 @@ var vibration_timer := Timer.new()  var current_vibration_strength := 0.  var current_vibration_change := 0. -var target: Vector2i = Vector2i(0, 0) +var target_tile: Vector2i = Vector2i.ZERO +var target_visual: Vector3 = Vector3.ZERO +var found_interact_target := false +  var last_interaction = null  func _ready(): @@ -53,7 +57,7 @@ func _ready():  	timer.start()  	timer.connect("timeout", func():  		if game.mp != null and game.join_state == Game.JoinState.JOINED: -			game.mp.send_movement(game.player_id, position_, direction, boosting) +			game.mp.send_movement(game.my_player_id, position_, direction, boosting)  	)  	add_child(onscreen_controls)  	super() @@ -61,7 +65,7 @@ func _ready():  const MAX_DT = 1. / 50.  func _process(delta):  	super(delta) -	marker.position = G.interpolate(marker.position, marker_target, delta * 30.) +	marker.position = G.interpolate(marker.position, target_visual, delta * 30.)  	while delta > 0.001:  		var dt = min(delta, MAX_DT)  		_process_movement(dt) @@ -86,7 +90,9 @@ func _process_movement(delta):  	if Input.is_action_pressed("interact_left") or Input.is_action_just_released("interact_left") or Input.is_action_pressed("interact_right") or Input.is_action_just_released("interact_right"):  		input *= 0  	else: -		target = get_interact_target() +		var targets := get_interact_target() +		target_visual = targets[0] +		target_tile = targets[1]  		# target = Vector2i(  		# 	int(floor(movement_base.position.x + sin(movement_base.rotation.y))),  		# 	int(floor(movement_base.position.z + cos(movement_base.rotation.y))) @@ -205,52 +211,84 @@ func take_item(tile: Tile, h: int):  func interact():  	if not is_input_enabled(): return -	var tile = game.map.get_tile_instance(target) +	 +	var tile = game.map.get_tile_instance(target_tile)  	if tile != null:  		marker.visible = true -		# clear last interaction if target has moved since -		if last_interaction != null and not last_interaction == target: -			game.mp.send_tile_interact(game.player_id, last_interaction, false, 0) +		# clear last interaction if target_tile has moved since +		if last_interaction != null and not last_interaction == target_tile: +			game.mp.send_tile_interact(game.my_player_id, last_interaction, false, 0)  			marker.set_interacting(false)  			last_interaction = null -		marker.set_interactive(game.get_tile_interactive(target)) -		marker_target = tile.item_base.global_position +		marker.set_interactive(found_interact_target)  		for h in [0, 1]:  			if Input.is_action_just_pressed("interact_"+G.index_to_hand(h)) and last_interaction == null: -				last_interaction = target -				game.mp.send_tile_interact(game.player_id, target, true, h) +				last_interaction = target_tile +				game.mp.send_tile_interact(game.my_player_id, target_tile, true, h)  				tile.interact()  				marker.set_interacting(true)  			if Input.is_action_just_released("interact_"+G.index_to_hand(h)):  				last_interaction = null -				game.mp.send_tile_interact(game.player_id, target, false, h) +				game.mp.send_tile_interact(game.my_player_id, target_tile, false, h)  				marker.set_interacting(false)  	else:  		marker.visible = false -func get_interact_target() -> Vector2i: +func get_interact_target() -> Array: # -> [visual_target: Vector3, tile_target: Vector2i]  	var interact_target := Vector2(  		movement_base.position.x + sin(movement_base.rotation.y) * 0.7,  		movement_base.position.z + cos(movement_base.rotation.y) * 0.7  		) -	var interact_target_i := Vector2i(interact_target.floor()) -	var best_cursor := interact_target_i +	var interact_target_i := interact_target.floor() +	var best_cursor_visual := Vector3(interact_target_i.x, 0, interact_target_i.y) +	var best_cursor_i := interact_target_i  	var best_distance := 100. -	 +	found_interact_target = false + +	# Calculate player positions. Tiles with players on them are valid interact targets. +	var player_positions: Dictionary = {} # Dictionary[id: int, pos: Vector3] +	for p: Player in game.players.values(): +		player_positions[p.id] = Vector3(p.position_anim.x, 0, p.position_anim.y) + +	# Test all tiles in a 3x3 square around the player for interactible tiles. +	# Return the one which is closest to interact_target.  	for offset_x in range(-1,1):  		for offset_y in range (-1, 1): -			var offset_cursor := interact_target_i + Vector2i(offset_x, offset_y) +			var offset_cursor := interact_target_i + Vector2(offset_x, offset_y) +			var tile_center := Vector2(offset_cursor) + Vector2(0.5, 0.5)  			if game.get_tile_interactive(offset_cursor): -				var tile_center := Vector2(offset_cursor) + Vector2(0.5, 0.5)  				var cursor_tile_distance := (interact_target - tile_center).length()  				var player_tile_distance := Vector2(  					movement_base.position.x - tile_center.x,  					movement_base.position.z - tile_center.y  					).length() -				if player_tile_distance < 1.9 && cursor_tile_distance < best_distance: +				if player_tile_distance < MAX_PLAYER_INTERACT_DIST && cursor_tile_distance < best_distance: +					found_interact_target = true  					best_distance = cursor_tile_distance -					best_cursor = offset_cursor +					best_cursor_visual = game.map.get_tile_instance(offset_cursor).item_base.global_position +					best_cursor_i = offset_cursor +				continue +			 +			# Check if there are any players on this tile. +			# If there are multilpe, remember the player closest to the center of the tile +			# (They will be the interact target) +			var best_player_tile_distance := 100. +			var best_player_pos: Vector3 +			for p_id: int in player_positions.keys(): +				if p_id == game.my_player_id: continue # I can't interact with myself +				var p_pos: Vector3 = player_positions[p_id] +				var p_pos_2d := Vector2(p_pos.x, p_pos.z) +				var distance := p_pos_2d.distance_to(tile_center) +				if distance < 0.7: +					if distance < best_player_tile_distance: +						best_player_tile_distance = distance +						best_player_pos = p_pos +			if best_player_tile_distance < MAX_PLAYER_INTERACT_DIST && best_player_tile_distance < best_distance: +				found_interact_target = true +				best_distance = best_player_tile_distance +				best_cursor_visual = best_player_pos +				best_cursor_i = offset_cursor -	return best_cursor +	return [best_cursor_visual, best_cursor_i] diff --git a/client/player/player.gd b/client/player/player.gd index 265c1d65..c82cf6e6 100644 --- a/client/player/player.gd +++ b/client/player/player.gd @@ -22,6 +22,7 @@ const PLAYER_SIZE: float = 0.4  const SPEED: float = 25.  var game: Game +var id := -1  var rotation_ = 0.  var rotation_anim = 0.  var position_ = Vector2(0, 0) @@ -37,7 +38,6 @@ var chat_bubble: ChatBubble = preload("res://player/chat_bubble.tscn").instantia  var item_bubble: ItemBubble = preload("res://player/item_bubble.tscn").instantiate()  var effect: Effect = preload("res://player/particles/effect.tscn").instantiate()  var marker: Marker = preload("res://player/marker/marker.tscn").instantiate() -var marker_target = Vector3(0, 0, 0)  var clear_timer: Timer = Timer.new() @@ -56,6 +56,7 @@ const DEFAULT_HAND_BASE_POSITION_LEFT: Vector3 = Vector3(.3, .425, .4)  const DEFAULT_HAND_BASE_POSITION_RIGHT: Vector3 = Vector3(-.3, .425, .4)  func _init(_id: int, name_: String, pos: Vector2, character_style_: Dictionary, player_class_: String, game_: Game): +	id = _id  	character_style = character_style_  	player_class = player_class_  	game = game_ | 
