Fix multiplayer menu workshop build
This commit is contained in:
BIN
releases/Brogether-Brogether-v0.1.6.zip
Normal file
BIN
releases/Brogether-Brogether-v0.1.6.zip
Normal file
Binary file not shown.
@@ -0,0 +1,19 @@
|
|||||||
|
extends Node
|
||||||
|
|
||||||
|
# TODO rename options to globals
|
||||||
|
|
||||||
|
var joining_multiplayer_lobby : bool = false
|
||||||
|
var is_solo_test : bool = false
|
||||||
|
|
||||||
|
var in_multiplayer_game : bool = false
|
||||||
|
|
||||||
|
var current_network_id : int = 0
|
||||||
|
|
||||||
|
var batched_enemy_deaths = {}
|
||||||
|
var batched_unit_flashes = {}
|
||||||
|
var batched_floating_text = []
|
||||||
|
var batched_hit_particles = []
|
||||||
|
var batched_explosions = []
|
||||||
|
var batched_hit_effects = []
|
||||||
|
var batched_sounds = []
|
||||||
|
var batched_2d_sounds = []
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
extends AttackBehavior
|
||||||
|
|
||||||
|
signal shot
|
||||||
|
signal finished_shooting
|
||||||
|
signal entered_long_cooldown
|
||||||
|
signal started_shooting
|
||||||
|
signal move_unlocked
|
||||||
|
signal wanted_to_spawn_an_enemy(enemy_scene, position)
|
||||||
|
|
||||||
|
# check out all the nothing this enemy will do!
|
||||||
|
var max_range
|
||||||
|
var charge_duration
|
||||||
|
var charge_speed
|
||||||
|
var long_cooldown = 1.0
|
||||||
|
var cooldown = 1.0
|
||||||
|
var _current_cd = 1.0
|
||||||
|
var number_projectiles
|
||||||
504
src/mods-unpacked/Brogether-Brogether/client/client_main.gd
Normal file
504
src/mods-unpacked/Brogether-Brogether/client/client_main.gd
Normal file
@@ -0,0 +1,504 @@
|
|||||||
|
extends Node
|
||||||
|
|
||||||
|
var ClientMovementBehavior = load("res://mods-unpacked/Brogether-Brogether/client/client_movement_behavior.gd")
|
||||||
|
|
||||||
|
signal consumable_to_process_added(consumable_data)
|
||||||
|
signal upgrade_to_process_added(consumable_data)
|
||||||
|
|
||||||
|
export (PackedScene) var gold_bag_scene:PackedScene
|
||||||
|
export (PackedScene) var gold_scene:PackedScene
|
||||||
|
export (PackedScene) var consumable_scene:PackedScene
|
||||||
|
export (Array) var gold_sprites:Array
|
||||||
|
export (Array, Resource) var gold_pickup_sounds:Array
|
||||||
|
export (Array, Resource) var gold_alt_pickup_sounds:Array
|
||||||
|
export (Resource) var level_up_sound:Resource
|
||||||
|
export (Array, Resource) var run_won_sounds:Array
|
||||||
|
export (Array, Resource) var run_lost_sounds:Array
|
||||||
|
export (Array, Resource) var end_wave_sounds:Array
|
||||||
|
|
||||||
|
const EDGE_SIZE = 96
|
||||||
|
const MAX_GOLDS = 50
|
||||||
|
const MIN_MAP_SIZE = 12
|
||||||
|
|
||||||
|
const MOUSE_DIST_FROM_PLAYER_MANUAL_AIM = 200
|
||||||
|
|
||||||
|
var _cleaning_up: = false
|
||||||
|
var _golds: = []
|
||||||
|
var _consumables: = []
|
||||||
|
var _upgrades_to_process: = []
|
||||||
|
var _consumables_to_process: = []
|
||||||
|
var _end_wave_timer_timedout: = false
|
||||||
|
|
||||||
|
var _player:Player
|
||||||
|
var _is_run_lost:bool
|
||||||
|
var _is_run_won:bool
|
||||||
|
var _gold_bag:Node
|
||||||
|
|
||||||
|
var _landmine_timer:Timer = null
|
||||||
|
var _is_chal_ui_displayed = false
|
||||||
|
|
||||||
|
var _last_rjoy_input:Vector2 = Vector2.ZERO
|
||||||
|
|
||||||
|
var _proj_on_death_stat_cache:Dictionary = {}
|
||||||
|
var _items_spawned_this_wave: = 0
|
||||||
|
|
||||||
|
var _nb_bosses_killed_this_wave: = 0
|
||||||
|
var _update_stats_on_gold_changed: = false
|
||||||
|
var _update_stats_on_enemies_changed: = false
|
||||||
|
var _update_stats_on_enemies_changed_timer:Timer = null
|
||||||
|
var _last_gold_amount_used_to_reload_stats: = 0
|
||||||
|
var _elite_killed_bonus: = 0
|
||||||
|
var _elite_killed: = false
|
||||||
|
|
||||||
|
var _convert_stats_half_wave_proced: = false
|
||||||
|
|
||||||
|
onready var _entities_container = $Entities
|
||||||
|
onready var _effects_manager = $EffectsManager
|
||||||
|
onready var _wave_manager = $WaveManager
|
||||||
|
onready var _floating_text_manager = $FloatingTextManager
|
||||||
|
onready var _camera = $Camera
|
||||||
|
onready var _screenshaker = $Camera / Screenshaker
|
||||||
|
onready var _items_container = $Items
|
||||||
|
onready var _consumables_container = $Consumables
|
||||||
|
onready var _births_container = $Births
|
||||||
|
onready var _pause_menu = $UI / PauseMenu
|
||||||
|
onready var _end_wave_timer = $EndWaveTimer
|
||||||
|
onready var _upgrades_ui = $UI / UpgradesUI as UpgradesUI
|
||||||
|
onready var _item_box_ui = $UI / ItemBoxUI as ItemBoxUI
|
||||||
|
onready var _wave_timer = $WaveTimer
|
||||||
|
onready var _player_life_bar = $"%PlayerLifeBar"
|
||||||
|
onready var _player_life_bar_container = $PlayerLifeBarContainer
|
||||||
|
|
||||||
|
onready var _wave_cleared_label = $UI / WaveClearedLabel
|
||||||
|
onready var _life_label = $UI / HUD / LifeContainer / UILifeBar / MarginContainer / LifeLabel
|
||||||
|
onready var _level_label = $UI / HUD / LifeContainer / UIXPBar / MarginContainer / LevelLabel
|
||||||
|
onready var _hud = $UI / HUD
|
||||||
|
onready var _life_bar = $UI / HUD / LifeContainer / UILifeBar
|
||||||
|
onready var _xp_bar = $UI / HUD / LifeContainer / UIXPBar
|
||||||
|
onready var _ui_gold = $UI / HUD / LifeContainer / UIGold
|
||||||
|
onready var _ui_bonus_gold = $UI / HUD / LifeContainer / UIBonusGold
|
||||||
|
onready var _ui_bonus_gold_pos = $UI / HUD / LifeContainer / UIBonusGold / Position2D
|
||||||
|
onready var _current_wave_label = $UI / HUD / WaveContainer / CurrentWaveLabel
|
||||||
|
onready var _wave_timer_label = $UI / HUD / WaveContainer / WaveTimerLabel
|
||||||
|
onready var _ui_wave_container = $UI / HUD / WaveContainer
|
||||||
|
onready var _ui_upgrades_to_process = $UI / HUD / ThingsToProcessContainer / Upgrades
|
||||||
|
onready var _ui_consumables_to_process = $UI / HUD / ThingsToProcessContainer / Consumables
|
||||||
|
onready var _ui_dim_screen = $UI / DimScreen
|
||||||
|
onready var _tile_map = $TileMap
|
||||||
|
onready var _tile_map_limits = $TileMapLimits
|
||||||
|
onready var _background = $CanvasLayer / Background
|
||||||
|
onready var _harvesting_timer = $HarvestingTimer
|
||||||
|
onready var _challenge_completed_ui = $UI / ChallengeCompletedUI
|
||||||
|
|
||||||
|
onready var _damage_vignette = $UI / DamageVignette
|
||||||
|
onready var _info_popup = $UI / InfoPopup
|
||||||
|
|
||||||
|
onready var game_controller = $"/root/GameController"
|
||||||
|
|
||||||
|
const refresh_time = 1.0 / 100.0
|
||||||
|
var update_timer = refresh_time
|
||||||
|
|
||||||
|
var health_tracker
|
||||||
|
const HealthTracker = preload("res://mods-unpacked/Brogether-Brogether/ui/health_tracker/health_tracker.tscn")
|
||||||
|
|
||||||
|
|
||||||
|
func _physics_process(delta:float)->void :
|
||||||
|
update_timer -= delta
|
||||||
|
if update_timer <= 0 and not _cleaning_up:
|
||||||
|
send_player_position()
|
||||||
|
update_timer = refresh_time
|
||||||
|
|
||||||
|
func send_player_position():
|
||||||
|
game_controller.send_client_position()
|
||||||
|
|
||||||
|
func _ready()->void :
|
||||||
|
_convert_stats_half_wave_proced = false
|
||||||
|
|
||||||
|
_background.texture.gradient.colors[1] = RunData.get_background_gradient_color()
|
||||||
|
_tile_map.tile_set.tile_set_texture(0, RunData.get_background().tiles_sprite)
|
||||||
|
_tile_map.outline.modulate = RunData.get_background().outline_color
|
||||||
|
|
||||||
|
TempStats.reset()
|
||||||
|
|
||||||
|
var current_zone = ZoneService.get_zone_data(RunData.current_zone).duplicate()
|
||||||
|
var current_wave_data = ZoneService.get_wave_data(RunData.current_zone, RunData.current_wave)
|
||||||
|
|
||||||
|
var map_size_coef = (1 + (RunData.effects["map_size"] / 100.0))
|
||||||
|
|
||||||
|
current_zone.width = max(MIN_MAP_SIZE, (current_zone.width * map_size_coef)) as int
|
||||||
|
current_zone.height = max(MIN_MAP_SIZE, (current_zone.height * map_size_coef)) as int
|
||||||
|
|
||||||
|
_tile_map.init(current_zone)
|
||||||
|
_tile_map_limits.init(current_zone)
|
||||||
|
|
||||||
|
ZoneService.current_zone_max_position = Vector2(current_zone.width * Utils.TILE_SIZE, current_zone.height * Utils.TILE_SIZE)
|
||||||
|
|
||||||
|
_current_wave_label.text = Text.text("WAVE", [str(RunData.current_wave)]).to_upper()
|
||||||
|
|
||||||
|
# _wave_timer.wait_time = 15
|
||||||
|
_wave_timer.wait_time = 1 if RunData.instant_waves else current_wave_data.wave_duration
|
||||||
|
_wave_timer.start()
|
||||||
|
_wave_timer_label.wave_timer = _wave_timer
|
||||||
|
var _error_wave_timer = _wave_timer.connect("tick_started", self, "on_tick_started")
|
||||||
|
|
||||||
|
_wave_manager.init(_wave_timer, current_wave_data)
|
||||||
|
|
||||||
|
on_bonus_gold_changed(RunData.bonus_gold)
|
||||||
|
|
||||||
|
init_camera()
|
||||||
|
set_level_label()
|
||||||
|
_ui_dim_screen.color.a = 0
|
||||||
|
|
||||||
|
DebugService.log_run_info()
|
||||||
|
RunData.reset_weapons_dmg_dealt()
|
||||||
|
RunData.reset_cache()
|
||||||
|
|
||||||
|
game_controller = $"/root/GameController"
|
||||||
|
|
||||||
|
health_tracker = HealthTracker.instance()
|
||||||
|
health_tracker.set_name("HealthTracker")
|
||||||
|
$UI.add_child(health_tracker)
|
||||||
|
health_tracker.init(game_controller.tracked_players)
|
||||||
|
|
||||||
|
var run_data = game_controller.tracked_players[game_controller.self_peer_id].run_data
|
||||||
|
var current_level = run_data.current_level
|
||||||
|
var current_xp = run_data.current_xp
|
||||||
|
var next_level_xp = RunData.get_xp_needed(current_level + 1)
|
||||||
|
_xp_bar.update_value(current_xp, next_level_xp)
|
||||||
|
|
||||||
|
var _error_gold_ui = RunData.connect("gold_changed", _ui_gold, "on_gold_changed")
|
||||||
|
|
||||||
|
var _error_upg_select = _upgrades_ui.connect("upgrade_selected", self, "on_upgrade_selected")
|
||||||
|
var _error_consumable_added = connect("consumable_to_process_added", _ui_consumables_to_process, "add_element")
|
||||||
|
|
||||||
|
var _error_take_button = _item_box_ui.connect("item_take_button_pressed", self, "on_item_box_take_button_pressed")
|
||||||
|
var _error_discard_button = _item_box_ui.connect("item_discard_button_pressed", self, "on_item_box_discard_button_pressed")
|
||||||
|
|
||||||
|
game_controller.send_client_started()
|
||||||
|
game_controller.send_client_started()
|
||||||
|
for player_id in game_controller.tracked_players:
|
||||||
|
game_controller.tracked_players[player_id].erase("player")
|
||||||
|
|
||||||
|
func _input(event:InputEvent)->void :
|
||||||
|
var is_right_stick_motion = event is InputEventJoypadMotion and (event.axis == JOY_AXIS_2 or event.axis == JOY_AXIS_3) and abs(event.axis_value) > 0.5
|
||||||
|
var is_mouse_press = event is InputEventMouseButton
|
||||||
|
|
||||||
|
if (is_mouse_press or is_right_stick_motion) and not _cleaning_up:
|
||||||
|
if ProgressData.settings.manual_aim_on_mouse_press and not ProgressData.settings.manual_aim:
|
||||||
|
ProgressData.update_mouse_cursor()
|
||||||
|
|
||||||
|
if is_mouse_press:
|
||||||
|
if event.pressed:
|
||||||
|
InputService.hide_mouse = false
|
||||||
|
else :
|
||||||
|
InputService.hide_mouse = true
|
||||||
|
else :
|
||||||
|
InputService.hide_mouse = false
|
||||||
|
|
||||||
|
if InputService.using_gamepad and not InputService.hide_mouse and not ProgressData.is_manual_aim():
|
||||||
|
InputService.hide_mouse = true
|
||||||
|
|
||||||
|
|
||||||
|
func add_timer(cooldown:int)->Timer:
|
||||||
|
var timer = Timer.new()
|
||||||
|
timer.wait_time = cooldown
|
||||||
|
add_child(timer)
|
||||||
|
timer.start()
|
||||||
|
return timer
|
||||||
|
|
||||||
|
func on_stat_updated(_stat_name:String, _value:int, _db_mod:float = 0.0)->void :
|
||||||
|
reload_stats()
|
||||||
|
|
||||||
|
func reload_stats()->void :
|
||||||
|
_player.update_player_stats()
|
||||||
|
|
||||||
|
LinkedStats.reset()
|
||||||
|
|
||||||
|
for weapon in _player.current_weapons:
|
||||||
|
if is_instance_valid(weapon):
|
||||||
|
weapon.init_stats(false)
|
||||||
|
|
||||||
|
_proj_on_death_stat_cache.clear()
|
||||||
|
|
||||||
|
func on_tick_started()->void :
|
||||||
|
_wave_timer_label.modulate = Color.red
|
||||||
|
|
||||||
|
|
||||||
|
func on_bonus_gold_changed(value:int)->void :
|
||||||
|
if value == 0:
|
||||||
|
_ui_bonus_gold.hide()
|
||||||
|
|
||||||
|
|
||||||
|
func init_camera()->void :
|
||||||
|
var max_pos = ZoneService.current_zone_max_position
|
||||||
|
var min_pos = ZoneService.current_zone_min_position
|
||||||
|
|
||||||
|
var zone_w = max_pos.x - min_pos.x
|
||||||
|
var zone_h = max_pos.y - min_pos.y
|
||||||
|
|
||||||
|
_camera.center_horizontal_pos = zone_w / 2
|
||||||
|
_camera.center_vertical_pos = zone_h / 2
|
||||||
|
|
||||||
|
if zone_w + EDGE_SIZE * 2 <= Utils.project_width:
|
||||||
|
_camera.center_horizontal = true
|
||||||
|
else :
|
||||||
|
_camera.limit_right = max_pos.x + EDGE_SIZE
|
||||||
|
_camera.limit_left = min_pos.x - EDGE_SIZE
|
||||||
|
|
||||||
|
if zone_h + EDGE_SIZE * 2 <= Utils.project_height:
|
||||||
|
_camera.center_vertical = true
|
||||||
|
else :
|
||||||
|
_camera.limit_bottom = max_pos.y + EDGE_SIZE
|
||||||
|
_camera.limit_top = min_pos.y - EDGE_SIZE * 2
|
||||||
|
|
||||||
|
func _on_player_died(_p_player:Player)->void :
|
||||||
|
_player_life_bar.hide()
|
||||||
|
|
||||||
|
if RunData.current_wave <= RunData.nb_of_waves:
|
||||||
|
_is_run_lost = true
|
||||||
|
else :
|
||||||
|
_is_run_won = true
|
||||||
|
clean_up_room(false, _is_run_lost, _is_run_won)
|
||||||
|
_end_wave_timer.start()
|
||||||
|
ProgressData.reset_run_state()
|
||||||
|
ChallengeService.complete_challenge("chal_rookie")
|
||||||
|
|
||||||
|
func on_levelled_up()->void :
|
||||||
|
SoundManager.play(level_up_sound, 0, 0, true)
|
||||||
|
var level = RunData.current_level
|
||||||
|
emit_signal("upgrade_to_process_added", ItemService.upgrade_to_process_icon, level)
|
||||||
|
_upgrades_to_process.push_back(level)
|
||||||
|
set_level_label()
|
||||||
|
RunData.add_stat("stat_max_hp", 1)
|
||||||
|
RunData.emit_signal("healing_effect", 1)
|
||||||
|
|
||||||
|
func set_level_label()->void :
|
||||||
|
_level_label.text = "LV." + str(RunData.current_level)
|
||||||
|
|
||||||
|
func set_life_label(current_health:int, max_health:int)->void :
|
||||||
|
_life_label.text = str(max(current_health, 0.0)) + " / " + str(max_health)
|
||||||
|
|
||||||
|
func connect_visual_effects(unit:Unit)->void :
|
||||||
|
var _error_effects = unit.connect("took_damage", _effects_manager, "_on_unit_took_damage")
|
||||||
|
var _error_floating_text = unit.connect("took_damage", _floating_text_manager, "_on_unit_took_damage")
|
||||||
|
|
||||||
|
func clean_up_room(is_last_wave:bool = false, is_run_lost:bool = false, is_run_won:bool = false)->void :
|
||||||
|
|
||||||
|
if is_run_lost:
|
||||||
|
DebugService.log_data("is_run_lost")
|
||||||
|
_wave_timer_label.is_run_lost = true
|
||||||
|
_wave_timer.stop()
|
||||||
|
_wave_timer.tick_timer.stop()
|
||||||
|
_end_wave_timer.wait_time = 2.5
|
||||||
|
SoundManager.play(Utils.get_rand_element(run_lost_sounds), - 5, 0, true)
|
||||||
|
_ui_dim_screen.dim()
|
||||||
|
MusicManager.tween( - 20)
|
||||||
|
elif is_run_won:
|
||||||
|
DebugService.log_data("is_run_won")
|
||||||
|
apply_run_won()
|
||||||
|
|
||||||
|
if RunData.is_endless_run:
|
||||||
|
|
||||||
|
if RunData.current_wave % 10 == 0 and RunData.current_wave >= 20:
|
||||||
|
RunData.init_elites_spawn(RunData.current_wave, 0.0)
|
||||||
|
|
||||||
|
DebugService.log_data("is_endless_run")
|
||||||
|
|
||||||
|
if RunData.current_wave >= 20:
|
||||||
|
var character_difficulty = ProgressData.get_character_difficulty_info(RunData.current_character.my_id, RunData.current_zone)
|
||||||
|
|
||||||
|
character_difficulty.max_endless_wave_beaten.set_info(
|
||||||
|
RunData.get_current_difficulty(),
|
||||||
|
RunData.current_wave,
|
||||||
|
RunData.current_run_accessibility_settings.health,
|
||||||
|
RunData.current_run_accessibility_settings.damage,
|
||||||
|
RunData.current_run_accessibility_settings.speed,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
|
||||||
|
# TODO maybe replace
|
||||||
|
# SoundManager.play(Utils.get_rand_element(end_wave_sounds))
|
||||||
|
_cleaning_up = true
|
||||||
|
_effects_manager.clean_up_room()
|
||||||
|
_floating_text_manager.clean_up_room()
|
||||||
|
|
||||||
|
for entity in _entities_container.get_children():
|
||||||
|
if not is_instance_valid(entity):
|
||||||
|
continue
|
||||||
|
if entity.get("_boost_zone") and is_instance_valid(entity._boost_zone):
|
||||||
|
continue
|
||||||
|
if not entity is EntityBirth and not entity is Player:
|
||||||
|
entity.die()
|
||||||
|
|
||||||
|
if entity.has_node("MovementBehavior"):
|
||||||
|
var movemenent_node = entity.get_node("MovementBehavior")
|
||||||
|
entity.remove_child(movemenent_node)
|
||||||
|
|
||||||
|
movemenent_node = ClientMovementBehavior.new()
|
||||||
|
movemenent_node.set_name("MovementBehavior")
|
||||||
|
entity.add_child(movemenent_node)
|
||||||
|
|
||||||
|
_entities_container.remove_child(entity)
|
||||||
|
|
||||||
|
health_tracker.hide()
|
||||||
|
_wave_cleared_label.hide()
|
||||||
|
_wave_timer_label.hide()
|
||||||
|
|
||||||
|
_wave_manager.clean_up_room()
|
||||||
|
|
||||||
|
if is_instance_valid(_player):
|
||||||
|
var movemenent_node = _player.get_node("MovementBehavior")
|
||||||
|
_player.remove_child(movemenent_node)
|
||||||
|
|
||||||
|
_player.clean_up()
|
||||||
|
|
||||||
|
DebugService.log_data("start wave_cleared_label...")
|
||||||
|
_wave_cleared_label.start(is_last_wave, is_run_lost, is_run_won)
|
||||||
|
DebugService.log_data("wave_cleared_label started...")
|
||||||
|
|
||||||
|
func get_gold_bag_pos()->Vector2:
|
||||||
|
return get_viewport().get_canvas_transform().affine_inverse().xform(_ui_bonus_gold_pos.global_position)
|
||||||
|
|
||||||
|
func on_focus_lost()->void :
|
||||||
|
if _end_wave_timer_timedout:
|
||||||
|
if _item_box_ui.visible:
|
||||||
|
_item_box_ui.focus()
|
||||||
|
elif _upgrades_ui.visible:
|
||||||
|
_upgrades_ui.focus()
|
||||||
|
|
||||||
|
func on_upgrade_selected(upgrade_data:UpgradeData)->void :
|
||||||
|
game_controller.on_upgrade_selected(upgrade_data)
|
||||||
|
|
||||||
|
func on_item_box_take_button_pressed(item_data:ItemParentData)->void :
|
||||||
|
game_controller.on_item_box_take_button_pressed(item_data)
|
||||||
|
|
||||||
|
func on_item_box_discard_button_pressed(item_data:ItemParentData) -> void:
|
||||||
|
game_controller.discard_item_box(item_data)
|
||||||
|
|
||||||
|
func _on_PauseMenu_paused()->void :
|
||||||
|
reload_stats()
|
||||||
|
|
||||||
|
func _on_PauseMenu_unpaused()->void :
|
||||||
|
on_focus_lost()
|
||||||
|
|
||||||
|
func apply_run_won()->void :
|
||||||
|
_wave_timer.stop()
|
||||||
|
_wave_timer.tick_timer.stop()
|
||||||
|
_end_wave_timer.wait_time = 3
|
||||||
|
_ui_dim_screen.dim()
|
||||||
|
SoundManager.play(Utils.get_rand_element(run_won_sounds), - 5, 0, true)
|
||||||
|
|
||||||
|
var character_chal_name = "chal_" + RunData.current_character.name.to_lower().replace("character_", "")
|
||||||
|
ChallengeService.complete_challenge(character_chal_name)
|
||||||
|
|
||||||
|
var character_difficulty = ProgressData.get_character_difficulty_info(RunData.current_character.my_id, RunData.current_zone)
|
||||||
|
|
||||||
|
if character_difficulty.max_selectable_difficulty < RunData.get_current_difficulty() + 1 and RunData.get_current_difficulty() + 1 <= ProgressData.MAX_DIFFICULTY:
|
||||||
|
RunData.difficulty_unlocked = RunData.get_current_difficulty() + 1
|
||||||
|
|
||||||
|
ChallengeService.complete_challenge("chal_difficulty_" + str(RunData.get_current_difficulty()))
|
||||||
|
|
||||||
|
for char_diff in ProgressData.difficulties_unlocked:
|
||||||
|
for zone_difficulty_info in char_diff.zones_difficulty_info:
|
||||||
|
zone_difficulty_info.max_selectable_difficulty = clamp(RunData.get_current_difficulty() + 1, zone_difficulty_info.max_selectable_difficulty, ProgressData.MAX_DIFFICULTY)
|
||||||
|
|
||||||
|
character_difficulty.max_difficulty_beaten.set_info(
|
||||||
|
RunData.get_current_difficulty(),
|
||||||
|
RunData.current_wave,
|
||||||
|
RunData.current_run_accessibility_settings.health,
|
||||||
|
RunData.current_run_accessibility_settings.damage,
|
||||||
|
RunData.current_run_accessibility_settings.speed,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
|
||||||
|
ProgressData.reset_run_state()
|
||||||
|
|
||||||
|
func is_last_wave()->bool:
|
||||||
|
var is_last_wave = RunData.current_wave == ZoneService.get_zone_data(RunData.current_zone).waves_data.size()
|
||||||
|
if RunData.is_endless_run:is_last_wave = false
|
||||||
|
return is_last_wave
|
||||||
|
|
||||||
|
func manage_harvesting()->void :
|
||||||
|
pass
|
||||||
|
|
||||||
|
func _on_UIBonusGold_mouse_entered()->void :
|
||||||
|
if _cleaning_up:
|
||||||
|
_info_popup.display(_ui_bonus_gold, Text.text("INFO_BONUS_GOLD", [str(RunData.bonus_gold)]))
|
||||||
|
|
||||||
|
|
||||||
|
func _on_UIBonusGold_mouse_exited()->void :
|
||||||
|
_info_popup.hide()
|
||||||
|
|
||||||
|
func _on_HarvestingTimer_timeout()->void :
|
||||||
|
if RunData.current_wave > RunData.nb_of_waves:
|
||||||
|
var val = ceil(Utils.get_stat("stat_harvesting") * (RunData.ENDLESS_HARVESTING_DECREASE / 100.0))
|
||||||
|
RunData.remove_stat("stat_harvesting", val)
|
||||||
|
else :
|
||||||
|
var val = ceil(Utils.get_stat("stat_harvesting") * (RunData.effects["harvesting_growth"] / 100.0))
|
||||||
|
|
||||||
|
var has_crown = false
|
||||||
|
var crown_value = 0
|
||||||
|
|
||||||
|
for item in RunData.items:
|
||||||
|
if item.my_id == "item_crown":
|
||||||
|
has_crown = true
|
||||||
|
crown_value = item.effects[0].value
|
||||||
|
break
|
||||||
|
|
||||||
|
if has_crown:
|
||||||
|
RunData.tracked_item_effects["item_crown"] += (Utils.get_stat("stat_harvesting") * (crown_value / 100.0)) as int
|
||||||
|
|
||||||
|
if val > 0:
|
||||||
|
RunData.add_stat("stat_harvesting", val)
|
||||||
|
|
||||||
|
func on_gold_changed(gold:int)->void :
|
||||||
|
if _update_stats_on_gold_changed:
|
||||||
|
if (gold / 30.0) as int != _last_gold_amount_used_to_reload_stats:
|
||||||
|
reload_stats()
|
||||||
|
_last_gold_amount_used_to_reload_stats = (gold / 30.0) as int
|
||||||
|
|
||||||
|
|
||||||
|
func _on_WaveTimer_timeout() -> void:
|
||||||
|
clean_up_room(false, false, false)
|
||||||
|
|
||||||
|
func _on_EndWaveTimer_timeout() -> void:
|
||||||
|
game_controller.send_complete_player_request()
|
||||||
|
yield(game_controller, "complete_player_update")
|
||||||
|
|
||||||
|
if _is_run_won:
|
||||||
|
apply_run_won()
|
||||||
|
RunData.run_won = true
|
||||||
|
var _error = get_tree().change_scene("res://ui/menus/run/end_run.tscn")
|
||||||
|
return
|
||||||
|
|
||||||
|
InputService.hide_mouse = true
|
||||||
|
|
||||||
|
var consumables = game_controller.tracked_players[game_controller.self_peer_id].consumables_to_process
|
||||||
|
if consumables.size() > 0:
|
||||||
|
for consumable in consumables:
|
||||||
|
var fixed_tier = - 1
|
||||||
|
|
||||||
|
if consumable.my_id == "consumable_legendary_item_box":
|
||||||
|
fixed_tier = Tier.LEGENDARY
|
||||||
|
|
||||||
|
var item_data = ItemService.process_item_box(RunData.current_wave, consumable, fixed_tier)
|
||||||
|
_item_box_ui.set_item_data(item_data)
|
||||||
|
yield (_item_box_ui, "item_box_processed")
|
||||||
|
|
||||||
|
game_controller.send_complete_player_request()
|
||||||
|
yield(game_controller, "complete_player_update")
|
||||||
|
|
||||||
|
_ui_consumables_to_process.remove_element(consumable)
|
||||||
|
game_controller.tracked_players[game_controller.self_peer_id].consumables_to_process = []
|
||||||
|
|
||||||
|
if _upgrades_to_process.size() > 0:
|
||||||
|
for upgrade_to_process in _upgrades_to_process:
|
||||||
|
_upgrades_ui.show_upgrade_options(upgrade_to_process)
|
||||||
|
yield (_upgrades_ui, "upgrade_selected")
|
||||||
|
|
||||||
|
game_controller.send_complete_player_request()
|
||||||
|
yield(game_controller, "complete_player_update")
|
||||||
|
|
||||||
|
_ui_upgrades_to_process.remove_element(upgrade_to_process)
|
||||||
|
|
||||||
|
var _error = get_tree().change_scene("res://mods-unpacked/Brogether-Brogether/ui/shop/multiplayer_shop.tscn")
|
||||||
460
src/mods-unpacked/Brogether-Brogether/client/client_main.tscn
Normal file
460
src/mods-unpacked/Brogether-Brogether/client/client_main.tscn
Normal file
@@ -0,0 +1,460 @@
|
|||||||
|
[gd_scene load_steps=81 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://particles/heal_particles.tscn" type="PackedScene" id=1]
|
||||||
|
[ext_resource path="res://particles/directional_hit_particles.tscn" type="PackedScene" id=2]
|
||||||
|
[ext_resource path="res://visual_effects/floating_text/floating_text.tscn" type="PackedScene" id=3]
|
||||||
|
[ext_resource path="res://visual_effects/hit_effect/hit_effect.tscn" type="PackedScene" id=4]
|
||||||
|
[ext_resource path="res://particles/pickup_gold_particles.tscn" type="PackedScene" id=5]
|
||||||
|
[ext_resource path="res://particles/stats_boost_particles.tscn" type="PackedScene" id=6]
|
||||||
|
[ext_resource path="res://ui/hud/ui_upgrade_to_process_element.tscn" type="PackedScene" id=7]
|
||||||
|
[ext_resource path="res://particles/speed_removed_particles.tscn" type="PackedScene" id=8]
|
||||||
|
[ext_resource path="res://particles/hit_particles.tscn" type="PackedScene" id=9]
|
||||||
|
[ext_resource path="res://resources/themes/base_theme.tres" type="Theme" id=11]
|
||||||
|
[ext_resource path="res://weapons/melee/dagger/dagger_icon.png" type="Texture" id=12]
|
||||||
|
[ext_resource path="res://ui/hud/ui_progress_bar.tscn" type="PackedScene" id=13]
|
||||||
|
[ext_resource path="res://items/materials/harvesting_icon.png" type="Texture" id=14]
|
||||||
|
[ext_resource path="res://ui/hud/ui_wave_timer.gd" type="Script" id=15]
|
||||||
|
[ext_resource path="res://zones/zone_1/000_all/group_2.tres" type="Resource" id=16]
|
||||||
|
[ext_resource path="res://zones/zone_1/000_elites/group_1.tres" type="Resource" id=17]
|
||||||
|
[ext_resource path="res://zones/zone_1/000_hordes/group_1.tres" type="Resource" id=18]
|
||||||
|
[ext_resource path="res://zones/zone_1/000_hordes/group_3.tres" type="Resource" id=19]
|
||||||
|
[ext_resource path="res://zones/zone_1/000_all/group_1.tres" type="Resource" id=20]
|
||||||
|
[ext_resource path="res://zones/zone_1/000_hordes/group_2.tres" type="Resource" id=21]
|
||||||
|
[ext_resource path="res://zones/zone_1/000_extra/group_1.tres" type="Resource" id=22]
|
||||||
|
[ext_resource path="res://zones/zone_1/000_hordes/group_4.tres" type="Resource" id=23]
|
||||||
|
[ext_resource path="res://zones/zone_1/000_hordes/group_5.tres" type="Resource" id=24]
|
||||||
|
[ext_resource path="res://items/materials/alt_sounds/coin_bag_ring_gemstone_item_03.wav" type="AudioStream" id=28]
|
||||||
|
[ext_resource path="res://resources/sounds/harvest/cartoon_boing_jump_01.wav" type="AudioStream" id=29]
|
||||||
|
[ext_resource path="res://resources/sounds/Madness 10.mp3" type="AudioStream" id=30]
|
||||||
|
[ext_resource path="res://resources/sounds/Madness 9.mp3" type="AudioStream" id=31]
|
||||||
|
[ext_resource path="res://resources/sounds/Madness 7.mp3" type="AudioStream" id=32]
|
||||||
|
[ext_resource path="res://resources/sounds/Madness 3.mp3" type="AudioStream" id=33]
|
||||||
|
[ext_resource path="res://resources/sounds/harvest/cartoon_boing_jump_07.wav" type="AudioStream" id=34]
|
||||||
|
[ext_resource path="res://resources/sounds/harvest/cartoon_boing_jump_09.wav" type="AudioStream" id=35]
|
||||||
|
[ext_resource path="res://resources/sounds/harvest/cartoon_boing_jump_06.wav" type="AudioStream" id=36]
|
||||||
|
[ext_resource path="res://ui/hud/ui_consumable_to_process_list.gd" type="Script" id=37]
|
||||||
|
[ext_resource path="res://global/my_tile_map_limits.gd" type="Script" id=38]
|
||||||
|
[ext_resource path="res://zones/backgrounds/background_gradient.tres" type="Gradient" id=39]
|
||||||
|
[ext_resource path="res://resources/tiles/ground_tiles.tres" type="TileSet" id=40]
|
||||||
|
[ext_resource path="res://global/my_camera.gd" type="Script" id=41]
|
||||||
|
[ext_resource path="res://resources/sounds/Madness 1.mp3" type="AudioStream" id=42]
|
||||||
|
[ext_resource path="res://items/materials/alt_sounds/coin_bag_ring_gemstone_item_01.wav" type="AudioStream" id=43]
|
||||||
|
[ext_resource path="res://resources/sounds/level_up.wav" type="AudioStream" id=44]
|
||||||
|
[ext_resource path="res://resources/sounds/Madness 8.mp3" type="AudioStream" id=45]
|
||||||
|
[ext_resource path="res://items/materials/water_drop_drip_single_02.wav" type="AudioStream" id=46]
|
||||||
|
[ext_resource path="res://items/materials/alt_sounds/coin_bag_ring_gemstone_item_05.wav" type="AudioStream" id=47]
|
||||||
|
[ext_resource path="res://resources/sounds/Madness 6.mp3" type="AudioStream" id=48]
|
||||||
|
[ext_resource path="res://items/materials/alt_sounds/coin_bag_ring_gemstone_item_02.wav" type="AudioStream" id=49]
|
||||||
|
[ext_resource path="res://items/materials/water_drop_drip_single_04.wav" type="AudioStream" id=50]
|
||||||
|
[ext_resource path="res://ui/sounds/end_wave.wav" type="AudioStream" id=51]
|
||||||
|
[ext_resource path="res://items/materials/water_drop_drip_single_05.wav" type="AudioStream" id=52]
|
||||||
|
[ext_resource path="res://resources/sounds/Madness 4.mp3" type="AudioStream" id=53]
|
||||||
|
[ext_resource path="res://items/materials/water_drop_drip_single_01.wav" type="AudioStream" id=54]
|
||||||
|
[ext_resource path="res://ui/sounds/CGM3_Bubble_Button_01_4.wav" type="AudioStream" id=55]
|
||||||
|
[ext_resource path="res://resources/sounds/Fear 10.mp3" type="AudioStream" id=56]
|
||||||
|
[ext_resource path="res://resources/tiles/tiles_outline.png" type="Texture" id=57]
|
||||||
|
[ext_resource path="res://items/materials/alt_sounds/coin_bag_ring_gemstone_item_04.wav" type="AudioStream" id=58]
|
||||||
|
[ext_resource path="res://items/materials/water_drop_drip_single_03.wav" type="AudioStream" id=59]
|
||||||
|
[ext_resource path="res://ui/sounds/clock_tick_01.wav" type="AudioStream" id=60]
|
||||||
|
[ext_resource path="res://resources/sounds/Madness 2.mp3" type="AudioStream" id=61]
|
||||||
|
[ext_resource path="res://ui/sounds/CGM3_Bubble_Button_01_3.wav" type="AudioStream" id=62]
|
||||||
|
[ext_resource path="res://global/screenshaker.gd" type="Script" id=63]
|
||||||
|
[ext_resource path="res://mods-unpacked/Brogether-Brogether/client/client_main.gd" type="Script" id=64]
|
||||||
|
[ext_resource path="res://visual_effects/damage_vignette.gd" type="Script" id=65]
|
||||||
|
[ext_resource path="res://ui/hud/ui_dim_screen.gd" type="Script" id=67]
|
||||||
|
[ext_resource path="res://ui/hud/ui_upgrade_to_process_list.gd" type="Script" id=68]
|
||||||
|
[ext_resource path="res://global/effects_manager.gd" type="Script" id=69]
|
||||||
|
[ext_resource path="res://global/my_tile_map.gd" type="Script" id=70]
|
||||||
|
[ext_resource path="res://ui/hud/wave_timer.gd" type="Script" id=71]
|
||||||
|
[ext_resource path="res://zones/wave_manager.gd" type="Script" id=72]
|
||||||
|
[ext_resource path="res://visual_effects/floating_text/floating_text_manager.gd" type="Script" id=73]
|
||||||
|
[ext_resource path="res://ui/menus/ingame/wave_cleared_label.gd" type="Script" id=74]
|
||||||
|
[ext_resource path="res://ui/hud/ui_bonus_gold.tscn" type="PackedScene" id=75]
|
||||||
|
[ext_resource path="res://ui/hud/ui_item_list.tscn" type="PackedScene" id=76]
|
||||||
|
[ext_resource path="res://ui/hud/ui_gold.tscn" type="PackedScene" id=77]
|
||||||
|
[ext_resource path="res://ui/menus/ingame/pause_menu.tscn" type="PackedScene" id=78]
|
||||||
|
[ext_resource path="res://ui/menus/ingame/upgrades_ui.tscn" type="PackedScene" id=79]
|
||||||
|
[ext_resource path="res://ui/menus/ingame/challenge_completed_ui.tscn" type="PackedScene" id=80]
|
||||||
|
[ext_resource path="res://ui/menus/ingame/info_popup.tscn" type="PackedScene" id=81]
|
||||||
|
[ext_resource path="res://ui/menus/upgrades/item_box_ui.tscn" type="PackedScene" id=82]
|
||||||
|
|
||||||
|
[sub_resource type="GradientTexture" id=3]
|
||||||
|
gradient = ExtResource( 39 )
|
||||||
|
width = 1920
|
||||||
|
|
||||||
|
[sub_resource type="Shader" id=10]
|
||||||
|
code = "shader_type canvas_item;
|
||||||
|
|
||||||
|
uniform vec4 color: hint_color;
|
||||||
|
uniform float multiplier = 0.2;
|
||||||
|
uniform float softness = 0.2;
|
||||||
|
|
||||||
|
void fragment() {
|
||||||
|
float value = distance(UV, vec2(0.5));
|
||||||
|
COLOR = vec4(color.rgb, smoothstep(multiplier, softness, value));
|
||||||
|
}"
|
||||||
|
|
||||||
|
[sub_resource type="ShaderMaterial" id=11]
|
||||||
|
shader = SubResource( 10 )
|
||||||
|
shader_param/color = Color( 0, 0, 0, 1 )
|
||||||
|
shader_param/multiplier = 0.8
|
||||||
|
shader_param/softness = 0.8
|
||||||
|
|
||||||
|
[node name="ClientMain" type="Node"]
|
||||||
|
script = ExtResource( 64 )
|
||||||
|
gold_pickup_sounds = [ ExtResource( 54 ), ExtResource( 46 ), ExtResource( 59 ), ExtResource( 50 ), ExtResource( 52 ) ]
|
||||||
|
gold_alt_pickup_sounds = [ ExtResource( 43 ), ExtResource( 49 ), ExtResource( 28 ), ExtResource( 58 ), ExtResource( 47 ) ]
|
||||||
|
level_up_sound = ExtResource( 44 )
|
||||||
|
run_won_sounds = [ ExtResource( 56 ) ]
|
||||||
|
run_lost_sounds = [ ExtResource( 42 ), ExtResource( 61 ), ExtResource( 33 ), ExtResource( 53 ), ExtResource( 48 ), ExtResource( 32 ), ExtResource( 45 ), ExtResource( 31 ), ExtResource( 30 ) ]
|
||||||
|
end_wave_sounds = [ ExtResource( 51 ) ]
|
||||||
|
|
||||||
|
[node name="CanvasLayer" type="CanvasLayer" parent="."]
|
||||||
|
layer = -10
|
||||||
|
|
||||||
|
[node name="Background" type="TextureRect" parent="CanvasLayer"]
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
margin_left = 1920.0
|
||||||
|
margin_right = 1080.0
|
||||||
|
margin_bottom = 840.0
|
||||||
|
rect_rotation = 89.9906
|
||||||
|
texture = SubResource( 3 )
|
||||||
|
expand = true
|
||||||
|
|
||||||
|
[node name="WaveManager" type="Node2D" parent="."]
|
||||||
|
script = ExtResource( 72 )
|
||||||
|
extra_groups = [ ExtResource( 22 ) ]
|
||||||
|
groups_data_in_all_waves = [ ExtResource( 20 ), ExtResource( 16 ) ]
|
||||||
|
horde_groups = [ ExtResource( 18 ), ExtResource( 21 ), ExtResource( 19 ), ExtResource( 23 ), ExtResource( 24 ) ]
|
||||||
|
elite_group = ExtResource( 17 )
|
||||||
|
|
||||||
|
[node name="EffectsManager" type="Node2D" parent="."]
|
||||||
|
script = ExtResource( 69 )
|
||||||
|
heal_particles = ExtResource( 1 )
|
||||||
|
stats_boost_particles = ExtResource( 6 )
|
||||||
|
speed_removed_particles = ExtResource( 8 )
|
||||||
|
hit_particles = ExtResource( 9 )
|
||||||
|
directional_hit_particles = ExtResource( 2 )
|
||||||
|
hit_effect = ExtResource( 4 )
|
||||||
|
gold_pickup_particles = ExtResource( 5 )
|
||||||
|
|
||||||
|
[node name="FloatingTextManager" type="Node2D" parent="."]
|
||||||
|
script = ExtResource( 73 )
|
||||||
|
_floating_text = ExtResource( 3 )
|
||||||
|
gold_on_crit_kill_icon = ExtResource( 12 )
|
||||||
|
harvesting_icon = ExtResource( 14 )
|
||||||
|
stat_pos_sounds = [ ExtResource( 35 ) ]
|
||||||
|
stat_neg_sounds = [ ExtResource( 34 ) ]
|
||||||
|
harvest_pos_sounds = [ ExtResource( 29 ) ]
|
||||||
|
harvest_neg_sounds = [ ExtResource( 36 ) ]
|
||||||
|
|
||||||
|
[node name="Camera" type="Camera2D" parent="."]
|
||||||
|
current = true
|
||||||
|
script = ExtResource( 41 )
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_lock_": true
|
||||||
|
}
|
||||||
|
|
||||||
|
[node name="Screenshaker" type="Node" parent="Camera"]
|
||||||
|
script = ExtResource( 63 )
|
||||||
|
|
||||||
|
[node name="TileMap" type="TileMap" parent="."]
|
||||||
|
tile_set = ExtResource( 40 )
|
||||||
|
cell_quadrant_size = 64
|
||||||
|
collision_layer = 128
|
||||||
|
collision_mask = 0
|
||||||
|
format = 1
|
||||||
|
tile_data = PoolIntArray( 7, 0, 65538, 65536, 0, 65538, 65537, 0, 65538 )
|
||||||
|
script = ExtResource( 70 )
|
||||||
|
|
||||||
|
[node name="Outline" type="NinePatchRect" parent="TileMap"]
|
||||||
|
modulate = Color( 0.470588, 0.403922, 0.345098, 1 )
|
||||||
|
show_behind_parent = true
|
||||||
|
margin_left = -64.0
|
||||||
|
margin_top = -64.0
|
||||||
|
margin_right = 640.0
|
||||||
|
margin_bottom = 392.0
|
||||||
|
texture = ExtResource( 57 )
|
||||||
|
patch_margin_left = 64
|
||||||
|
patch_margin_top = 64
|
||||||
|
patch_margin_right = 64
|
||||||
|
patch_margin_bottom = 64
|
||||||
|
axis_stretch_horizontal = 1
|
||||||
|
axis_stretch_vertical = 1
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_lock_": true,
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[node name="TileMapLimits" type="StaticBody2D" parent="."]
|
||||||
|
position = Vector2( -64, -64 )
|
||||||
|
collision_layer = 128
|
||||||
|
collision_mask = 0
|
||||||
|
script = ExtResource( 38 )
|
||||||
|
|
||||||
|
[node name="Items" type="Node2D" parent="."]
|
||||||
|
|
||||||
|
[node name="Consumables" type="Node2D" parent="."]
|
||||||
|
|
||||||
|
[node name="Births" type="Node2D" parent="."]
|
||||||
|
|
||||||
|
[node name="Entities" type="YSort" parent="."]
|
||||||
|
|
||||||
|
[node name="Projectiles" type="Node2D" parent="."]
|
||||||
|
|
||||||
|
[node name="PlayerLifeBarContainer" type="Node2D" parent="."]
|
||||||
|
|
||||||
|
[node name="PlayerLifeBar" parent="PlayerLifeBarContainer" instance=ExtResource( 13 )]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
visible = false
|
||||||
|
margin_left = -32.0
|
||||||
|
margin_top = -72.0
|
||||||
|
margin_right = 32.0
|
||||||
|
margin_bottom = -56.0
|
||||||
|
nine_patch_stretch = true
|
||||||
|
progress_color = Color( 0.721569, 0, 0, 1 )
|
||||||
|
|
||||||
|
[node name="UI" type="CanvasLayer" parent="."]
|
||||||
|
|
||||||
|
[node name="DamageVignette" type="ColorRect" parent="UI"]
|
||||||
|
material = SubResource( 11 )
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
script = ExtResource( 65 )
|
||||||
|
|
||||||
|
[node name="DimScreen" type="ColorRect" parent="UI"]
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
margin_left = 40.0
|
||||||
|
margin_right = 40.0
|
||||||
|
color = Color( 0, 0, 0, 0 )
|
||||||
|
script = ExtResource( 67 )
|
||||||
|
|
||||||
|
[node name="Tween" type="Tween" parent="UI/DimScreen"]
|
||||||
|
|
||||||
|
[node name="WaveClearedLabel" type="Label" parent="UI"]
|
||||||
|
anchor_left = 0.5
|
||||||
|
anchor_right = 0.5
|
||||||
|
margin_left = -958.0
|
||||||
|
margin_right = 960.0
|
||||||
|
margin_bottom = 400.0
|
||||||
|
theme = ExtResource( 11 )
|
||||||
|
text = "WAVE_COMPLETED"
|
||||||
|
align = 1
|
||||||
|
valign = 1
|
||||||
|
uppercase = true
|
||||||
|
script = ExtResource( 74 )
|
||||||
|
font_end_run = ExtResource( 26 )
|
||||||
|
character_appearing_sounds = [ ExtResource( 62 ), ExtResource( 55 ) ]
|
||||||
|
|
||||||
|
[node name="Timer" type="Timer" parent="UI/WaveClearedLabel"]
|
||||||
|
wait_time = 0.1
|
||||||
|
one_shot = true
|
||||||
|
|
||||||
|
[node name="ItemBoxUI" parent="UI" instance=ExtResource( 82 )]
|
||||||
|
visible = false
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
margin_left = 0.0
|
||||||
|
margin_top = 0.0
|
||||||
|
margin_right = 0.0
|
||||||
|
margin_bottom = 0.0
|
||||||
|
|
||||||
|
[node name="UpgradesUI" parent="UI" instance=ExtResource( 79 )]
|
||||||
|
visible = false
|
||||||
|
|
||||||
|
[node name="HUD" type="MarginContainer" parent="UI"]
|
||||||
|
anchor_right = 1.0
|
||||||
|
margin_bottom = 284.0
|
||||||
|
size_flags_horizontal = 0
|
||||||
|
size_flags_vertical = 0
|
||||||
|
custom_constants/margin_right = 24
|
||||||
|
custom_constants/margin_top = 24
|
||||||
|
custom_constants/margin_left = 24
|
||||||
|
custom_constants/margin_bottom = 24
|
||||||
|
|
||||||
|
[node name="LifeContainer" type="VBoxContainer" parent="UI/HUD"]
|
||||||
|
margin_left = 24.0
|
||||||
|
margin_top = 24.0
|
||||||
|
margin_right = 344.0
|
||||||
|
margin_bottom = 260.0
|
||||||
|
size_flags_horizontal = 0
|
||||||
|
size_flags_vertical = 0
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[node name="UILifeBar" parent="UI/HUD/LifeContainer" instance=ExtResource( 13 )]
|
||||||
|
margin_bottom = 48.0
|
||||||
|
size_flags_horizontal = 0
|
||||||
|
tint_progress = Color( 0.721569, 0, 0, 1 )
|
||||||
|
progress_color = Color( 0.721569, 0, 0, 1 )
|
||||||
|
|
||||||
|
[node name="MarginContainer" type="MarginContainer" parent="UI/HUD/LifeContainer/UILifeBar"]
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
custom_constants/margin_right = 12
|
||||||
|
custom_constants/margin_top = 7
|
||||||
|
custom_constants/margin_left = 12
|
||||||
|
custom_constants/margin_bottom = 7
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[node name="LifeLabel" type="Label" parent="UI/HUD/LifeContainer/UILifeBar/MarginContainer"]
|
||||||
|
margin_left = 12.0
|
||||||
|
margin_top = 8.0
|
||||||
|
margin_right = 308.0
|
||||||
|
margin_bottom = 39.0
|
||||||
|
grow_horizontal = 0
|
||||||
|
text = "8 / 8"
|
||||||
|
align = 1
|
||||||
|
valign = 1
|
||||||
|
uppercase = true
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[node name="UIXPBar" parent="UI/HUD/LifeContainer" instance=ExtResource( 13 )]
|
||||||
|
margin_top = 52.0
|
||||||
|
margin_bottom = 100.0
|
||||||
|
size_flags_horizontal = 0
|
||||||
|
value = 50.0
|
||||||
|
|
||||||
|
[node name="MarginContainer" type="MarginContainer" parent="UI/HUD/LifeContainer/UIXPBar"]
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
custom_constants/margin_right = 12
|
||||||
|
custom_constants/margin_top = 7
|
||||||
|
custom_constants/margin_left = 12
|
||||||
|
custom_constants/margin_bottom = 7
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[node name="LevelLabel" type="Label" parent="UI/HUD/LifeContainer/UIXPBar/MarginContainer"]
|
||||||
|
margin_left = 12.0
|
||||||
|
margin_top = 8.0
|
||||||
|
margin_right = 308.0
|
||||||
|
margin_bottom = 39.0
|
||||||
|
grow_horizontal = 0
|
||||||
|
text = "LV. 1"
|
||||||
|
align = 2
|
||||||
|
valign = 1
|
||||||
|
uppercase = true
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[node name="UIGold" parent="UI/HUD/LifeContainer" instance=ExtResource( 77 )]
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_right = 0.0
|
||||||
|
margin_left = 0.0
|
||||||
|
margin_top = 104.0
|
||||||
|
margin_right = 320.0
|
||||||
|
margin_bottom = 168.0
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
alignment = 0
|
||||||
|
|
||||||
|
[node name="UIBonusGold" parent="UI/HUD/LifeContainer" instance=ExtResource( 75 )]
|
||||||
|
margin_top = 172.0
|
||||||
|
margin_bottom = 236.0
|
||||||
|
size_flags_horizontal = 0
|
||||||
|
|
||||||
|
[node name="WaveContainer" type="VBoxContainer" parent="UI/HUD"]
|
||||||
|
margin_left = 873.0
|
||||||
|
margin_top = 24.0
|
||||||
|
margin_right = 1046.0
|
||||||
|
margin_bottom = 146.0
|
||||||
|
size_flags_horizontal = 4
|
||||||
|
size_flags_vertical = 0
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[node name="CurrentWaveLabel" type="Label" parent="UI/HUD/WaveContainer"]
|
||||||
|
margin_right = 173.0
|
||||||
|
margin_bottom = 45.0
|
||||||
|
theme = ExtResource( 11 )
|
||||||
|
text = "WAVE {0}"
|
||||||
|
align = 1
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[node name="WaveTimerLabel" type="Label" parent="UI/HUD/WaveContainer"]
|
||||||
|
margin_top = 49.0
|
||||||
|
margin_right = 173.0
|
||||||
|
margin_bottom = 122.0
|
||||||
|
theme = ExtResource( 11 )
|
||||||
|
text = "60"
|
||||||
|
align = 1
|
||||||
|
script = ExtResource( 15 )
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[node name="ThingsToProcessContainer" type="VBoxContainer" parent="UI/HUD"]
|
||||||
|
margin_left = 1896.0
|
||||||
|
margin_top = 24.0
|
||||||
|
margin_right = 1896.0
|
||||||
|
margin_bottom = 36.0
|
||||||
|
size_flags_horizontal = 8
|
||||||
|
size_flags_vertical = 0
|
||||||
|
custom_constants/separation = 12
|
||||||
|
|
||||||
|
[node name="Upgrades" parent="UI/HUD/ThingsToProcessContainer" instance=ExtResource( 76 )]
|
||||||
|
modulate = Color( 1, 1, 1, 0.501961 )
|
||||||
|
script = ExtResource( 68 )
|
||||||
|
element_scene = ExtResource( 7 )
|
||||||
|
|
||||||
|
[node name="Consumables" parent="UI/HUD/ThingsToProcessContainer" instance=ExtResource( 76 )]
|
||||||
|
modulate = Color( 1, 1, 1, 0.501961 )
|
||||||
|
margin_top = 12.0
|
||||||
|
margin_bottom = 12.0
|
||||||
|
script = ExtResource( 37 )
|
||||||
|
|
||||||
|
[node name="PauseMenu" parent="UI" instance=ExtResource( 78 )]
|
||||||
|
pause_mode = 2
|
||||||
|
visible = false
|
||||||
|
|
||||||
|
[node name="ChallengeCompletedUI" parent="UI" instance=ExtResource( 80 )]
|
||||||
|
visible = false
|
||||||
|
|
||||||
|
[node name="InfoPopup" parent="UI" instance=ExtResource( 81 )]
|
||||||
|
visible = false
|
||||||
|
|
||||||
|
[node name="EndWaveTimer" type="Timer" parent="."]
|
||||||
|
wait_time = 0.75
|
||||||
|
one_shot = true
|
||||||
|
|
||||||
|
[node name="HarvestingTimer" type="Timer" parent="."]
|
||||||
|
wait_time = 0.66
|
||||||
|
one_shot = true
|
||||||
|
|
||||||
|
[node name="WaveTimer" type="Timer" parent="."]
|
||||||
|
one_shot = true
|
||||||
|
script = ExtResource( 71 )
|
||||||
|
tick_sounds = [ ExtResource( 60 ) ]
|
||||||
|
|
||||||
|
[node name="TickTimer" type="Timer" parent="WaveTimer"]
|
||||||
|
|
||||||
|
[node name="CanvasLayer2" type="CanvasLayer" parent="."]
|
||||||
|
|
||||||
|
[connection signal="timeout" from="UI/WaveClearedLabel/Timer" to="UI/WaveClearedLabel" method="_on_Timer_timeout"]
|
||||||
|
[connection signal="mouse_entered" from="UI/HUD/LifeContainer/UIBonusGold" to="." method="_on_UIBonusGold_mouse_entered"]
|
||||||
|
[connection signal="mouse_exited" from="UI/HUD/LifeContainer/UIBonusGold" to="." method="_on_UIBonusGold_mouse_exited"]
|
||||||
|
[connection signal="paused" from="UI/PauseMenu" to="." method="_on_PauseMenu_paused"]
|
||||||
|
[connection signal="unpaused" from="UI/PauseMenu" to="." method="_on_PauseMenu_unpaused"]
|
||||||
|
[connection signal="timeout" from="EndWaveTimer" to="." method="_on_EndWaveTimer_timeout"]
|
||||||
|
[connection signal="timeout" from="HarvestingTimer" to="." method="_on_HarvestingTimer_timeout"]
|
||||||
|
[connection signal="timeout" from="WaveTimer" to="." method="_on_WaveTimer_timeout"]
|
||||||
|
[connection signal="timeout" from="WaveTimer" to="WaveTimer" method="_on_WaveTimer_timeout"]
|
||||||
|
[connection signal="timeout" from="WaveTimer/TickTimer" to="WaveTimer" method="_on_TickTimer_timeout"]
|
||||||
|
|
||||||
|
[editable path="UI/HUD/LifeContainer/UILifeBar"]
|
||||||
|
[editable path="UI/HUD/LifeContainer/UIXPBar"]
|
||||||
|
[editable path="UI/ChallengeCompletedUI"]
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
extends MovementBehavior
|
||||||
|
|
||||||
|
signal detected_player
|
||||||
|
|
||||||
|
func init(parent:Node)->Node:
|
||||||
|
var _init = .init(parent)
|
||||||
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
func get_movement()->Vector2:
|
||||||
|
return Vector2.ZERO
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
extends TargetBehavior
|
||||||
|
|
||||||
|
func update_target():
|
||||||
|
pass
|
||||||
21
src/mods-unpacked/Brogether-Brogether/client/waiting.gd
Normal file
21
src/mods-unpacked/Brogether-Brogether/client/waiting.gd
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
extends Node2D
|
||||||
|
|
||||||
|
onready var message_label = $Message
|
||||||
|
|
||||||
|
# Called when the node enters the scene tree for the first time.
|
||||||
|
func _ready():
|
||||||
|
var messages = []
|
||||||
|
|
||||||
|
messages.push_back("THESE PRETZELS ARE MAKING ME THIRSTY")
|
||||||
|
messages.push_back("support the dev -> get a better screen here")
|
||||||
|
messages.push_back("SERENITY NOW")
|
||||||
|
messages.push_back("(1/3) We must go forward not backward")
|
||||||
|
messages.push_back("(2/3) Upward not forward")
|
||||||
|
messages.push_back("(3/3) And always twirling, twirling, twirling towards freedom")
|
||||||
|
messages.push_back("So you're telling me there's a chance")
|
||||||
|
messages.push_back("Great Success!")
|
||||||
|
messages.push_back("Bueller ... Bueller ... Bueller")
|
||||||
|
messages.push_back("The dude abides")
|
||||||
|
|
||||||
|
|
||||||
|
message_label.text = Utils.get_rand_element(messages)
|
||||||
25
src/mods-unpacked/Brogether-Brogether/client/waiting.tscn
Normal file
25
src/mods-unpacked/Brogether-Brogether/client/waiting.tscn
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
[gd_scene load_steps=3 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://resources/themes/inventory_button_theme.tres" type="Theme" id=1]
|
||||||
|
[ext_resource path="res://mods-unpacked/Brogether-Brogether/client/waiting.gd" type="Script" id=2]
|
||||||
|
|
||||||
|
[node name="Node2D" type="Node2D"]
|
||||||
|
script = ExtResource( 2 )
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="."]
|
||||||
|
margin_left = 2.0
|
||||||
|
margin_top = 6.0
|
||||||
|
margin_right = 1918.0
|
||||||
|
margin_bottom = 192.0
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
theme = ExtResource( 1 )
|
||||||
|
text = "Please wait for the host to shop and resume the game"
|
||||||
|
|
||||||
|
[node name="Message" type="Label" parent="."]
|
||||||
|
margin_left = -1.0
|
||||||
|
margin_top = 285.0
|
||||||
|
margin_right = 1915.0
|
||||||
|
margin_bottom = 471.0
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
theme = ExtResource( 1 )
|
||||||
|
text = "These Pretzels are making me Thirsty!"
|
||||||
3
src/mods-unpacked/Brogether-Brogether/data_node.gd
Normal file
3
src/mods-unpacked/Brogether-Brogether/data_node.gd
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
extends Node
|
||||||
|
|
||||||
|
var data = {}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
extends "res://entities/birth/entity_birth.gd"
|
||||||
|
|
||||||
|
var steam_connection
|
||||||
|
var brotatogether_options
|
||||||
|
var in_multiplayer_game = false
|
||||||
|
var network_id = 0
|
||||||
|
var is_host = false
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
steam_connection = $"/root/SteamConnection"
|
||||||
|
brotatogether_options = $"/root/BrotogetherOptions"
|
||||||
|
in_multiplayer_game = brotatogether_options.in_multiplayer_game
|
||||||
|
|
||||||
|
if in_multiplayer_game:
|
||||||
|
is_host = steam_connection.is_host()
|
||||||
|
network_id = brotatogether_options.current_network_id
|
||||||
|
brotatogether_options.current_network_id = brotatogether_options.current_network_id + 1
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
extends "res://entities/entity.gd"
|
||||||
|
|
||||||
|
var steam_connection
|
||||||
|
var brotatogether_options
|
||||||
|
var in_multiplayer_game = false
|
||||||
|
var network_id = 0
|
||||||
|
var is_host = false
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
steam_connection = $"/root/SteamConnection"
|
||||||
|
brotatogether_options = $"/root/BrotogetherOptions"
|
||||||
|
in_multiplayer_game = brotatogether_options.in_multiplayer_game
|
||||||
|
|
||||||
|
if in_multiplayer_game:
|
||||||
|
is_host = steam_connection.is_host()
|
||||||
|
network_id = brotatogether_options.current_network_id
|
||||||
|
brotatogether_options.current_network_id = brotatogether_options.current_network_id + 1
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
extends "res://entities/structures/turret/turret.gd"
|
||||||
|
|
||||||
|
|
||||||
|
func _on_AnimationPlayer_animation_finished(anim_name: String) -> void :
|
||||||
|
if self.in_multiplayer_game and not self.is_host:
|
||||||
|
return
|
||||||
|
._on_AnimationPlayer_animation_finished(anim_name)
|
||||||
|
|
||||||
|
func shoot() -> void :
|
||||||
|
if self.in_multiplayer_game and not self.is_host:
|
||||||
|
return
|
||||||
|
.shoot()
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
extends "res://entities/units/movement_behaviors/player_movement_behavior.gd"
|
||||||
|
|
||||||
|
|
||||||
|
func get_movement()->Vector2:
|
||||||
|
if device >= 50:
|
||||||
|
return get_parent()._current_movement
|
||||||
|
|
||||||
|
return .get_movement()
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
extends "res://entities/units/unit/unit.gd"
|
||||||
|
|
||||||
|
# THIS IS CURRENTLY A DUPE, hopefully that won't be a problem
|
||||||
|
enum EntityState {
|
||||||
|
ENTITY_STATE_NETWORK_ID,
|
||||||
|
|
||||||
|
ENTITY_STATE_X_POS,
|
||||||
|
ENTITY_STATE_Y_POS,
|
||||||
|
ENTITY_STATE_X_MOVE,
|
||||||
|
ENTITY_STATE_Y_MOVE,
|
||||||
|
ENTITY_STATE_CURRENT_HP,
|
||||||
|
ENTITY_STATE_MAX_HP,
|
||||||
|
ENTITY_STATE_SPRITE_SCALE,
|
||||||
|
|
||||||
|
# Player-specific entity state.
|
||||||
|
ENTITY_STATE_PLAYER_GOLD,
|
||||||
|
ENTITY_STATE_PLAYER_CURRENT_XP,
|
||||||
|
ENTITY_STATE_PLAYER_NEXT_LEVEL_XP,
|
||||||
|
ENTITY_STATE_PLAYER_NUM_UPGRADES,
|
||||||
|
ENTITY_STATE_PLAYER_WEAPONS,
|
||||||
|
ENTITY_STATE_PLAYER_LEVEL,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum WeaponState {
|
||||||
|
WEAPON_STATE_X_POS,
|
||||||
|
WEAPON_STATE_Y_POS,
|
||||||
|
WEAPON_STATE_ROTATION,
|
||||||
|
WEAPON_STATE_SPRITE_ROTATION,
|
||||||
|
WEAPON_STATE_IS_SHOOTING,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func take_damage(value: int, args: TakeDamageArgs) -> Array:
|
||||||
|
if self.in_multiplayer_game and not self.is_host:
|
||||||
|
return []
|
||||||
|
return .take_damage(value, args)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_Hurtbox_area_entered(hitbox: Area2D) -> void :
|
||||||
|
if self.in_multiplayer_game and not self.is_host:
|
||||||
|
return
|
||||||
|
._on_Hurtbox_area_entered(hitbox)
|
||||||
|
|
||||||
|
|
||||||
|
func flash()->void :
|
||||||
|
if self.in_multiplayer_game and self.is_host:
|
||||||
|
self.brotatogether_options.batched_unit_flashes[self.network_id] = true
|
||||||
|
.flash()
|
||||||
|
|
||||||
|
|
||||||
|
func die(args: = Entity.DieArgs.new())->void :
|
||||||
|
if self.in_multiplayer_game and self.is_host:
|
||||||
|
self.brotatogether_options.batched_enemy_deaths[self.network_id] = true
|
||||||
|
.die(args)
|
||||||
|
|
||||||
|
|
||||||
|
func update_client_enemy(unit_dict : Dictionary) -> void:
|
||||||
|
set_deferred("position", Vector2(unit_dict["X_POS"], unit_dict["Y_POS"]))
|
||||||
|
|
||||||
|
_current_movement.x = unit_dict["MOVE_X"]
|
||||||
|
_current_movement.y = unit_dict["MOVE_Y"]
|
||||||
|
|
||||||
|
var modulate_a = unit_dict["MODULATE_A"]
|
||||||
|
var modulate_r = unit_dict["MODULATE_R"]
|
||||||
|
var modulate_g = unit_dict["MODULATE_G"]
|
||||||
|
var modulate_b = unit_dict["MODULATE_B"]
|
||||||
|
|
||||||
|
sprite.self_modulate = Color8(modulate_r, modulate_g, modulate_b, modulate_a)
|
||||||
|
|
||||||
|
call_deferred("update_animation", _current_movement)
|
||||||
|
|
||||||
|
|
||||||
|
func update_external_player_position(player_dict : Dictionary) -> void:
|
||||||
|
self.position.x = player_dict[EntityState.ENTITY_STATE_X_POS]
|
||||||
|
self.position.y = player_dict[EntityState.ENTITY_STATE_Y_POS]
|
||||||
|
|
||||||
|
self.sprite.scale.x = player_dict[EntityState.ENTITY_STATE_SPRITE_SCALE]
|
||||||
|
|
||||||
|
self._current_movement.x = player_dict[EntityState.ENTITY_STATE_X_MOVE]
|
||||||
|
self._current_movement.y = player_dict[EntityState.ENTITY_STATE_Y_MOVE]
|
||||||
|
|
||||||
|
if not dead:
|
||||||
|
self.update_animation(_current_movement)
|
||||||
|
|
||||||
|
|
||||||
|
func update_client_player(player_dict : Dictionary, player_index : int) -> void:
|
||||||
|
var current_xp = player_dict[EntityState.ENTITY_STATE_PLAYER_CURRENT_XP]
|
||||||
|
var next_level_xp = player_dict[EntityState.ENTITY_STATE_PLAYER_NEXT_LEVEL_XP]
|
||||||
|
RunData.players_data[player_index].current_xp = current_xp
|
||||||
|
RunData.emit_signal("xp_added", current_xp, next_level_xp, player_index)
|
||||||
|
|
||||||
|
var current_hp = player_dict[EntityState.ENTITY_STATE_CURRENT_HP]
|
||||||
|
var max_hp = player_dict[EntityState.ENTITY_STATE_MAX_HP]
|
||||||
|
var should_send_hp_signal = false
|
||||||
|
if current_hp != self.current_stats.health:
|
||||||
|
should_send_hp_signal = true
|
||||||
|
self.current_stats.health = current_hp
|
||||||
|
if max_hp != self.max_stats.health:
|
||||||
|
should_send_hp_signal = true
|
||||||
|
self.max_stats.health = max_hp
|
||||||
|
if should_send_hp_signal:
|
||||||
|
self.emit_signal("health_updated", self, self.current_stats.health, self.max_stats.health)
|
||||||
|
|
||||||
|
var current_gold = player_dict[EntityState.ENTITY_STATE_PLAYER_GOLD]
|
||||||
|
var current_level = player_dict[EntityState.ENTITY_STATE_PLAYER_LEVEL]
|
||||||
|
RunData.players_data[player_index].gold = current_gold
|
||||||
|
RunData.players_data[player_index].current_level = current_level
|
||||||
|
|
||||||
|
RunData.emit_signal("gold_changed", current_gold, player_index)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var weapons_array = player_dict[EntityState.ENTITY_STATE_PLAYER_WEAPONS]
|
||||||
|
for weapon_index in weapons_array.size():
|
||||||
|
var weapon_dict = weapons_array[weapon_index]
|
||||||
|
var weapon = self.current_weapons[weapon_index]
|
||||||
|
|
||||||
|
weapon.sprite.position.x = weapon_dict[WeaponState.WEAPON_STATE_X_POS]
|
||||||
|
weapon.sprite.position.y = weapon_dict[WeaponState.WEAPON_STATE_Y_POS]
|
||||||
|
weapon.sprite.rotation = weapon_dict[WeaponState.WEAPON_STATE_SPRITE_ROTATION]
|
||||||
|
weapon.rotation = weapon_dict[WeaponState.WEAPON_STATE_ROTATION]
|
||||||
|
weapon._is_shooting = weapon_dict[WeaponState.WEAPON_STATE_IS_SHOOTING]
|
||||||
|
weapon._current_cooldown = 9999
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
extends "res://global/effects_manager.gd"
|
||||||
|
|
||||||
|
var steam_connection
|
||||||
|
var brotatogether_options
|
||||||
|
var in_multiplayer_game = false
|
||||||
|
var is_host = false
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
steam_connection = $"/root/SteamConnection"
|
||||||
|
brotatogether_options = $"/root/BrotogetherOptions"
|
||||||
|
in_multiplayer_game = brotatogether_options.in_multiplayer_game
|
||||||
|
|
||||||
|
if in_multiplayer_game:
|
||||||
|
is_host = steam_connection.is_host()
|
||||||
|
|
||||||
|
|
||||||
|
func play_hit_particles(effect_pos: Vector2, direction: Vector2, effect_scale: float) -> void:
|
||||||
|
.play_hit_particles(effect_pos, direction, effect_scale)
|
||||||
|
|
||||||
|
if in_multiplayer_game and self.is_host:
|
||||||
|
var hit_particle_dict = {}
|
||||||
|
hit_particle_dict["X_POS"] = effect_pos.x
|
||||||
|
hit_particle_dict["Y_POS"] = effect_pos.y
|
||||||
|
hit_particle_dict["X_DIR"] = direction.x
|
||||||
|
hit_particle_dict["Y_DIR"] = direction.y
|
||||||
|
hit_particle_dict["SCALE"] = effect_scale
|
||||||
|
brotatogether_options.batched_hit_particles.push_back(hit_particle_dict)
|
||||||
|
|
||||||
|
|
||||||
|
func play_hit_effect(effect_pos: Vector2, _direction: Vector2, effect_scale: float)->void :
|
||||||
|
.play_hit_effect(effect_pos, _direction, effect_scale)
|
||||||
|
|
||||||
|
if in_multiplayer_game and self.is_host:
|
||||||
|
var hit_effect_dict = {}
|
||||||
|
hit_effect_dict["X_POS"] = effect_pos.x
|
||||||
|
hit_effect_dict["Y_POS"] = effect_pos.y
|
||||||
|
hit_effect_dict["SCALE"] = effect_scale
|
||||||
|
brotatogether_options.batched_hit_effects.push_back(hit_effect_dict)
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
extends "res://global/entity_spawner.gd"
|
||||||
|
|
||||||
|
var steam_connection
|
||||||
|
var brotatogether_options
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
steam_connection = $"/root/SteamConnection"
|
||||||
|
brotatogether_options = $"/root/BrotogetherOptions"
|
||||||
|
|
||||||
|
|
||||||
|
func spawn(queue_from: Array, player_index: = - 1) -> void:
|
||||||
|
if not brotatogether_options.in_multiplayer_game:
|
||||||
|
.spawn(queue_from, player_index)
|
||||||
|
return
|
||||||
|
|
||||||
|
if not steam_connection.is_host():
|
||||||
|
queue_from.pop_back()
|
||||||
|
return
|
||||||
|
|
||||||
|
.spawn(queue_from, player_index)
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
extends "res://items/global/item.gd"
|
||||||
|
|
||||||
|
var steam_connection
|
||||||
|
var brotatogether_options
|
||||||
|
var in_multiplayer_game = false
|
||||||
|
var network_id = 0
|
||||||
|
var is_host = false
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
steam_connection = $"/root/SteamConnection"
|
||||||
|
brotatogether_options = $"/root/BrotogetherOptions"
|
||||||
|
in_multiplayer_game = brotatogether_options.in_multiplayer_game
|
||||||
|
|
||||||
|
if in_multiplayer_game:
|
||||||
|
is_host = steam_connection.is_host()
|
||||||
|
network_id = brotatogether_options.current_network_id
|
||||||
|
brotatogether_options.current_network_id = brotatogether_options.current_network_id + 1
|
||||||
1613
src/mods-unpacked/Brogether-Brogether/extensions/main.gd
Normal file
1613
src/mods-unpacked/Brogether-Brogether/extensions/main.gd
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,44 +0,0 @@
|
|||||||
extends "res://main.gd"
|
|
||||||
|
|
||||||
var _brogether_snapshot_elapsed := 0.0
|
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
|
||||||
._ready()
|
|
||||||
var brogether = _get_brogether()
|
|
||||||
if brogether != null:
|
|
||||||
brogether.on_run_scene_ready(self)
|
|
||||||
|
|
||||||
|
|
||||||
func _physics_process(delta: float) -> void:
|
|
||||||
._physics_process(delta)
|
|
||||||
_brogether_snapshot_elapsed += delta
|
|
||||||
if _brogether_snapshot_elapsed < 0.25:
|
|
||||||
return
|
|
||||||
_brogether_snapshot_elapsed = 0.0
|
|
||||||
var brogether = _get_brogether()
|
|
||||||
if brogether != null:
|
|
||||||
brogether.on_run_snapshot_tick(_players)
|
|
||||||
|
|
||||||
|
|
||||||
func _on_EntitySpawner_players_spawned(players: Array) -> void:
|
|
||||||
._on_EntitySpawner_players_spawned(players)
|
|
||||||
var brogether = _get_brogether()
|
|
||||||
if brogether != null:
|
|
||||||
brogether.on_run_players_spawned(players)
|
|
||||||
|
|
||||||
|
|
||||||
func _exit_tree() -> void:
|
|
||||||
var brogether = _get_brogether()
|
|
||||||
if brogether != null:
|
|
||||||
brogether.on_run_scene_exiting()
|
|
||||||
|
|
||||||
|
|
||||||
func _get_brogether():
|
|
||||||
var root: Viewport = get_tree().get_root()
|
|
||||||
if root == null:
|
|
||||||
return null
|
|
||||||
var mod_loader: Node = root.get_node_or_null("ModLoader")
|
|
||||||
if mod_loader == null:
|
|
||||||
return null
|
|
||||||
return mod_loader.get_node_or_null("Brogether-Brogether")
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
extends "res://ui/menus/pages/main_menu.gd"
|
|
||||||
|
|
||||||
var _brogether_button: Button = null
|
|
||||||
|
|
||||||
|
|
||||||
func setup_menu() -> void:
|
|
||||||
.setup_menu()
|
|
||||||
_add_brogether_button()
|
|
||||||
|
|
||||||
|
|
||||||
func _add_brogether_button() -> void:
|
|
||||||
if _brogether_button != null and is_instance_valid(_brogether_button):
|
|
||||||
return
|
|
||||||
if right_container == null:
|
|
||||||
return
|
|
||||||
_brogether_button = Button.new()
|
|
||||||
_brogether_button.name = "BrogetherButton"
|
|
||||||
_brogether_button.text = "BROGETHER"
|
|
||||||
_brogether_button.rect_min_size = mods_button.rect_min_size
|
|
||||||
_brogether_button.size_flags_horizontal = mods_button.size_flags_horizontal
|
|
||||||
_brogether_button.size_flags_vertical = mods_button.size_flags_vertical
|
|
||||||
_brogether_button.theme = mods_button.theme
|
|
||||||
_brogether_button.connect("pressed", self, "_on_BrogetherButton_pressed")
|
|
||||||
right_container.add_child(_brogether_button)
|
|
||||||
right_container.move_child(_brogether_button, right_container.get_child_count() - 1)
|
|
||||||
|
|
||||||
|
|
||||||
func _on_BrogetherButton_pressed() -> void:
|
|
||||||
var brogether = _get_brogether()
|
|
||||||
if brogether != null:
|
|
||||||
brogether.open_debug_panel()
|
|
||||||
|
|
||||||
|
|
||||||
func _get_brogether():
|
|
||||||
var root: Viewport = get_tree().get_root()
|
|
||||||
if root == null:
|
|
||||||
return null
|
|
||||||
var mod_loader: Node = root.get_node_or_null("ModLoader")
|
|
||||||
if mod_loader == null:
|
|
||||||
return null
|
|
||||||
return mod_loader.get_node_or_null("Brogether-Brogether")
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
extends "res://projectiles/player_explosion.gd"
|
||||||
|
|
||||||
|
var is_ghost_explosion = false
|
||||||
|
|
||||||
|
func start_explosion() -> void:
|
||||||
|
var steam_connection = $"/root/SteamConnection"
|
||||||
|
var brotatogether_options = $"/root/BrotogetherOptions"
|
||||||
|
if brotatogether_options.in_multiplayer_game and not is_ghost_explosion:
|
||||||
|
if steam_connection.is_host():
|
||||||
|
var explosion_dict = {
|
||||||
|
"X_POS" : global_position.x,
|
||||||
|
"Y_POS" : global_position.y,
|
||||||
|
"SCALE" : scale.x,
|
||||||
|
}
|
||||||
|
brotatogether_options.batched_explosions.push_back(explosion_dict)
|
||||||
|
.start_explosion()
|
||||||
|
else:
|
||||||
|
.start_explosion()
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
extends "res://singletons/coop_service.gd"
|
||||||
|
|
||||||
|
|
||||||
|
func is_player_using_gamepad(player_index) -> bool:
|
||||||
|
if get_remapped_player_device(player_index) >= 50:
|
||||||
|
return false
|
||||||
|
|
||||||
|
return .is_player_using_gamepad(player_index)
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
extends "res://singletons/run_data.gd"
|
||||||
|
|
||||||
|
var steam_connection
|
||||||
|
var brotatogether_options
|
||||||
|
|
||||||
|
var is_multiplayer_lobby = false
|
||||||
|
|
||||||
|
|
||||||
|
func init_multiplayer() -> void:
|
||||||
|
steam_connection = $"/root/SteamConnection"
|
||||||
|
brotatogether_options = $"/root/BrotogetherOptions"
|
||||||
|
|
||||||
|
steam_connection.leave_game_lobby()
|
||||||
|
|
||||||
|
|
||||||
|
func lock_player_shop_item(item_data: ItemParentData, wave_value: int, player_index: int)->void :
|
||||||
|
if brotatogether_options.in_multiplayer_game:
|
||||||
|
if steam_connection.is_host():
|
||||||
|
.lock_player_shop_item(item_data, wave_value, player_index)
|
||||||
|
steam_connection.shop_lock_item(item_data.my_id, wave_value)
|
||||||
|
else:
|
||||||
|
.lock_player_shop_item(item_data, wave_value, player_index)
|
||||||
|
|
||||||
|
|
||||||
|
func unlock_player_shop_item(item_data: ItemParentData, player_index: int)->void :
|
||||||
|
if brotatogether_options.in_multiplayer_game:
|
||||||
|
if steam_connection.is_host():
|
||||||
|
.unlock_player_shop_item(item_data, player_index)
|
||||||
|
steam_connection.shop_unlock_item(item_data.my_id)
|
||||||
|
else:
|
||||||
|
.unlock_player_shop_item(item_data, player_index)
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
extends "res://singletons/sound_manager.gd"
|
||||||
|
|
||||||
|
var steam_connection
|
||||||
|
var brotatogether_options
|
||||||
|
|
||||||
|
var is_multiplayer_lobby = false
|
||||||
|
|
||||||
|
|
||||||
|
func init_multiplayer() -> void:
|
||||||
|
steam_connection = $"/root/SteamConnection"
|
||||||
|
brotatogether_options = $"/root/BrotogetherOptions"
|
||||||
|
|
||||||
|
|
||||||
|
func play(sound: Resource, volume_mod: float = 0.0, pitch_rand: float = 0.0, always_play: bool = false)->void :
|
||||||
|
if steam_connection and brotatogether_options:
|
||||||
|
if brotatogether_options.in_multiplayer_game:
|
||||||
|
if steam_connection.is_host():
|
||||||
|
var sound_dict = {
|
||||||
|
"RESOURCE_PATH" : sound.resource_path,
|
||||||
|
}
|
||||||
|
brotatogether_options.batched_sounds.push_back(sound_dict)
|
||||||
|
.play(sound, volume_mod, pitch_rand, always_play)
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
extends "res://singletons/sound_manager_2d.gd"
|
||||||
|
|
||||||
|
var steam_connection
|
||||||
|
var brotatogether_options
|
||||||
|
|
||||||
|
var is_multiplayer_lobby = false
|
||||||
|
|
||||||
|
|
||||||
|
func init_multiplayer() -> void:
|
||||||
|
steam_connection = $"/root/SteamConnection"
|
||||||
|
brotatogether_options = $"/root/BrotogetherOptions"
|
||||||
|
|
||||||
|
|
||||||
|
func play(sound: Resource, pos: Vector2, volume_mod: float = 0.0, pitch_rand: float = 0.0, always_play: bool = false)->void :
|
||||||
|
if steam_connection and brotatogether_options:
|
||||||
|
if brotatogether_options.in_multiplayer_game:
|
||||||
|
if steam_connection.is_host():
|
||||||
|
var sound_dict = {
|
||||||
|
"RESOURCE_PATH" : sound.resource_path,
|
||||||
|
"X_POS" : pos.x,
|
||||||
|
"Y_POS" : pos.y
|
||||||
|
}
|
||||||
|
brotatogether_options.batched_2d_sounds.push_back(sound_dict)
|
||||||
|
.play(sound, pos, volume_mod, pitch_rand, always_play)
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
extends "res://singletons/utils.gd"
|
||||||
|
|
||||||
|
|
||||||
|
func is_player_action_released(event: InputEvent, player_index: int, action: String)->bool:
|
||||||
|
if CoopService.get_remapped_player_device(player_index) >= 50:
|
||||||
|
return false
|
||||||
|
|
||||||
|
return .is_player_action_released(event, player_index, action)
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
extends "res://ui/menus/global/focus_emulator.gd"
|
||||||
|
|
||||||
|
var global_focused_control
|
||||||
|
var steam_connection
|
||||||
|
var brotatogether_options
|
||||||
|
|
||||||
|
|
||||||
|
func ready() -> void:
|
||||||
|
steam_connection = $"/root/SteamConnection"
|
||||||
|
brotatogether_options = $"/root/BrotogetherOptions"
|
||||||
|
|
||||||
|
var _err = get_viewport().connect("gui_focus_changed", self, "_on_focus_changed_multiplayer")
|
||||||
|
|
||||||
|
|
||||||
|
func _on_focus_changed_multiplayer(control:Control) -> void:
|
||||||
|
if control != null:
|
||||||
|
global_focused_control = control
|
||||||
|
|
||||||
|
|
||||||
|
# Have line edit eat inputs so that you can send messages
|
||||||
|
func _handle_input(event:InputEvent) -> bool:
|
||||||
|
if not brotatogether_options:
|
||||||
|
brotatogether_options = $"/root/BrotogetherOptions"
|
||||||
|
|
||||||
|
if not steam_connection:
|
||||||
|
steam_connection = $"/root/SteamConnection"
|
||||||
|
|
||||||
|
if get_tree().current_scene.name == "CoopShop" and brotatogether_options.in_multiplayer_game:
|
||||||
|
if event is InputEventKey:
|
||||||
|
if event.pressed:
|
||||||
|
var carousel = get_tree().current_scene._get_coop_player_container(steam_connection.get_my_index()).carousel
|
||||||
|
if event.scancode == KEY_R:
|
||||||
|
carousel._on_ArrowRight_pressed()
|
||||||
|
if event.scancode == KEY_L:
|
||||||
|
carousel._on_ArrowLeft_pressed()
|
||||||
|
|
||||||
|
if global_focused_control != null and global_focused_control is LineEdit:
|
||||||
|
return false
|
||||||
|
return ._handle_input(event)
|
||||||
|
|
||||||
|
|
||||||
|
func _get_focus_neighbour_for_event(event: InputEvent, target: Control)->GetFocusNeighbourForEventResult:
|
||||||
|
if _device >= 50:
|
||||||
|
return GetFocusNeighbourForEventResult.new()
|
||||||
|
|
||||||
|
return ._get_focus_neighbour_for_event(event,target)
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
extends "res://ui/menus/ingame/coop_upgrades_ui_player_container.gd"
|
||||||
|
|
||||||
|
var steam_connection
|
||||||
|
var brotatogether_options
|
||||||
|
var in_multiplayer_game = false
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
steam_connection = $"/root/SteamConnection"
|
||||||
|
brotatogether_options = $"/root/BrotogetherOptions"
|
||||||
|
in_multiplayer_game = brotatogether_options.in_multiplayer_game
|
||||||
|
|
||||||
|
|
||||||
|
func _on_RerollButton_pressed() -> void:
|
||||||
|
if in_multiplayer_game:
|
||||||
|
if steam_connection.is_host():
|
||||||
|
._on_RerollButton_pressed()
|
||||||
|
else:
|
||||||
|
steam_connection.send_main_scene_client_reroll_button_ressed()
|
||||||
|
else:
|
||||||
|
._on_RerollButton_pressed()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_choose_button_pressed(upgrade: UpgradeData) -> void:
|
||||||
|
if in_multiplayer_game:
|
||||||
|
if steam_connection.is_host():
|
||||||
|
._on_choose_button_pressed(upgrade)
|
||||||
|
else:
|
||||||
|
var upgrade_dict = {
|
||||||
|
"UPGRADE_ID" : upgrade.my_id
|
||||||
|
}
|
||||||
|
steam_connection.send_main_scene_client_choose_upgrade_pressed(upgrade_dict)
|
||||||
|
else:
|
||||||
|
._on_choose_button_pressed(upgrade)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_TakeButton_pressed():
|
||||||
|
if in_multiplayer_game:
|
||||||
|
if steam_connection.is_host():
|
||||||
|
._on_TakeButton_pressed()
|
||||||
|
else:
|
||||||
|
steam_connection.send_main_scene_client_take_button_pressed()
|
||||||
|
else:
|
||||||
|
._on_TakeButton_pressed()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_DiscardButton_pressed():
|
||||||
|
if in_multiplayer_game:
|
||||||
|
if steam_connection.is_host():
|
||||||
|
._on_DiscardButton_pressed()
|
||||||
|
else:
|
||||||
|
steam_connection.send_main_scene_client_discard_button_pressed()
|
||||||
|
else:
|
||||||
|
._on_DiscardButton_pressed()
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
extends "res://ui/menus/ingame/pause_menu.gd"
|
||||||
|
|
||||||
|
var steam_connection
|
||||||
|
var brotatogether_options
|
||||||
|
|
||||||
|
var is_multiplayer_lobby = false
|
||||||
|
|
||||||
|
|
||||||
|
# Called when the node enters the scene tree for the first time.
|
||||||
|
func _ready():
|
||||||
|
steam_connection = $"/root/SteamConnection"
|
||||||
|
brotatogether_options = $"/root/BrotogetherOptions"
|
||||||
|
|
||||||
|
|
||||||
|
func on_game_lost_focus()->void :
|
||||||
|
if steam_connection.game_lobby_id > 0:
|
||||||
|
return
|
||||||
|
.on_game_lost_focus()
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
extends "res://ui/menus/pages/main_menu.gd"
|
||||||
|
|
||||||
|
|
||||||
|
var multiplayer_button: Button
|
||||||
|
|
||||||
|
# Add a multiplayer button to the main menu
|
||||||
|
func _ready():
|
||||||
|
RunData.init_multiplayer()
|
||||||
|
SoundManager.init_multiplayer()
|
||||||
|
SoundManager2D.init_multiplayer()
|
||||||
|
|
||||||
|
var buttons_node = $"MarginContainer/VBoxContainer/HBoxContainer/ButtonsLeft"
|
||||||
|
|
||||||
|
# Duplicate a Button to get the styling
|
||||||
|
multiplayer_button = start_button.duplicate()
|
||||||
|
multiplayer_button.text = "Multiplayer"
|
||||||
|
multiplayer_button.name = "MultiplayerButton"
|
||||||
|
|
||||||
|
var _unused = multiplayer_button.connect("pressed", self, "_on_MultiplayerButton_pressed")
|
||||||
|
multiplayer_button.disconnect("pressed", self, "_on_StartButton_pressed")
|
||||||
|
|
||||||
|
buttons_node.add_child_below_node(buttons_node.get_children()[0], multiplayer_button)
|
||||||
|
buttons_node.move_child(multiplayer_button, 0)
|
||||||
|
|
||||||
|
remove_game_controller()
|
||||||
|
|
||||||
|
$"/root/BrotogetherOptions".joining_multiplayer_lobby = false
|
||||||
|
$"/root/BrotogetherOptions".is_solo_test = false
|
||||||
|
|
||||||
|
|
||||||
|
func init() -> void:
|
||||||
|
.init()
|
||||||
|
if continue_button.visible:
|
||||||
|
continue_button.focus_neighbour_top = multiplayer_button.get_path()
|
||||||
|
else:
|
||||||
|
start_button.focus_neighbour_top = multiplayer_button.get_path()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_MultiplayerButton_pressed():
|
||||||
|
var _error = get_tree().change_scene("res://mods-unpacked/Brogether-Brogether/ui/multiplayer_menu.tscn")
|
||||||
|
|
||||||
|
func remove_game_controller():
|
||||||
|
if $"/root".has_node("GameController"):
|
||||||
|
var game_controller = $"/root/GameController"
|
||||||
|
$"/root".remove_child(game_controller)
|
||||||
@@ -0,0 +1,342 @@
|
|||||||
|
extends "res://ui/menus/run/character_selection.gd"
|
||||||
|
|
||||||
|
const ChatPanel = preload("res://mods-unpacked/Brogether-Brogether/ui/chat_panel.tscn")
|
||||||
|
const ChatMessage = preload("res://mods-unpacked/Brogether-Brogether/ui/chat/chat_message.tscn")
|
||||||
|
const UsernameLabel = preload("res://mods-unpacked/Brogether-Brogether/ui/username_label.tscn")
|
||||||
|
|
||||||
|
const MULTIPLAYER_CLIENT_PLAYER_TYPE = 10
|
||||||
|
|
||||||
|
var steam_connection
|
||||||
|
var brotatogether_options
|
||||||
|
|
||||||
|
var is_multiplayer_lobby = false
|
||||||
|
|
||||||
|
var global_chat_panel
|
||||||
|
var global_chat_messsages
|
||||||
|
var global_chat_input
|
||||||
|
|
||||||
|
var lobby_chat_panel
|
||||||
|
var lobby_chat_messsages
|
||||||
|
var lobby_chat_input
|
||||||
|
|
||||||
|
var panel_parent_container
|
||||||
|
|
||||||
|
var panels_array
|
||||||
|
var visible_panel_index : int = 0
|
||||||
|
|
||||||
|
# Mapped inventory item by item keys. Used to reset focus based on external
|
||||||
|
# calls.
|
||||||
|
var inventory_by_string_key : Dictionary
|
||||||
|
|
||||||
|
# Mapped Selections by item keys. Kept independent of itnentory items to
|
||||||
|
# avoid complications around randoms, locked items, etc.
|
||||||
|
var selections_by_string_key : Dictionary
|
||||||
|
|
||||||
|
var username_labels = []
|
||||||
|
var external_focus = false
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
steam_connection = $"/root/SteamConnection"
|
||||||
|
steam_connection.connect("global_chat_received", self, "_received_global_chat")
|
||||||
|
steam_connection.connect("game_lobby_chat_received", self, "_received_lobby_chat")
|
||||||
|
steam_connection.connect("player_focused_character", self, "_player_focused_character")
|
||||||
|
steam_connection.connect("player_selected_character", self, "_player_selected_character")
|
||||||
|
steam_connection.connect("character_lobby_update", self, "_lobby_characters_updated")
|
||||||
|
steam_connection.connect("request_character_lobby_update", self, "_character_lobby_update_requested")
|
||||||
|
steam_connection.connect("character_selection_complete", self, "_host_character_selection_complete")
|
||||||
|
|
||||||
|
# TODO gracefully add new players
|
||||||
|
steam_connection.connect("lobby_players_updated", self, "reload_scene")
|
||||||
|
|
||||||
|
brotatogether_options = $"/root/BrotogetherOptions"
|
||||||
|
is_multiplayer_lobby = brotatogether_options.joining_multiplayer_lobby
|
||||||
|
|
||||||
|
if is_multiplayer_lobby:
|
||||||
|
RunData.is_coop_run = true
|
||||||
|
_coop_button.init()
|
||||||
|
_coop_button.hide()
|
||||||
|
var run_options_top_panel = _run_options_panel.get_node("MarginContainer/VBoxContainer/HBoxContainer")
|
||||||
|
run_options_top_panel.remove_child(run_options_top_panel.get_node("Icon"))
|
||||||
|
|
||||||
|
# Add left and right buttons to the heading
|
||||||
|
var run_options_left_arrow : TextureButton = TextureButton.new()
|
||||||
|
run_options_left_arrow.texture_normal = load("res://ui/menus/global/arrow_left.png")
|
||||||
|
run_options_top_panel.add_child(run_options_left_arrow)
|
||||||
|
run_options_top_panel.move_child(run_options_left_arrow, 0)
|
||||||
|
var _err = run_options_left_arrow.connect("pressed", self, "_on_pressed_left_menu_arrow")
|
||||||
|
|
||||||
|
var run_options_right_arrow : TextureButton = TextureButton.new()
|
||||||
|
run_options_right_arrow.texture_normal = load("res://ui/menus/global/arrow_right.png")
|
||||||
|
run_options_top_panel.add_child(run_options_right_arrow)
|
||||||
|
_err = run_options_right_arrow.connect("pressed", self, "_on_pressed_right_menu_arrow")
|
||||||
|
|
||||||
|
panel_parent_container = _run_options_panel.get_parent()
|
||||||
|
|
||||||
|
var username_label_player_1 : Label = UsernameLabel.instance()
|
||||||
|
$"MarginContainer/VBoxContainer/DescriptionContainer/HBoxContainer/Panel1/vboxContainer".add_child(username_label_player_1)
|
||||||
|
$"MarginContainer/VBoxContainer/DescriptionContainer/HBoxContainer/Panel1/vboxContainer".move_child(username_label_player_1, 0)
|
||||||
|
username_labels.push_back(username_label_player_1)
|
||||||
|
|
||||||
|
var username_label_player_2 : Label = UsernameLabel.instance()
|
||||||
|
$"MarginContainer/VBoxContainer/DescriptionContainer/HBoxContainer/Panel2/vboxContainer".add_child(username_label_player_2)
|
||||||
|
$"MarginContainer/VBoxContainer/DescriptionContainer/HBoxContainer/Panel2/vboxContainer".move_child(username_label_player_2, 0)
|
||||||
|
username_labels.push_back(username_label_player_2)
|
||||||
|
|
||||||
|
var username_label_player_3 : Label = UsernameLabel.instance()
|
||||||
|
$"MarginContainer/VBoxContainer/DescriptionContainer/HBoxContainer/Panel3/vboxContainer".add_child(username_label_player_3)
|
||||||
|
$"MarginContainer/VBoxContainer/DescriptionContainer/HBoxContainer/Panel3/vboxContainer".move_child(username_label_player_3, 0)
|
||||||
|
username_labels.push_back(username_label_player_3)
|
||||||
|
|
||||||
|
var username_label_player_4 : Label = UsernameLabel.instance()
|
||||||
|
$"MarginContainer/VBoxContainer/DescriptionContainer/HBoxContainer/Panel4/vboxContainer".add_child(username_label_player_4)
|
||||||
|
$"MarginContainer/VBoxContainer/DescriptionContainer/HBoxContainer/Panel4/vboxContainer".move_child(username_label_player_4, 0)
|
||||||
|
username_labels.push_back(username_label_player_4)
|
||||||
|
|
||||||
|
for index in steam_connection.lobby_member_names.size():
|
||||||
|
username_labels[index].text = steam_connection.lobby_member_names[index]
|
||||||
|
|
||||||
|
global_chat_panel = ChatPanel.instance()
|
||||||
|
global_chat_panel.get_node("MarginContainer/VBoxContainer/HBoxContainer/ChatTitle").text = "Global Chat"
|
||||||
|
var global_chat_left_arrow = global_chat_panel.get_node("MarginContainer/VBoxContainer/HBoxContainer/LeftArrow")
|
||||||
|
_err = global_chat_left_arrow.connect("pressed", self, "_on_pressed_left_menu_arrow")
|
||||||
|
var global_chat_right_arrow = global_chat_panel.get_node("MarginContainer/VBoxContainer/HBoxContainer/RightArrow")
|
||||||
|
_err = global_chat_right_arrow.connect("pressed", self, "_on_pressed_right_menu_arrow")
|
||||||
|
panel_parent_container.add_child_below_node(_run_options_panel, global_chat_panel)
|
||||||
|
|
||||||
|
global_chat_messsages = global_chat_panel.get_node("MarginContainer/VBoxContainer/ScrollContainer/ChatMessages")
|
||||||
|
global_chat_input = global_chat_panel.get_node("MarginContainer/VBoxContainer/ChatInput")
|
||||||
|
global_chat_input.connect("text_entered", self, "_on_global_chat_text_entered")
|
||||||
|
|
||||||
|
lobby_chat_panel = ChatPanel.instance()
|
||||||
|
lobby_chat_panel.get_node("MarginContainer/VBoxContainer/HBoxContainer/ChatTitle").text = "Lobby Chat"
|
||||||
|
var lobby_chat_left_arrow = lobby_chat_panel.get_node("MarginContainer/VBoxContainer/HBoxContainer/LeftArrow")
|
||||||
|
_err = lobby_chat_left_arrow.connect("pressed", self, "_on_pressed_left_menu_arrow")
|
||||||
|
var lobby_chat_right_arrow = lobby_chat_panel.get_node("MarginContainer/VBoxContainer/HBoxContainer/RightArrow")
|
||||||
|
_err = lobby_chat_right_arrow.connect("pressed", self, "_on_pressed_right_menu_arrow")
|
||||||
|
panel_parent_container.add_child_below_node(_run_options_panel, lobby_chat_panel)
|
||||||
|
|
||||||
|
lobby_chat_messsages = lobby_chat_panel.get_node("MarginContainer/VBoxContainer/ScrollContainer/ChatMessages")
|
||||||
|
lobby_chat_input = lobby_chat_panel.get_node("MarginContainer/VBoxContainer/ChatInput")
|
||||||
|
lobby_chat_input.connect("text_entered", self, "_on_lobby_chat_text_entered")
|
||||||
|
|
||||||
|
panels_array = [_run_options_panel, global_chat_panel, lobby_chat_panel]
|
||||||
|
update_panel_visiblility()
|
||||||
|
|
||||||
|
for member_index in steam_connection.lobby_members.size():
|
||||||
|
var member_id = steam_connection.lobby_members[member_index]
|
||||||
|
if member_id == steam_connection.steam_id:
|
||||||
|
CoopService._add_player(0, MULTIPLAYER_CLIENT_PLAYER_TYPE)
|
||||||
|
else:
|
||||||
|
CoopService._add_player(100 + member_index, MULTIPLAYER_CLIENT_PLAYER_TYPE)
|
||||||
|
|
||||||
|
for character_data in _get_all_possible_elements(0):
|
||||||
|
selections_by_string_key[character_item_to_string(character_data)] = character_data
|
||||||
|
|
||||||
|
# Find the random element in the inventory
|
||||||
|
for character_data in _get_inventories()[0].get_children():
|
||||||
|
if character_data.is_random:
|
||||||
|
inventory_by_string_key[character_item_to_string(character_data)] = character_data
|
||||||
|
selections_by_string_key[character_item_to_string(character_data)] = character_data
|
||||||
|
else:
|
||||||
|
inventory_by_string_key[character_item_to_string(character_data.item)] = character_data
|
||||||
|
|
||||||
|
for panel in _get_panels():
|
||||||
|
panel._small(true)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_pressed_left_menu_arrow() -> void:
|
||||||
|
visible_panel_index = (visible_panel_index - 1 + panels_array.size()) % panels_array.size()
|
||||||
|
update_panel_visiblility()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_pressed_right_menu_arrow() -> void:
|
||||||
|
visible_panel_index = (visible_panel_index + 1) % panels_array.size()
|
||||||
|
update_panel_visiblility()
|
||||||
|
|
||||||
|
|
||||||
|
func update_panel_visiblility() -> void:
|
||||||
|
for index in panels_array.size():
|
||||||
|
if index == visible_panel_index:
|
||||||
|
panels_array[index].visible = true
|
||||||
|
else:
|
||||||
|
panels_array[index].visible = false
|
||||||
|
|
||||||
|
|
||||||
|
func _received_global_chat(user, message) -> void:
|
||||||
|
var new_message_node = ChatMessage.instance()
|
||||||
|
new_message_node.message = message
|
||||||
|
new_message_node.username = user
|
||||||
|
global_chat_messsages.add_child(new_message_node)
|
||||||
|
|
||||||
|
|
||||||
|
func _received_lobby_chat(user, message) -> void:
|
||||||
|
var new_message_node = ChatMessage.instance()
|
||||||
|
new_message_node.message = message
|
||||||
|
new_message_node.username = user
|
||||||
|
lobby_chat_messsages.add_child(new_message_node)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_global_chat_text_entered(message):
|
||||||
|
steam_connection.send_global_chat_message(message)
|
||||||
|
global_chat_input.clear()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_lobby_chat_text_entered(message):
|
||||||
|
steam_connection.send_lobby_chat_message(message)
|
||||||
|
lobby_chat_input.clear()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_element_focused(element:InventoryElement, inventory_player_index:int, _displayPanelData: bool = true) -> void:
|
||||||
|
._on_element_focused(element, inventory_player_index)
|
||||||
|
|
||||||
|
if is_multiplayer_lobby:
|
||||||
|
var element_string = ""
|
||||||
|
if element.item != null:
|
||||||
|
element_string = element.item.name
|
||||||
|
elif element.is_random:
|
||||||
|
element_string = "RANDOM"
|
||||||
|
if not external_focus:
|
||||||
|
steam_connection.character_focused(element_string)
|
||||||
|
else:
|
||||||
|
external_focus = false
|
||||||
|
|
||||||
|
|
||||||
|
func character_item_to_string(item : Resource) -> String:
|
||||||
|
if item == null:
|
||||||
|
return "RANDOM"
|
||||||
|
return item.name
|
||||||
|
|
||||||
|
|
||||||
|
func _player_focused_character(player_index : int , character : String) -> void:
|
||||||
|
var selected_item = null
|
||||||
|
var focused_element = null
|
||||||
|
|
||||||
|
if selections_by_string_key.has(character):
|
||||||
|
selected_item = selections_by_string_key[character]
|
||||||
|
|
||||||
|
if inventory_by_string_key.has(character):
|
||||||
|
focused_element = inventory_by_string_key[character]
|
||||||
|
|
||||||
|
_clear_selected_element(player_index)
|
||||||
|
_player_characters[player_index] = selected_item
|
||||||
|
if player_index < RunData.get_player_count() and player_index != steam_connection.get_my_index():
|
||||||
|
if focused_element != null:
|
||||||
|
if Utils.get_focus_emulator(player_index).focused_control != focused_element:
|
||||||
|
external_focus = true
|
||||||
|
Utils.get_focus_emulator(player_index).focused_control = focused_element
|
||||||
|
|
||||||
|
var panel = _get_panels()[player_index]
|
||||||
|
|
||||||
|
if panel.visible:
|
||||||
|
if selected_item != null:
|
||||||
|
if character == "RANDOM":
|
||||||
|
panel.set_custom_data("RANDOM", selected_item.get_inventory_icon())
|
||||||
|
else:
|
||||||
|
panel.set_data(selected_item, player_index)
|
||||||
|
|
||||||
|
|
||||||
|
func _player_selected_character(player_index : int) -> void:
|
||||||
|
_set_selected_element(player_index)
|
||||||
|
|
||||||
|
|
||||||
|
func reload_scene() -> void:
|
||||||
|
$"/root/BrotogetherOptions".joining_multiplayer_lobby = true
|
||||||
|
var _error = get_tree().change_scene(MenuData.character_selection_scene)
|
||||||
|
|
||||||
|
|
||||||
|
func _lobby_characters_updated(player_characters : Array, has_player_selected : Array) -> void:
|
||||||
|
for player_index in RunData.get_player_count():
|
||||||
|
if player_characters[player_index] != null:
|
||||||
|
_player_focused_character(player_index, player_characters[player_index])
|
||||||
|
|
||||||
|
var all_selected = true
|
||||||
|
for player_index in RunData.get_player_count():
|
||||||
|
if has_player_selected[player_index]:
|
||||||
|
_set_selected_element(player_index)
|
||||||
|
else:
|
||||||
|
all_selected = false
|
||||||
|
_clear_selected_element(player_index)
|
||||||
|
|
||||||
|
if all_selected and steam_connection.is_host():
|
||||||
|
_selections_completed_timer.start()
|
||||||
|
|
||||||
|
|
||||||
|
func _set_selected_element(player_index:int) -> void:
|
||||||
|
if _has_player_selected[player_index]:
|
||||||
|
return
|
||||||
|
|
||||||
|
._set_selected_element(player_index)
|
||||||
|
|
||||||
|
if brotatogether_options.is_solo_test:
|
||||||
|
var all_selected = true
|
||||||
|
for i in RunData.get_player_count():
|
||||||
|
if not _has_player_selected[i]:
|
||||||
|
all_selected = false
|
||||||
|
break
|
||||||
|
if all_selected:
|
||||||
|
CoopService.listening_for_inputs = false
|
||||||
|
_selections_completed_timer.start()
|
||||||
|
|
||||||
|
if steam_connection.get_lobby_index_for_player(steam_connection.steam_id) == player_index:
|
||||||
|
steam_connection.character_selected()
|
||||||
|
|
||||||
|
|
||||||
|
func _character_lobby_update_requested() -> void:
|
||||||
|
var currently_focused_characters = []
|
||||||
|
for panel in _get_panels():
|
||||||
|
var selected_item = panel.item_data
|
||||||
|
if selected_item == null:
|
||||||
|
currently_focused_characters.push_back("RANDOM")
|
||||||
|
else:
|
||||||
|
currently_focused_characters.push_back(character_item_to_string(selected_item))
|
||||||
|
|
||||||
|
steam_connection.send_character_lobby_update(currently_focused_characters, _has_player_selected)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_selections_completed() -> void:
|
||||||
|
if is_multiplayer_lobby:
|
||||||
|
if not steam_connection.is_host():
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
._on_selections_completed()
|
||||||
|
return
|
||||||
|
|
||||||
|
var currently_focused_characters = []
|
||||||
|
# Sad dupe of inner logic to make things simpler
|
||||||
|
for player_index in RunData.get_player_count():
|
||||||
|
var chosen_item = _get_panels()[player_index]
|
||||||
|
|
||||||
|
var character = _player_characters[player_index]
|
||||||
|
if chosen_item.item_data == null:
|
||||||
|
var available_elements: = []
|
||||||
|
for element in ItemService.characters:
|
||||||
|
if not element.is_locked:
|
||||||
|
available_elements.push_back(element)
|
||||||
|
character = Utils.get_rand_element(available_elements)
|
||||||
|
_player_characters[player_index] = character
|
||||||
|
|
||||||
|
RunData.add_character(character, player_index)
|
||||||
|
currently_focused_characters.push_back(character_item_to_string(character))
|
||||||
|
|
||||||
|
steam_connection.send_character_selection_completed(RunData.some_player_has_weapon_slots(), currently_focused_characters)
|
||||||
|
if RunData.some_player_has_weapon_slots():
|
||||||
|
_change_scene(MenuData.weapon_selection_scene)
|
||||||
|
else:
|
||||||
|
_change_scene(MenuData.difficulty_selection_scene)
|
||||||
|
|
||||||
|
|
||||||
|
func _host_character_selection_complete(some_player_has_weapon_slots : bool, selected_characters : Array) -> void:
|
||||||
|
# Sad dupe of inner logic to make things simpler
|
||||||
|
for player_index in selected_characters.size():
|
||||||
|
if selected_characters[player_index] != null:
|
||||||
|
_player_focused_character(player_index, selected_characters[player_index])
|
||||||
|
|
||||||
|
for player_index in RunData.get_player_count():
|
||||||
|
var character = _player_characters[player_index]
|
||||||
|
RunData.add_character(character, player_index)
|
||||||
|
|
||||||
|
if some_player_has_weapon_slots:
|
||||||
|
_change_scene(MenuData.weapon_selection_scene)
|
||||||
|
else:
|
||||||
|
_change_scene(MenuData.difficulty_selection_scene)
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
extends "res://ui/menus/run/difficulty_selection/difficulty_selection.gd"
|
||||||
|
|
||||||
|
var steam_connection
|
||||||
|
var brotatogether_options
|
||||||
|
var is_multiplayer_lobby = false
|
||||||
|
|
||||||
|
var inventory_by_string_key : Dictionary
|
||||||
|
var selection_by_string_key : Dictionary
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
steam_connection = $"/root/SteamConnection"
|
||||||
|
steam_connection.connect("difficulty_focused", self, "_difficulty_focused")
|
||||||
|
steam_connection.connect("difficulty_selected", self, "_difficulty_selected")
|
||||||
|
|
||||||
|
brotatogether_options = $"/root/BrotogetherOptions"
|
||||||
|
is_multiplayer_lobby = brotatogether_options.joining_multiplayer_lobby
|
||||||
|
|
||||||
|
if is_multiplayer_lobby:
|
||||||
|
brotatogether_options.joining_multiplayer_lobby = false
|
||||||
|
brotatogether_options.in_multiplayer_game = true
|
||||||
|
|
||||||
|
for difficulty_data in ItemService.difficulties:
|
||||||
|
selection_by_string_key[difficulty_data.value] = difficulty_data
|
||||||
|
|
||||||
|
for inventory_item in _get_inventories()[0].get_children():
|
||||||
|
inventory_by_string_key[inventory_item.item.value] = inventory_item
|
||||||
|
|
||||||
|
|
||||||
|
func _on_element_focused(element:InventoryElement, inventory_player_index:int, _displayPanelData: bool = true) -> void:
|
||||||
|
# Disregard difficulty updates from clients
|
||||||
|
if is_multiplayer_lobby:
|
||||||
|
if not steam_connection.is_host():
|
||||||
|
return
|
||||||
|
|
||||||
|
._on_element_focused(element, inventory_player_index)
|
||||||
|
|
||||||
|
if is_multiplayer_lobby:
|
||||||
|
steam_connection.difficulty_focused()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_element_pressed(element: InventoryElement, _inventory_player_index: int) -> void:
|
||||||
|
# Disregard difficulty updates from clients
|
||||||
|
if is_multiplayer_lobby:
|
||||||
|
if not steam_connection.is_host():
|
||||||
|
return
|
||||||
|
|
||||||
|
._on_element_pressed(element, _inventory_player_index)
|
||||||
|
|
||||||
|
if is_multiplayer_lobby:
|
||||||
|
steam_connection.difficulty_pressed()
|
||||||
|
|
||||||
|
|
||||||
|
func _difficulty_selected(_difficutly : int) -> void:
|
||||||
|
var _error = get_tree().change_scene(MenuData.game_scene)
|
||||||
|
|
||||||
|
|
||||||
|
func _difficulty_focused(difficutly : int) -> void:
|
||||||
|
|
||||||
|
# Hosts don't respect update calls
|
||||||
|
if is_multiplayer_lobby:
|
||||||
|
if steam_connection.is_host():
|
||||||
|
return
|
||||||
|
|
||||||
|
var selected_item = null
|
||||||
|
if selection_by_string_key.has(difficutly):
|
||||||
|
selected_item = selection_by_string_key[difficutly]
|
||||||
|
|
||||||
|
Utils.get_focus_emulator(0).focused_control = inventory_by_string_key[difficutly]
|
||||||
|
|
||||||
|
if selected_item != null:
|
||||||
|
_get_panels()[0].visible = true
|
||||||
|
_get_panels()[0].set_data(selected_item, 0)
|
||||||
@@ -0,0 +1,172 @@
|
|||||||
|
extends "res://ui/menus/run/weapon_selection.gd"
|
||||||
|
|
||||||
|
var steam_connection
|
||||||
|
var brotatogether_options
|
||||||
|
var is_multiplayer_lobby = false
|
||||||
|
|
||||||
|
var selections_by_string_key : Dictionary
|
||||||
|
var external_focus = false
|
||||||
|
|
||||||
|
|
||||||
|
var inventory_maps : Array
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
steam_connection = $"/root/SteamConnection"
|
||||||
|
|
||||||
|
steam_connection.connect("player_focused_weapon", self, "_player_focused_weapon")
|
||||||
|
steam_connection.connect("player_selected_weapon", self, "_player_selected_weapon")
|
||||||
|
steam_connection.connect("weapon_lobby_update", self, "_lobby_weapons_updated")
|
||||||
|
steam_connection.connect("weapon_selection_completed", self, "_weapon_selection_completed")
|
||||||
|
|
||||||
|
brotatogether_options = $"/root/BrotogetherOptions"
|
||||||
|
is_multiplayer_lobby = brotatogether_options.joining_multiplayer_lobby
|
||||||
|
|
||||||
|
if is_multiplayer_lobby:
|
||||||
|
for weapon_data in ItemService.weapons:
|
||||||
|
selections_by_string_key[weapon_item_to_string(weapon_data)] = weapon_data
|
||||||
|
|
||||||
|
inventory_maps = []
|
||||||
|
for player_index in RunData.get_player_count():
|
||||||
|
var inventory_map = {}
|
||||||
|
for inventory_item in _get_inventories()[player_index].get_children():
|
||||||
|
inventory_map[weapon_item_to_string(inventory_item.item)] = inventory_item
|
||||||
|
inventory_maps.push_back(inventory_map)
|
||||||
|
|
||||||
|
|
||||||
|
func weapon_item_to_string(item : Resource) -> String:
|
||||||
|
if item == null:
|
||||||
|
return "RANDOM"
|
||||||
|
return item.my_id
|
||||||
|
|
||||||
|
|
||||||
|
func _lobby_weapons_updated(player_weapons : Array, has_player_selected : Array) -> void:
|
||||||
|
for player_index in player_weapons.size():
|
||||||
|
if player_weapons[player_index] != null:
|
||||||
|
_player_focused_weapon(player_index, player_weapons[player_index])
|
||||||
|
|
||||||
|
var all_selected = true
|
||||||
|
for player_index in RunData.get_player_count():
|
||||||
|
if has_player_selected[player_index]:
|
||||||
|
_set_selected_element(player_index)
|
||||||
|
else:
|
||||||
|
all_selected = false
|
||||||
|
_clear_selected_element(player_index)
|
||||||
|
|
||||||
|
if all_selected:
|
||||||
|
_selections_completed_timer.start()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_element_focused(element:InventoryElement, inventory_player_index:int, _displayPanelData: bool = true) -> void:
|
||||||
|
._on_element_focused(element, inventory_player_index)
|
||||||
|
|
||||||
|
if is_multiplayer_lobby:
|
||||||
|
var element_string = ""
|
||||||
|
if element.item != null:
|
||||||
|
element_string = element.item.my_id
|
||||||
|
elif element.is_random:
|
||||||
|
element_string = "RANDOM"
|
||||||
|
|
||||||
|
if not external_focus:
|
||||||
|
steam_connection.weapon_focused(element_string)
|
||||||
|
else:
|
||||||
|
external_focus = false
|
||||||
|
|
||||||
|
|
||||||
|
func _player_focused_weapon(player_index : int , weapon : String) -> void:
|
||||||
|
var selected_item = null
|
||||||
|
if selections_by_string_key.has(weapon):
|
||||||
|
selected_item = selections_by_string_key[weapon]
|
||||||
|
|
||||||
|
var focused_weapon = null
|
||||||
|
if inventory_maps[player_index].has(weapon):
|
||||||
|
focused_weapon = inventory_maps[player_index][weapon]
|
||||||
|
|
||||||
|
if focused_weapon != null:
|
||||||
|
if Utils.get_focus_emulator(player_index).focused_control != focused_weapon:
|
||||||
|
external_focus = true
|
||||||
|
Utils.get_focus_emulator(player_index).focused_control = focused_weapon
|
||||||
|
|
||||||
|
_player_weapons[player_index] = selected_item
|
||||||
|
_clear_selected_element(player_index)
|
||||||
|
|
||||||
|
var panel = _get_panels()[player_index]
|
||||||
|
if panel.visible:
|
||||||
|
# TODO handle randoms
|
||||||
|
if selected_item != null:
|
||||||
|
panel.set_data(selected_item, player_index)
|
||||||
|
|
||||||
|
|
||||||
|
func _player_selected_weapon(player_index : int) -> void:
|
||||||
|
_set_selected_element(player_index)
|
||||||
|
|
||||||
|
|
||||||
|
func _set_selected_element(p_player_index:int) -> void:
|
||||||
|
if _has_player_selected[p_player_index]:
|
||||||
|
return
|
||||||
|
|
||||||
|
# This happens during the base _ready for characters with no weapon slots.
|
||||||
|
if not steam_connection:
|
||||||
|
_has_player_selected[p_player_index] = true
|
||||||
|
return
|
||||||
|
|
||||||
|
._set_selected_element(p_player_index)
|
||||||
|
|
||||||
|
if brotatogether_options.is_solo_test:
|
||||||
|
var all_selected = true
|
||||||
|
for i in RunData.get_player_count():
|
||||||
|
if not _has_player_selected[i]:
|
||||||
|
all_selected = false
|
||||||
|
break
|
||||||
|
if all_selected:
|
||||||
|
CoopService.listening_for_inputs = false
|
||||||
|
_selections_completed_timer.start()
|
||||||
|
|
||||||
|
if steam_connection.get_lobby_index_for_player(steam_connection.steam_id) == p_player_index:
|
||||||
|
steam_connection.weapon_selected()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_selections_completed() -> void:
|
||||||
|
if is_multiplayer_lobby:
|
||||||
|
if not steam_connection.is_host():
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
._on_selections_completed()
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
for player_index in RunData.get_player_count():
|
||||||
|
var chosen_item = _get_panels()[player_index]
|
||||||
|
var weapon = _player_weapons[player_index]
|
||||||
|
|
||||||
|
if chosen_item.item_data == null or weapon == null:
|
||||||
|
var available_elements: = []
|
||||||
|
for element in displayed_elements[player_index]:
|
||||||
|
if not element.is_locked:
|
||||||
|
available_elements.push_back(element)
|
||||||
|
weapon = Utils.get_rand_element(available_elements)
|
||||||
|
_player_weapons[player_index] = weapon
|
||||||
|
|
||||||
|
if weapon:
|
||||||
|
var _weapon = RunData.add_weapon(weapon, player_index, true)
|
||||||
|
|
||||||
|
RunData.add_starting_items_and_weapons()
|
||||||
|
|
||||||
|
var all_selected_weapons = []
|
||||||
|
for player_index in RunData.get_player_count():
|
||||||
|
var selected_weapons = []
|
||||||
|
for owned_weapon in RunData.players_data[player_index].weapons:
|
||||||
|
selected_weapons.push_back(weapon_item_to_string(owned_weapon))
|
||||||
|
all_selected_weapons.push_back(selected_weapons)
|
||||||
|
|
||||||
|
steam_connection.send_weapon_selection_completed(all_selected_weapons)
|
||||||
|
|
||||||
|
_change_scene(MenuData.difficulty_selection_scene)
|
||||||
|
|
||||||
|
|
||||||
|
func _weapon_selection_completed(selected_weapons : Array) -> void:
|
||||||
|
for player_index in RunData.get_player_count():
|
||||||
|
RunData.players_data[player_index].weapons.clear()
|
||||||
|
for weapon_index in selected_weapons[player_index].size():
|
||||||
|
RunData.players_data[player_index].weapons.push_back(selections_by_string_key[selected_weapons[player_index][weapon_index]])
|
||||||
|
|
||||||
|
_change_scene(MenuData.difficulty_selection_scene)
|
||||||
@@ -0,0 +1,643 @@
|
|||||||
|
extends "res://ui/menus/shop/coop_shop.gd"
|
||||||
|
|
||||||
|
|
||||||
|
var steam_connection
|
||||||
|
var brotatogether_options
|
||||||
|
|
||||||
|
var in_multiplayer_game = false
|
||||||
|
|
||||||
|
# If true, the steam logic will be skipped to avoid duplicate rpc chains.
|
||||||
|
var is_self_call = false
|
||||||
|
|
||||||
|
var player_in_scene = [true, false, false, false]
|
||||||
|
var waiting_to_start_shop = false
|
||||||
|
|
||||||
|
var focusing_reroll_button = false
|
||||||
|
var focusing_go_button = false
|
||||||
|
|
||||||
|
# Force clients to update their focus, this syncs up focus after inventory
|
||||||
|
# changes (buys, discards, etc) and prevents the client focus from disappearing
|
||||||
|
var pending_force_focus = []
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
steam_connection = $"/root/SteamConnection"
|
||||||
|
|
||||||
|
brotatogether_options = $"/root/BrotogetherOptions"
|
||||||
|
in_multiplayer_game = brotatogether_options.in_multiplayer_game
|
||||||
|
|
||||||
|
if in_multiplayer_game:
|
||||||
|
waiting_to_start_shop = true
|
||||||
|
|
||||||
|
steam_connection.connect("client_status_received", self, "_client_status_received")
|
||||||
|
steam_connection.connect("shop_lobby_update", self, "_update_shop")
|
||||||
|
steam_connection.connect("client_shop_focus_updated", self, "_client_shop_focus_updated")
|
||||||
|
steam_connection.connect("client_shop_go_button_pressed", self, "_client_shop_go_button_pressed")
|
||||||
|
steam_connection.connect("client_shop_discard_weapon", self, "_client_shop_discard_weapon")
|
||||||
|
steam_connection.connect("client_shop_combine_weapon", self, "_client_shop_combine_weapon")
|
||||||
|
steam_connection.connect("client_shop_buy_item", self, "_client_shop_buy_item")
|
||||||
|
steam_connection.connect("client_shop_reroll", self, "_client_shop_reroll")
|
||||||
|
steam_connection.connect("client_shop_lock_item", self, "_client_shop_lock_item")
|
||||||
|
steam_connection.connect("client_shop_unlock_item", self, "_client_shop_unlock_item")
|
||||||
|
steam_connection.connect("client_shop_focus_inventory_element", self, "_client_focused_inventory_element")
|
||||||
|
steam_connection.connect("client_shop_requested", self, "send_shop_state")
|
||||||
|
steam_connection.connect("close_popup", self, "_remote_close_client_popup")
|
||||||
|
steam_connection.connect("receive_leave_shop", self, "_receive_leave_shop")
|
||||||
|
|
||||||
|
if steam_connection.is_host():
|
||||||
|
steam_connection.send_host_entered_shop()
|
||||||
|
|
||||||
|
|
||||||
|
func _process(_delta):
|
||||||
|
if in_multiplayer_game:
|
||||||
|
if waiting_to_start_shop:
|
||||||
|
if steam_connection.is_host():
|
||||||
|
var all_players_entered = true
|
||||||
|
for player_index in RunData.get_player_count():
|
||||||
|
if not player_in_scene[player_index]:
|
||||||
|
all_players_entered = false
|
||||||
|
break
|
||||||
|
if all_players_entered:
|
||||||
|
waiting_to_start_shop = false
|
||||||
|
|
||||||
|
# Initial shop state, all players can break focus
|
||||||
|
send_shop_state([0,1,2,3])
|
||||||
|
_check_for_focus_change()
|
||||||
|
|
||||||
|
|
||||||
|
func _client_status_received(client_data : Dictionary, player_index : int) -> void:
|
||||||
|
if waiting_to_start_shop:
|
||||||
|
if client_data["CURRENT_SCENE"] == get_tree().current_scene.name:
|
||||||
|
player_in_scene[player_index] = true
|
||||||
|
|
||||||
|
|
||||||
|
func _on_element_focused(element: InventoryElement, player_index: int)->void :
|
||||||
|
._on_element_focused(element,player_index)
|
||||||
|
|
||||||
|
if in_multiplayer_game:
|
||||||
|
if is_self_call:
|
||||||
|
is_self_call = false
|
||||||
|
else:
|
||||||
|
var focus_string = _dictionary_for_focus_inventory_element(element, player_index)
|
||||||
|
steam_connection.shop_focus_inventory_element(focus_string)
|
||||||
|
|
||||||
|
|
||||||
|
func _client_shop_focus_updated(shop_item_string : String, player_index : int) -> void:
|
||||||
|
is_self_call = true
|
||||||
|
|
||||||
|
var shop_item : ShopItem = _shop_item_for_string(shop_item_string, player_index)
|
||||||
|
if shop_item:
|
||||||
|
Utils.get_focus_emulator(player_index).focused_control = shop_item._button
|
||||||
|
|
||||||
|
|
||||||
|
func _on_shop_item_focused(shop_item: ShopItem, player_index : int) -> void:
|
||||||
|
if in_multiplayer_game:
|
||||||
|
var is_me = player_index == steam_connection.get_my_index()
|
||||||
|
if waiting_to_start_shop and not is_me:
|
||||||
|
return
|
||||||
|
._on_shop_item_focused(shop_item, player_index)
|
||||||
|
if is_self_call:
|
||||||
|
is_self_call = false
|
||||||
|
elif is_me or steam_connection.is_host():
|
||||||
|
var players_to_force = pending_force_focus.duplicate()
|
||||||
|
pending_force_focus.clear()
|
||||||
|
steam_connection.shop_item_focused(_string_for_shop_item(shop_item), players_to_force)
|
||||||
|
else:
|
||||||
|
._on_shop_item_focused(shop_item, player_index)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_item_discard_button_pressed(weapon_data: WeaponData, player_index: int)->void :
|
||||||
|
if in_multiplayer_game:
|
||||||
|
if steam_connection.is_host():
|
||||||
|
._on_item_discard_button_pressed(weapon_data, player_index)
|
||||||
|
pending_force_focus.push_back(player_index)
|
||||||
|
steam_connection.shop_weapon_discard(_string_for_weapon(weapon_data), player_index)
|
||||||
|
else:
|
||||||
|
._on_item_discard_button_pressed(weapon_data, player_index)
|
||||||
|
|
||||||
|
|
||||||
|
func _client_shop_discard_weapon(weapon_string : String, player_index : int) -> void:
|
||||||
|
_on_item_discard_button_pressed(_weapon_for_string(weapon_string, player_index), player_index)
|
||||||
|
steam_connection.request_close_client_shop_popup(player_index)
|
||||||
|
|
||||||
|
|
||||||
|
func _remote_close_client_popup() -> void:
|
||||||
|
_get_coop_player_container(steam_connection.get_my_index()).item_popup.cancel()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_GoButton_pressed(player_index: int) -> void:
|
||||||
|
if in_multiplayer_game:
|
||||||
|
if steam_connection.is_host():
|
||||||
|
_on_go_button_pressed_brotatogether(player_index)
|
||||||
|
steam_connection.shop_go_button_pressed(not _player_pressed_go_button[player_index])
|
||||||
|
else:
|
||||||
|
._on_GoButton_pressed(player_index)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_go_button_pressed_brotatogether(player_index: int)->void :
|
||||||
|
if get_tree().paused:
|
||||||
|
return
|
||||||
|
|
||||||
|
if _player_pressed_go_button[player_index]:
|
||||||
|
_clear_go_button_pressed(player_index)
|
||||||
|
return
|
||||||
|
|
||||||
|
_player_pressed_go_button[player_index] = true
|
||||||
|
var checkmark = _get_checkmark(player_index)
|
||||||
|
if checkmark != null:
|
||||||
|
checkmark.show()
|
||||||
|
|
||||||
|
for other_player_index in RunData.get_player_count():
|
||||||
|
if not _player_pressed_go_button[other_player_index]:
|
||||||
|
return
|
||||||
|
|
||||||
|
RunData.current_wave += 1
|
||||||
|
steam_connection.leave_shop()
|
||||||
|
var _error = get_tree().change_scene(MenuData.game_scene)
|
||||||
|
|
||||||
|
|
||||||
|
func _receive_leave_shop() -> void:
|
||||||
|
RunData.current_wave += 1
|
||||||
|
var _error = get_tree().change_scene(MenuData.game_scene)
|
||||||
|
|
||||||
|
|
||||||
|
func _clear_go_button_pressed(player_index: int) -> void :
|
||||||
|
if in_multiplayer_game:
|
||||||
|
if steam_connection.is_host():
|
||||||
|
._clear_go_button_pressed(player_index)
|
||||||
|
steam_connection.shop_go_button_pressed(false)
|
||||||
|
else:
|
||||||
|
._clear_go_button_pressed(player_index)
|
||||||
|
|
||||||
|
|
||||||
|
func _client_shop_go_button_pressed(latest_go_state : bool, player_index : int) -> void:
|
||||||
|
# Make the go function change the state to the new state by setting to the
|
||||||
|
# opposite
|
||||||
|
_player_pressed_go_button[player_index] = not latest_go_state
|
||||||
|
_on_GoButton_pressed(player_index)
|
||||||
|
|
||||||
|
|
||||||
|
func on_shop_item_bought(shop_item: ShopItem, player_index: int) -> void:
|
||||||
|
if in_multiplayer_game:
|
||||||
|
if steam_connection.is_host():
|
||||||
|
.on_shop_item_bought(shop_item, player_index)
|
||||||
|
pending_force_focus.push_back(player_index)
|
||||||
|
steam_connection.shop_buy_item(_string_for_shop_item(shop_item), player_index)
|
||||||
|
else:
|
||||||
|
.on_shop_item_bought(shop_item, player_index)
|
||||||
|
|
||||||
|
|
||||||
|
func _client_shop_buy_item(item_string : String, player_index : int) -> void:
|
||||||
|
_get_shop_items_container(player_index).on_shop_item_buy_button_pressed(_shop_item_for_string(item_string, player_index))
|
||||||
|
|
||||||
|
|
||||||
|
func _on_item_combine_button_pressed(weapon_data: WeaponData, player_index: int)->void :
|
||||||
|
if in_multiplayer_game:
|
||||||
|
if steam_connection.is_host():
|
||||||
|
pending_force_focus.push_back(player_index)
|
||||||
|
._on_item_combine_button_pressed(weapon_data, player_index)
|
||||||
|
steam_connection.shop_combine_weapon(_string_for_weapon(weapon_data), false, player_index)
|
||||||
|
else:
|
||||||
|
._on_item_combine_button_pressed(weapon_data, player_index)
|
||||||
|
|
||||||
|
|
||||||
|
func _client_shop_combine_weapon(weapon_string : String, _is_upgrade: bool, player_index : int) -> void:
|
||||||
|
_on_item_combine_button_pressed(_weapon_for_string(weapon_string, player_index), player_index)
|
||||||
|
steam_connection.request_close_client_shop_popup(player_index)
|
||||||
|
|
||||||
|
|
||||||
|
func _client_shop_lock_item(item_string : String, _wave_value: int, player_index: int) -> void:
|
||||||
|
_shop_item_for_string(item_string, player_index).change_lock_status(true)
|
||||||
|
|
||||||
|
|
||||||
|
func _client_shop_unlock_item(item_string : String, player_index : int) -> void:
|
||||||
|
_shop_item_for_string(item_string, player_index).change_lock_status(false)
|
||||||
|
|
||||||
|
|
||||||
|
func send_shop_state(changed_shop_player_indeces : Array = []) -> void:
|
||||||
|
var result_dict : Dictionary = {}
|
||||||
|
var abyssal_dlc = ProgressData.get_dlc_data("abyssal_terrors")
|
||||||
|
|
||||||
|
var players_array = []
|
||||||
|
var player_count: int = RunData.get_player_count()
|
||||||
|
for player_index in player_count:
|
||||||
|
var player_data = RunData.players_data[player_index]
|
||||||
|
var player_dict = {}
|
||||||
|
var shop_items = []
|
||||||
|
for item in _shop_items[player_index]:
|
||||||
|
var item_dict : Dictionary = {}
|
||||||
|
|
||||||
|
item_dict["ID"] = item[0].my_id
|
||||||
|
item_dict["WAVE_VALUE"] = item[1]
|
||||||
|
|
||||||
|
if abyssal_dlc:
|
||||||
|
if item[0].is_cursed:
|
||||||
|
item_dict["CURSED"] = true
|
||||||
|
|
||||||
|
shop_items.push_back(item_dict)
|
||||||
|
player_dict["SHOP_ITEMS"] = shop_items
|
||||||
|
|
||||||
|
player_dict["EFFECTS"] = player_data._serialize_effects(player_data.effects)
|
||||||
|
var active_sets = {}
|
||||||
|
for set in player_data.active_sets:
|
||||||
|
active_sets[set] = player_data.active_sets[set]
|
||||||
|
player_dict["ACTIVE_SETS"] = active_sets
|
||||||
|
|
||||||
|
var locked_items : Array = []
|
||||||
|
for item in RunData.locked_shop_items[player_index]:
|
||||||
|
var item_dict : Dictionary = {}
|
||||||
|
item_dict["ID"] = item[0].my_id
|
||||||
|
item_dict["WAVE_VALUE"] = item[1]
|
||||||
|
locked_items.push_back(item_dict)
|
||||||
|
player_dict["LOCKED_ITEMS"] = locked_items
|
||||||
|
|
||||||
|
var weapons_array = []
|
||||||
|
for weapon in RunData.get_player_weapons(player_index):
|
||||||
|
weapons_array.push_back(_dictionary_for_weapon(weapon))
|
||||||
|
player_dict["WEAPONS"] = weapons_array
|
||||||
|
player_dict["GO_PRESSED"] = _player_pressed_go_button[player_index]
|
||||||
|
|
||||||
|
var gear_container : PlayerGearContainer = _get_gear_container(player_index)
|
||||||
|
var items_array = []
|
||||||
|
for element in gear_container.items_container._elements.get_children():
|
||||||
|
items_array.push_back(_dictionary_for_inventory_item(element))
|
||||||
|
# print_debug("shop container has ", element.item.my_id)
|
||||||
|
player_dict["ITEMS"] = items_array
|
||||||
|
|
||||||
|
player_dict["GOLD"] = RunData.get_player_gold(player_index)
|
||||||
|
player_dict["FOCUS"] = _focus_dictionary_for_player(player_index)
|
||||||
|
|
||||||
|
player_dict["REROLL_PRICE"] = _reroll_price[player_index]
|
||||||
|
player_dict["REROLL_DICSOUNT"] = _reroll_discount[player_index]
|
||||||
|
player_dict["HAS_BONUS_FREE_REROLL"] = _has_bonus_free_reroll[player_index]
|
||||||
|
|
||||||
|
|
||||||
|
players_array.push_back(player_dict)
|
||||||
|
|
||||||
|
result_dict["PLAYERS"] = players_array
|
||||||
|
result_dict["CHANGED_PLAYERS"] = changed_shop_player_indeces
|
||||||
|
|
||||||
|
# print_debug("sending shop state with dict ", result_dict)
|
||||||
|
steam_connection.send_shop_update(result_dict)
|
||||||
|
|
||||||
|
|
||||||
|
func _update_shop(shop_dictionary : Dictionary) -> void:
|
||||||
|
if not shop_dictionary.has("PLAYERS"):
|
||||||
|
print("WARNING - received shop update without PLAYERS element, ignoring; data:", shop_dictionary)
|
||||||
|
return
|
||||||
|
|
||||||
|
if steam_connection.is_host():
|
||||||
|
print("WARNING - host shouldn't be updating for remote, returning; data:", shop_dictionary)
|
||||||
|
return
|
||||||
|
|
||||||
|
# print_debug("updating shop for dictionary - ", shop_dictionary)
|
||||||
|
|
||||||
|
for player_index in shop_dictionary["PLAYERS"].size():
|
||||||
|
var player_dict = shop_dictionary["PLAYERS"][player_index]
|
||||||
|
|
||||||
|
var is_me = steam_connection.get_my_index() == player_index
|
||||||
|
var can_update = not is_me or shop_dictionary["CHANGED_PLAYERS"].has(player_index)
|
||||||
|
|
||||||
|
var go_pressed = player_dict["GO_PRESSED"]
|
||||||
|
_player_pressed_go_button[player_index] = go_pressed
|
||||||
|
var checkmark = _get_checkmark(player_index)
|
||||||
|
if checkmark != null:
|
||||||
|
if go_pressed:
|
||||||
|
checkmark.show()
|
||||||
|
else:
|
||||||
|
checkmark.hide()
|
||||||
|
|
||||||
|
if not can_update:
|
||||||
|
# print_debug("skipping update for player ", player_index)
|
||||||
|
continue
|
||||||
|
|
||||||
|
Utils.get_focus_emulator(player_index)._clear_focused_control()
|
||||||
|
_shop_items[player_index].clear()
|
||||||
|
Utils.reset_stat_cache(player_index)
|
||||||
|
var player_data = RunData.players_data[player_index]
|
||||||
|
|
||||||
|
var reserilaized_effects = {}
|
||||||
|
for key in player_dict["EFFECTS"]:
|
||||||
|
reserilaized_effects[str(key)] = player_dict["EFFECTS"][key]
|
||||||
|
player_data.effects = player_data._deserialize_effects(reserilaized_effects, {})
|
||||||
|
|
||||||
|
player_data.active_sets.clear()
|
||||||
|
var active_sets_dict = player_dict["ACTIVE_SETS"]
|
||||||
|
for active_set in player_dict["ACTIVE_SETS"]:
|
||||||
|
player_data.active_sets[active_set] = active_sets_dict[active_set]
|
||||||
|
|
||||||
|
for shop_item_dict in player_dict["SHOP_ITEMS"]:
|
||||||
|
_shop_items[player_index].push_back(_shop_item_for_dictionary(shop_item_dict))
|
||||||
|
_get_shop_items_container(player_index).set_shop_items(_shop_items[player_index])
|
||||||
|
|
||||||
|
var player_gear_container = _get_gear_container(player_index)
|
||||||
|
|
||||||
|
RunData.players_data[player_index].weapons.clear()
|
||||||
|
for weapon in player_dict["WEAPONS"]:
|
||||||
|
RunData.players_data[player_index].weapons.push_back(_weapon_for_dictionary(weapon))
|
||||||
|
player_gear_container.set_weapons_data(RunData.players_data[player_index].weapons)
|
||||||
|
|
||||||
|
RunData.players_data[player_index].items.clear()
|
||||||
|
for item in player_dict["ITEMS"]:
|
||||||
|
for _i in item["NUMBER"]:
|
||||||
|
RunData.players_data[player_index].items.push_back(_inventory_item_for_dictionary(item))
|
||||||
|
player_gear_container.set_items_data(RunData.players_data[player_index].items)
|
||||||
|
|
||||||
|
|
||||||
|
if player_dict.has("FOCUS"):
|
||||||
|
_set_client_focus_for_player(player_dict["FOCUS"], player_index)
|
||||||
|
else:
|
||||||
|
print_debug("WARN - missing focus for player ", player_index, " ", player_dict)
|
||||||
|
|
||||||
|
_reroll_price[player_index] = player_dict["REROLL_PRICE"]
|
||||||
|
_reroll_discount[player_index] = player_dict["REROLL_DICSOUNT"]
|
||||||
|
_has_bonus_free_reroll[player_index] = player_dict["HAS_BONUS_FREE_REROLL"]
|
||||||
|
set_reroll_button_price(player_index)
|
||||||
|
|
||||||
|
var locked_items : Array = player_dict["LOCKED_ITEMS"]
|
||||||
|
for item in _get_shop_items_container(player_index).get_children():
|
||||||
|
if not item is ShopItem:
|
||||||
|
continue
|
||||||
|
|
||||||
|
var is_locked = false
|
||||||
|
for locked_item in locked_items:
|
||||||
|
if locked_item["ID"] == item.item_data.my_id:
|
||||||
|
is_locked = true
|
||||||
|
break
|
||||||
|
|
||||||
|
if is_locked:
|
||||||
|
item.lock_visually()
|
||||||
|
else:
|
||||||
|
item.unlock_visually()
|
||||||
|
|
||||||
|
RunData.players_data[player_index].gold = player_dict["GOLD"]
|
||||||
|
_get_gold_label(player_index).update_value(RunData.players_data[player_index].gold)
|
||||||
|
|
||||||
|
waiting_to_start_shop = false
|
||||||
|
|
||||||
|
|
||||||
|
func _dictionary_for_inventory_item(inventory_element : InventoryElement) -> Dictionary:
|
||||||
|
var item_data : ItemData = inventory_element.item
|
||||||
|
var item_dict = {
|
||||||
|
"ID" : item_data.my_id,
|
||||||
|
"NUMBER" : inventory_element.current_number,
|
||||||
|
}
|
||||||
|
|
||||||
|
var dlc = ProgressData.get_dlc_data("abyssal_terrors")
|
||||||
|
if dlc:
|
||||||
|
if item_data.is_cursed:
|
||||||
|
item_dict["CURSED"] = true
|
||||||
|
|
||||||
|
return item_dict
|
||||||
|
|
||||||
|
|
||||||
|
func _client_focused_inventory_element(data : Dictionary, player_index : int) -> void:
|
||||||
|
var focused_element = _focus_inventory_item_for_dictionary(data, player_index)
|
||||||
|
|
||||||
|
is_self_call = true
|
||||||
|
Utils.get_focus_emulator(player_index).focused_control = focused_element
|
||||||
|
|
||||||
|
|
||||||
|
func _dictionary_for_focus_inventory_element(element: InventoryElement, player_index : int) -> Dictionary:
|
||||||
|
var gear_container : PlayerGearContainer = _get_gear_container(player_index)
|
||||||
|
|
||||||
|
var weapons : Array = gear_container.weapons_container._elements.get_children()
|
||||||
|
for weapon_index in weapons.size():
|
||||||
|
if element == weapons[weapon_index]:
|
||||||
|
return {
|
||||||
|
"TYPE" : "WEAPON",
|
||||||
|
"INDEX" : weapon_index
|
||||||
|
}
|
||||||
|
|
||||||
|
var items : Array = gear_container.items_container._elements.get_children()
|
||||||
|
for item_index in items.size():
|
||||||
|
if element == items[item_index]:
|
||||||
|
return {
|
||||||
|
"TYPE" : "ITEM",
|
||||||
|
"INDEX" : item_index
|
||||||
|
}
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
func _focus_inventory_item_for_dictionary(item_dict : Dictionary, player_index : int) -> Control:
|
||||||
|
var gear_container : PlayerGearContainer = _get_gear_container(player_index)
|
||||||
|
|
||||||
|
var focus_type = item_dict["TYPE"]
|
||||||
|
if focus_type == "WEAPON":
|
||||||
|
var weapon_index = item_dict["INDEX"]
|
||||||
|
if weapon_index < gear_container.weapons_container._elements.get_children().size():
|
||||||
|
return gear_container.weapons_container._elements.get_children()[weapon_index]
|
||||||
|
elif focus_type == "ITEM":
|
||||||
|
return gear_container.items_container._elements.get_children()[item_dict["INDEX"]]
|
||||||
|
elif focus_type == "GO":
|
||||||
|
return _get_go_button(player_index)
|
||||||
|
elif focus_type == "REROLL":
|
||||||
|
return _get_reroll_button(player_index)
|
||||||
|
elif focus_type == "SHOP_ITEM":
|
||||||
|
var shop_item : ShopItem = _shop_item_for_string(item_dict["ID"], player_index)
|
||||||
|
if shop_item:
|
||||||
|
return shop_item._button
|
||||||
|
else:
|
||||||
|
print("ERR - Focusing inventgory element of unknown type ", item_dict)
|
||||||
|
|
||||||
|
print("ERR - failed to found focus for dict ", item_dict, " ", player_index)
|
||||||
|
return null
|
||||||
|
|
||||||
|
|
||||||
|
func _inventory_item_for_dictionary(item_dict : Dictionary) -> ItemData:
|
||||||
|
var query_id = item_dict["ID"]
|
||||||
|
|
||||||
|
var result
|
||||||
|
for item in ItemService.items:
|
||||||
|
if item.my_id == query_id:
|
||||||
|
result = item.duplicate()
|
||||||
|
|
||||||
|
for character in ItemService.characters:
|
||||||
|
if character.my_id == query_id:
|
||||||
|
result = character.duplicate()
|
||||||
|
|
||||||
|
var dlc = ProgressData.get_dlc_data("abyssal_terrors")
|
||||||
|
if dlc:
|
||||||
|
if item_dict.has("CURSED") and item_dict["CURSED"]:
|
||||||
|
result.is_cursed = true
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
func _dictionary_for_shop_item(shop_item : Array) -> Dictionary:
|
||||||
|
return {
|
||||||
|
"ID" : shop_item[0].my_id,
|
||||||
|
"WAVE_VALUE": shop_item[1],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func _shop_item_for_dictionary(shop_item_dict : Dictionary) -> Array:
|
||||||
|
var item_element
|
||||||
|
|
||||||
|
var query_id = shop_item_dict["ID"]
|
||||||
|
for item in ItemService.items:
|
||||||
|
if item.my_id == query_id:
|
||||||
|
item_element = item.duplicate()
|
||||||
|
for weapon in ItemService.weapons:
|
||||||
|
if weapon.my_id == query_id:
|
||||||
|
item_element = weapon.duplicate()
|
||||||
|
|
||||||
|
var abyssal_dlc = ProgressData.get_dlc_data("abyssal_terrors")
|
||||||
|
if abyssal_dlc:
|
||||||
|
if shop_item_dict.has("CURSED") and shop_item_dict["CURSED"]:
|
||||||
|
item_element.is_cursed = true
|
||||||
|
|
||||||
|
return [item_element, shop_item_dict["WAVE_VALUE"]]
|
||||||
|
|
||||||
|
|
||||||
|
func _dictionary_for_weapon(weapon_data : WeaponData) -> Dictionary:
|
||||||
|
var weapon_dict = {
|
||||||
|
"ID" : weapon_data.my_id
|
||||||
|
}
|
||||||
|
|
||||||
|
var dlc = ProgressData.get_dlc_data("abyssal_terrors")
|
||||||
|
if dlc:
|
||||||
|
if weapon_data.is_cursed:
|
||||||
|
weapon_dict["CURSED"] = true
|
||||||
|
|
||||||
|
return weapon_dict
|
||||||
|
|
||||||
|
|
||||||
|
func _weapon_for_dictionary(weapon_dict : Dictionary) -> WeaponData:
|
||||||
|
var query_id = weapon_dict["ID"]
|
||||||
|
|
||||||
|
var result
|
||||||
|
for weapon in ItemService.weapons:
|
||||||
|
if weapon.my_id == query_id:
|
||||||
|
result = weapon.duplicate()
|
||||||
|
|
||||||
|
var dlc = ProgressData.get_dlc_data("abyssal_terrors")
|
||||||
|
if dlc and result:
|
||||||
|
if weapon_dict.has("CURSED") and weapon_dict["CURSED"]:
|
||||||
|
result.is_cursed = true
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
func _string_for_weapon(weapon_data : WeaponData) -> String:
|
||||||
|
return weapon_data.my_id
|
||||||
|
|
||||||
|
|
||||||
|
func _weapon_for_string(weapon_string : String, player_index : int) -> WeaponData:
|
||||||
|
for element in _get_gear_container(player_index).weapons_container._elements.get_children():
|
||||||
|
if _string_for_weapon(element.item) == weapon_string:
|
||||||
|
return element.item
|
||||||
|
return null
|
||||||
|
|
||||||
|
|
||||||
|
func _string_for_shop_item(shop_item : ShopItem) -> String:
|
||||||
|
return shop_item.item_data.my_id
|
||||||
|
|
||||||
|
|
||||||
|
func _shop_item_for_string(shop_item_string : String, player_index : int) -> ShopItem:
|
||||||
|
for item in _get_shop_items_container(player_index).get_children():
|
||||||
|
if not item is ShopItem:
|
||||||
|
continue
|
||||||
|
if item.item_data.my_id == shop_item_string:
|
||||||
|
return item
|
||||||
|
|
||||||
|
return null
|
||||||
|
|
||||||
|
|
||||||
|
func fill_shop_items(player_locked_items: Array, player_index: int, just_entered_shop: bool = false) -> void:
|
||||||
|
if $"/root/BrotogetherOptions".in_multiplayer_game:
|
||||||
|
if $"/root/SteamConnection".is_host():
|
||||||
|
.fill_shop_items(player_locked_items, player_index, just_entered_shop)
|
||||||
|
else:
|
||||||
|
.fill_shop_items(player_locked_items, player_index, just_entered_shop)
|
||||||
|
|
||||||
|
|
||||||
|
func _focus_dictionary_for_player(player_index : int) -> Dictionary:
|
||||||
|
var focused_control : Control = Utils.get_focus_emulator(player_index).focused_control
|
||||||
|
for shop_item in _get_shop_items_container(player_index).get_children():
|
||||||
|
if not shop_item is ShopItem:
|
||||||
|
continue
|
||||||
|
if shop_item._button == focused_control:
|
||||||
|
return {
|
||||||
|
"TYPE" : "SHOP_ITEM",
|
||||||
|
"ID" : _string_for_shop_item(shop_item)
|
||||||
|
}
|
||||||
|
|
||||||
|
var gear_container : PlayerGearContainer = _get_gear_container(player_index)
|
||||||
|
var weapons : Array = gear_container.weapons_container._elements.get_children()
|
||||||
|
for weapon_index in weapons.size():
|
||||||
|
if focused_control == weapons[weapon_index]:
|
||||||
|
return {
|
||||||
|
"TYPE" : "WEAPON",
|
||||||
|
"INDEX" : weapon_index
|
||||||
|
}
|
||||||
|
|
||||||
|
var items : Array = gear_container.items_container._elements.get_children()
|
||||||
|
for item_index in items.size():
|
||||||
|
if focused_control == items[item_index]:
|
||||||
|
return {
|
||||||
|
"TYPE" : "ITEM",
|
||||||
|
"INDEX" : item_index
|
||||||
|
}
|
||||||
|
|
||||||
|
if focused_control == _get_go_button(player_index):
|
||||||
|
return {
|
||||||
|
"TYPE" : "GO",
|
||||||
|
}
|
||||||
|
|
||||||
|
if focused_control == _get_reroll_button(player_index):
|
||||||
|
return {
|
||||||
|
"TYPE" : "REROLL",
|
||||||
|
}
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
func _set_client_focus_for_player(focus_dict : Dictionary, player_index : int) -> void:
|
||||||
|
if not focus_dict.has("TYPE"):
|
||||||
|
print("ERR - unkown client focus ", player_index, " ", focus_dict)
|
||||||
|
return
|
||||||
|
|
||||||
|
var focus_control = _focus_inventory_item_for_dictionary(focus_dict, player_index)
|
||||||
|
if focus_control != null and is_instance_valid(focus_control):
|
||||||
|
var focus_type : String = focus_dict["TYPE"]
|
||||||
|
if focus_type in ["SHOP_ITEM", "ITEM", "WEAPON"]:
|
||||||
|
is_self_call = true
|
||||||
|
Utils.get_focus_emulator(player_index).focused_control = focus_control
|
||||||
|
else:
|
||||||
|
print("ERR - Invalid focus dict", focus_dict, " ", player_index)
|
||||||
|
|
||||||
|
|
||||||
|
# Process time check for focusing reroll or go buttons which don't have
|
||||||
|
# exisiting connected functions
|
||||||
|
func _check_for_focus_change() -> void:
|
||||||
|
var player_index : int = steam_connection.get_my_index()
|
||||||
|
var focused_control = Utils.get_focus_emulator(player_index).focused_control
|
||||||
|
|
||||||
|
if focused_control == _get_reroll_button(player_index):
|
||||||
|
if not focusing_reroll_button and not waiting_to_start_shop:
|
||||||
|
steam_connection.shop_focus_inventory_element(_focus_dictionary_for_player(player_index))
|
||||||
|
focusing_reroll_button = true
|
||||||
|
else:
|
||||||
|
focusing_reroll_button = false
|
||||||
|
|
||||||
|
if focused_control == _get_go_button(player_index):
|
||||||
|
if not focusing_go_button and not waiting_to_start_shop:
|
||||||
|
steam_connection.shop_focus_inventory_element(_focus_dictionary_for_player(player_index))
|
||||||
|
focusing_go_button = true
|
||||||
|
else:
|
||||||
|
focusing_go_button = false
|
||||||
|
|
||||||
|
|
||||||
|
func _client_shop_reroll(player_index : int) -> void:
|
||||||
|
_on_RerollButton_pressed(player_index)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_RerollButton_pressed(player_index: int)->void :
|
||||||
|
if in_multiplayer_game:
|
||||||
|
if steam_connection.is_host():
|
||||||
|
._on_RerollButton_pressed(player_index)
|
||||||
|
steam_connection.shop_reroll(player_index)
|
||||||
|
else:
|
||||||
|
._on_RerollButton_pressed( player_index)
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
extends "res://ui/menus/shop/player_gear_container.gd"
|
||||||
|
|
||||||
|
var steam_connection
|
||||||
|
var brotatogether_options
|
||||||
|
|
||||||
|
var in_multiplayer_game = false
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
steam_connection = $"/root/SteamConnection"
|
||||||
|
brotatogether_options = $"/root/BrotogetherOptions"
|
||||||
|
in_multiplayer_game = brotatogether_options.in_multiplayer_game
|
||||||
|
|
||||||
|
|
||||||
|
func set_items_data(items: Array)->void :
|
||||||
|
if in_multiplayer_game:
|
||||||
|
items_container.set_data("ITEMS", Category.ITEM, items, false, true)
|
||||||
|
else:
|
||||||
|
.set_items_data(items)
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
extends "res://ui/menus/shop/shop.gd"
|
||||||
|
|
||||||
|
# Empty extension to help some extension chaos
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
extends "res://ui/menus/shop/shop_item.gd"
|
||||||
|
|
||||||
|
var steam_connection
|
||||||
|
var brotatogether_options
|
||||||
|
|
||||||
|
var in_multiplayer_game = false
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
steam_connection = $"/root/SteamConnection"
|
||||||
|
brotatogether_options = $"/root/BrotogetherOptions"
|
||||||
|
in_multiplayer_game = brotatogether_options.in_multiplayer_game
|
||||||
|
|
||||||
|
|
||||||
|
func deactivate()->void :
|
||||||
|
if in_multiplayer_game:
|
||||||
|
if steam_connection.is_host():
|
||||||
|
.deactivate()
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
modulate = Color(1, 1, 1, 0)
|
||||||
|
_button.disable()
|
||||||
|
_lock_icon.hide()
|
||||||
|
locked = false
|
||||||
|
active = false
|
||||||
|
emit_signal("shop_item_deactivated", self)
|
||||||
|
else:
|
||||||
|
.deactivate()
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
extends "res://visual_effects/floating_text/floating_text_manager.gd"
|
||||||
|
|
||||||
|
var steam_connection
|
||||||
|
var brotatogether_options
|
||||||
|
var in_multiplayer_game = false
|
||||||
|
var is_host = false
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
steam_connection = $"/root/SteamConnection"
|
||||||
|
brotatogether_options = $"/root/BrotogetherOptions"
|
||||||
|
in_multiplayer_game = brotatogether_options.in_multiplayer_game
|
||||||
|
|
||||||
|
if in_multiplayer_game:
|
||||||
|
is_host = steam_connection.is_host()
|
||||||
|
|
||||||
|
|
||||||
|
func display(value: String, text_pos: Vector2, color: Color = Color.white, icon: Resource = null, p_duration: float = duration, always_display: bool = false, p_direction: Vector2 = direction, need_translate: bool = true, icon_scale: Vector2 = Vector2(0.5, 0.5))->void :
|
||||||
|
.display(value, text_pos, color, icon, p_duration, always_display, p_direction, need_translate, icon_scale)
|
||||||
|
|
||||||
|
if in_multiplayer_game and self.is_host:
|
||||||
|
var text_dict = {}
|
||||||
|
|
||||||
|
text_dict["X_POS"] = text_pos.x
|
||||||
|
text_dict["Y_POS"] = text_pos.y
|
||||||
|
text_dict["R_COLOR"] = color.r8
|
||||||
|
text_dict["G_COLOR"] = color.g8
|
||||||
|
text_dict["B_COLOR"] = color.b8
|
||||||
|
text_dict["A_COLOR"] = color.a8
|
||||||
|
text_dict["VALUE"] = value
|
||||||
|
text_dict["DURATION"] = p_duration
|
||||||
|
|
||||||
|
# brotatogether_options.batched_floating_text.push_back(text_dict)
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "Brogether",
|
"name": "Brogether",
|
||||||
"namespace": "Brogether",
|
"namespace": "Brogether",
|
||||||
"version_number": "0.1.0",
|
"version_number": "0.1.6",
|
||||||
"description": "Experimental 2-player online multiplayer foundation for Brotato using Steam lobbies and P2P packets.",
|
"description": "Experimental 2-player online multiplayer foundation for Brotato using Steam lobbies and P2P packets.",
|
||||||
"website_url": "https://git.mischlabs.de/MrDiderot/Brogether",
|
"website_url": "https://git.mischlabs.de/MrDiderot/Brogether",
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,27 @@
|
|||||||
|
extends Node
|
||||||
|
|
||||||
|
# Connection interface
|
||||||
|
|
||||||
|
func send_start_game(_game_info:Dictionary) -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
|
func send_display_floating_text(_text_info:Dictionary) -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
|
func send_display_hit_effect(_effect_info:Dictionary) -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
|
func send_enemy_death(_enemy_id:int) -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
|
func send_end_wave() -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
|
func send_flash_enemy(_enemy_id:int) -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
|
func send_flash_neutral(_neutral_id:int) -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
|
func send_client_position(_client_position: Dictionary) -> void:
|
||||||
|
pass
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
extends Node
|
||||||
|
|
||||||
|
var network_id
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
extends "res://mods-unpacked/Brogether-Brogether/networking/connection.gd"
|
||||||
|
|
||||||
|
var parent
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
var _error = get_tree().connect("network_peer_connected", self, "_player_connected")
|
||||||
|
_error = get_tree().connect("connected_to_server", self, "_connected_ok")
|
||||||
|
_error = get_tree().connect("connection_failed", self, "_connected_fail")
|
||||||
|
_error = get_tree().connect("server_disconnected", self, "_server_disconnected")
|
||||||
|
|
||||||
|
func _player_connected(_id):
|
||||||
|
rpc("register_player")
|
||||||
|
|
||||||
|
func _connected_ok():
|
||||||
|
var current_scene_name = get_tree().get_current_scene().get_name()
|
||||||
|
if current_scene_name == "MultiplayerMenu":
|
||||||
|
$"/root/MultiplayerMenu/HBoxContainer/InfoBox/Label".text = "connected"
|
||||||
|
parent.self_peer_id = get_tree().get_network_unique_id()
|
||||||
|
|
||||||
|
func _server_disconnected():
|
||||||
|
pass # Server kicked us; show error and abort.
|
||||||
|
|
||||||
|
func _connected_fail():
|
||||||
|
pass # Could not even connect to server; abort.
|
||||||
|
|
||||||
|
remotesync func register_player():
|
||||||
|
var id = get_tree().get_rpc_sender_id()
|
||||||
|
if parent.is_host and not parent.tracked_players.has(id):
|
||||||
|
parent.tracked_players[id] = {}
|
||||||
|
|
||||||
|
func send_state(game_state:Dictionary) -> void:
|
||||||
|
rpc("update_game_state", game_state)
|
||||||
|
|
||||||
|
remote func update_game_state(game_state:Dictionary) -> void:
|
||||||
|
parent.update_game_state(game_state)
|
||||||
|
|
||||||
|
func send_start_game(game_info:Dictionary) -> void:
|
||||||
|
rpc("start_game", game_info)
|
||||||
|
|
||||||
|
remote func start_game(game_info: Dictionary) -> void:
|
||||||
|
parent.start_game(game_info)
|
||||||
|
|
||||||
|
func send_display_floating_text(text_info:Dictionary) -> void:
|
||||||
|
rpc("display_floating_text", text_info)
|
||||||
|
|
||||||
|
remote func display_floating_text(text_info:Dictionary) -> void:
|
||||||
|
parent.display_floating_text(text_info)
|
||||||
|
|
||||||
|
func send_display_hit_effect(effect_info: Dictionary) -> void:
|
||||||
|
rpc("display_hit_effect", effect_info)
|
||||||
|
|
||||||
|
remote func display_hit_effect(effect_info: Dictionary) -> void:
|
||||||
|
parent.display_hit_effect(effect_info)
|
||||||
|
|
||||||
|
func send_enemy_death(enemy_id:int) -> void:
|
||||||
|
rpc("enemy_death", enemy_id)
|
||||||
|
|
||||||
|
remote func enemy_death(enemy_id:int) -> void:
|
||||||
|
parent.enemy_death(enemy_id)
|
||||||
|
|
||||||
|
func send_end_wave() -> void:
|
||||||
|
rpc("end_wave")
|
||||||
|
|
||||||
|
remote func end_wave() -> void:
|
||||||
|
parent.end_wave()
|
||||||
|
|
||||||
|
func send_more_enemies() -> void:
|
||||||
|
rpc("receive_more_enemies")
|
||||||
|
|
||||||
|
remote func receive_more_enemies() -> void:
|
||||||
|
parent.received_more_enemies(get_tree().get_rpc_sender_id())
|
||||||
|
|
||||||
|
func send_bought_item(shop_item:Resource) -> void:
|
||||||
|
rpc("receive_bought_item", shop_item.get_path())
|
||||||
|
|
||||||
|
remote func receive_bought_item(resource_path: String) -> void:
|
||||||
|
var sender_id = get_tree().get_rpc_sender_id()
|
||||||
|
var resource = load(resource_path)
|
||||||
|
parent.receive_bought_item(resource, sender_id)
|
||||||
|
|
||||||
|
func send_flash_enemy(enemy_id:int) -> void:
|
||||||
|
rpc("flash_enemy", enemy_id)
|
||||||
|
|
||||||
|
remote func flash_enemy(enemy_id:int) -> void:
|
||||||
|
parent.flash_enemy(enemy_id)
|
||||||
|
|
||||||
|
func send_flash_neutral(neutral_id:int) -> void:
|
||||||
|
rpc("flash_neutral", neutral_id)
|
||||||
|
|
||||||
|
remote func flash_neutral(neutral_id:int) -> void:
|
||||||
|
parent.flash_neutral(neutral_id)
|
||||||
|
|
||||||
|
func send_client_position(client_position:Dictionary) -> void:
|
||||||
|
rpc("update_client_position", client_position)
|
||||||
|
|
||||||
|
remote func update_client_position(client_position:Dictionary) -> void:
|
||||||
|
parent.update_client_position(client_position)
|
||||||
|
|
||||||
|
func send_ready(is_ready:bool) -> void:
|
||||||
|
rpc("ready", is_ready)
|
||||||
|
|
||||||
|
remote func ready(is_ready:bool) -> void:
|
||||||
|
var sender_id = get_tree().get_rpc_sender_id()
|
||||||
|
parent.update_ready_state(sender_id, is_ready)
|
||||||
|
|
||||||
|
func send_tracked_players(tracked_players:Dictionary) -> void:
|
||||||
|
rpc("update_tracked_players", tracked_players)
|
||||||
|
|
||||||
|
remote func update_tracked_players(tracked_players:Dictionary) -> void:
|
||||||
|
parent.update_tracked_players(tracked_players)
|
||||||
|
|
||||||
|
func send_health_update(current_health:int, max_health:int) -> void:
|
||||||
|
rpc("health_update", current_health, max_health)
|
||||||
|
|
||||||
|
remote func health_update(current_health:int, max_health:int) -> void:
|
||||||
|
var sender_id = get_tree().get_rpc_sender_id()
|
||||||
|
parent.receive_health_update(current_health, max_health, sender_id)
|
||||||
@@ -0,0 +1,946 @@
|
|||||||
|
extends Node
|
||||||
|
|
||||||
|
# here they'll be keyed by steam user ids
|
||||||
|
var tracked_players = {}
|
||||||
|
var connection
|
||||||
|
|
||||||
|
# tracked player info to be used in the multiplayer lobby
|
||||||
|
var lobby_data = {}
|
||||||
|
|
||||||
|
# The id of this player, in direct ip connections this will be 1 for the host.
|
||||||
|
# in steam connections this will be a steam id against which a username can
|
||||||
|
# be queried
|
||||||
|
var self_peer_id
|
||||||
|
|
||||||
|
# True iff the user hosted the lobby
|
||||||
|
var is_host = false
|
||||||
|
|
||||||
|
var is_source_of_truth = true
|
||||||
|
var game_mode = GameMode.VERSUS
|
||||||
|
|
||||||
|
enum GameMode {
|
||||||
|
VERSUS,
|
||||||
|
COOP,
|
||||||
|
}
|
||||||
|
|
||||||
|
# A counter user to assign ids for game components
|
||||||
|
var id_count = 0
|
||||||
|
|
||||||
|
var GameStateController = load("res://mods-unpacked/Brogether-Brogether/networking/game_state_controller.gd")
|
||||||
|
|
||||||
|
const toggle_scene = preload("res://mods-unpacked/Brogether-Brogether/ui/toggle.tscn")
|
||||||
|
const button_scene = preload("res://mods-unpacked/Brogether-Brogether/ui/button.tscn")
|
||||||
|
const explosion_scene = preload("res://projectiles/explosion.tscn")
|
||||||
|
|
||||||
|
const MOD_NAME = "Brogether-Brogether"
|
||||||
|
const CONFIG_FILENAME = "user://Brogether-Brogether-options.cfg"
|
||||||
|
const CONFIG_SECTION = "latest-mp-lobby"
|
||||||
|
|
||||||
|
var current_scene_name = ""
|
||||||
|
var run_updates = false
|
||||||
|
var disable_pause = false
|
||||||
|
var back_to_lobby = false
|
||||||
|
var all_players_ready = true
|
||||||
|
|
||||||
|
var batched_deaths = []
|
||||||
|
var batched_enemy_damage = []
|
||||||
|
var batched_flash_enemy = []
|
||||||
|
var batched_floating_text = []
|
||||||
|
var batched_hit_effects = []
|
||||||
|
|
||||||
|
var ready_toggle
|
||||||
|
|
||||||
|
var extra_enemies_next_wave = {}
|
||||||
|
var effects_next_wave = {}
|
||||||
|
var game_state_controller
|
||||||
|
|
||||||
|
var waiting_for_client_starts = false
|
||||||
|
|
||||||
|
signal complete_player_update
|
||||||
|
signal lobby_info_updated
|
||||||
|
signal danger_selected(danger_level)
|
||||||
|
signal character_selected(character_item_data)
|
||||||
|
signal weapon_selected(weapon_data)
|
||||||
|
|
||||||
|
|
||||||
|
func _init():
|
||||||
|
game_state_controller = GameStateController.new()
|
||||||
|
game_state_controller.parent = self
|
||||||
|
add_child(game_state_controller)
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
init_lobby_info()
|
||||||
|
|
||||||
|
|
||||||
|
func _process(_delta):
|
||||||
|
var scene_name = get_tree().get_current_scene().get_name()
|
||||||
|
# TODO: NOT THIS
|
||||||
|
if scene_name != current_scene_name:
|
||||||
|
if scene_name == "Shop":
|
||||||
|
enter_async_shop()
|
||||||
|
|
||||||
|
current_scene_name = scene_name
|
||||||
|
|
||||||
|
func init_client_starts_wait() -> void:
|
||||||
|
waiting_for_client_starts = true
|
||||||
|
for player in tracked_players:
|
||||||
|
if not player != self_peer_id:
|
||||||
|
tracked_players[player].in_game = false
|
||||||
|
receive_client_start(self_peer_id)
|
||||||
|
|
||||||
|
|
||||||
|
func init_lobby_info() -> void:
|
||||||
|
lobby_data = {}
|
||||||
|
lobby_data["players"] = {}
|
||||||
|
|
||||||
|
lobby_data["game_mode"] = 0
|
||||||
|
lobby_data["copy_host"] = false
|
||||||
|
lobby_data["first_death_loss"] = false
|
||||||
|
lobby_data["shared_gold"] = false
|
||||||
|
lobby_data["material_count"] = 1
|
||||||
|
lobby_data["enemy_count"] = 1
|
||||||
|
lobby_data["enemy_hp"] = 1
|
||||||
|
lobby_data["enemy_damage"] = 1
|
||||||
|
lobby_data["enemy_speed"] = 1
|
||||||
|
load_config()
|
||||||
|
|
||||||
|
|
||||||
|
func save_config() -> void:
|
||||||
|
var config := ConfigFile.new()
|
||||||
|
|
||||||
|
for key in lobby_data:
|
||||||
|
if key == "players":
|
||||||
|
continue
|
||||||
|
config.set_value(CONFIG_SECTION, key, lobby_data[key])
|
||||||
|
|
||||||
|
var _unused_save_result = config.save(CONFIG_FILENAME)
|
||||||
|
|
||||||
|
|
||||||
|
func load_config() -> void:
|
||||||
|
var config := ConfigFile.new()
|
||||||
|
var err = config.load(CONFIG_FILENAME)
|
||||||
|
|
||||||
|
if err != OK:
|
||||||
|
return
|
||||||
|
|
||||||
|
for key in config.get_section_keys(CONFIG_SECTION):
|
||||||
|
lobby_data[key] = config.get_value(CONFIG_SECTION, key)
|
||||||
|
|
||||||
|
|
||||||
|
func send_client_started() -> void:
|
||||||
|
connection.send_client_started()
|
||||||
|
|
||||||
|
|
||||||
|
func receive_client_start(player_id) -> void:
|
||||||
|
if not is_host:
|
||||||
|
return
|
||||||
|
|
||||||
|
if not waiting_for_client_starts:
|
||||||
|
return
|
||||||
|
|
||||||
|
tracked_players[player_id].in_game = true
|
||||||
|
|
||||||
|
var done_waiting = true
|
||||||
|
for player in tracked_players:
|
||||||
|
if not player != self_peer_id:
|
||||||
|
if not tracked_players[player].in_game:
|
||||||
|
done_waiting = false
|
||||||
|
break
|
||||||
|
|
||||||
|
if done_waiting:
|
||||||
|
waiting_for_client_starts = false
|
||||||
|
$"/root/Main"._wave_timer.set_paused(false)
|
||||||
|
$"/root/Main".send_updates = true
|
||||||
|
|
||||||
|
func enter_async_shop() -> void:
|
||||||
|
if $"/root/Shop/Content/MarginContainer/HBoxContainer/VBoxContainer2/StatsContainer":
|
||||||
|
$"/root/Shop/Content/MarginContainer/HBoxContainer/VBoxContainer2/StatsContainer".update_bought_items(tracked_players)
|
||||||
|
|
||||||
|
if is_host:
|
||||||
|
init_shop_go_button()
|
||||||
|
|
||||||
|
else:
|
||||||
|
$"/root/Shop/Content/MarginContainer/HBoxContainer/VBoxContainer2/GoButton".hide()
|
||||||
|
$"/root/Shop/Content/MarginContainer/HBoxContainer/VBoxContainer2".add_child(create_ready_toggle())
|
||||||
|
|
||||||
|
func create_extra_creatures_map() -> Dictionary:
|
||||||
|
var extra_creatures_map = {}
|
||||||
|
|
||||||
|
for player_id in tracked_players:
|
||||||
|
extra_creatures_map[player_id] = tracked_players[player_id]["extra_enemies_next_wave"]
|
||||||
|
return extra_creatures_map
|
||||||
|
|
||||||
|
func create_effects_map() -> Dictionary:
|
||||||
|
var effects_map = {}
|
||||||
|
|
||||||
|
for player_id in tracked_players:
|
||||||
|
effects_map[player_id] = tracked_players[player_id]["effects"]
|
||||||
|
|
||||||
|
return effects_map
|
||||||
|
|
||||||
|
func init_shop_go_button() -> void:
|
||||||
|
var shop = get_tree().get_current_scene()
|
||||||
|
var button = $"/root/Shop/Content/MarginContainer/HBoxContainer/VBoxContainer2/GoButton"
|
||||||
|
|
||||||
|
button.disconnect("pressed", shop, "_on_GoButton_pressed")
|
||||||
|
button.connect("pressed", self, "_on_GoButton_pressed")
|
||||||
|
|
||||||
|
update_go_button()
|
||||||
|
|
||||||
|
func _on_GoButton_pressed()-> void:
|
||||||
|
var shop = get_tree().get_current_scene()
|
||||||
|
if shop._go_button_pressed:
|
||||||
|
return
|
||||||
|
|
||||||
|
shop._go_button_pressed = true
|
||||||
|
|
||||||
|
extra_enemies_next_wave = create_extra_creatures_map()
|
||||||
|
effects_next_wave = create_effects_map()
|
||||||
|
|
||||||
|
RunData.current_wave += 1
|
||||||
|
MusicManager.tween(0)
|
||||||
|
|
||||||
|
var wave_data = {"current_wave":RunData.current_wave, "mode":game_mode}
|
||||||
|
var extra_creatures_map = extra_enemies_next_wave
|
||||||
|
|
||||||
|
wave_data["extra_enemies_next_wave"] = extra_creatures_map
|
||||||
|
wave_data["effects"] = effects_next_wave
|
||||||
|
|
||||||
|
send_start_game(wave_data)
|
||||||
|
reset_extra_creatures()
|
||||||
|
reset_ready_map()
|
||||||
|
|
||||||
|
# RunData.effects["extra_enemies_next_wave"] = tracked_players[self_peer_id]["extra_enemies_next_wave"]
|
||||||
|
|
||||||
|
var _error = get_tree().change_scene(MenuData.game_scene)
|
||||||
|
|
||||||
|
func init_all_player_data():
|
||||||
|
for player_id in tracked_players:
|
||||||
|
init_player_data(tracked_players[player_id], player_id)
|
||||||
|
|
||||||
|
func init_player_data(player:Dictionary, player_id) -> void:
|
||||||
|
var run_data = {}
|
||||||
|
|
||||||
|
# Randomly useful in places
|
||||||
|
run_data["player_id"] = player_id
|
||||||
|
|
||||||
|
run_data["effects"] = RunData.init_effects()
|
||||||
|
|
||||||
|
run_data["items"] = []
|
||||||
|
run_data["weapons"] = []
|
||||||
|
run_data["additional_weapon_effects"] = []
|
||||||
|
run_data["active_set_effects"] = []
|
||||||
|
run_data["gold"] = DebugService.starting_gold
|
||||||
|
run_data["current_xp"] = 0
|
||||||
|
run_data["current_level"] = 0
|
||||||
|
|
||||||
|
run_data["tier_i_weapon_effects"] = []
|
||||||
|
run_data["tier_iv_weapon_effects"] = []
|
||||||
|
|
||||||
|
run_data["unique_effects"] = []
|
||||||
|
run_data["appearances_displayed"] = []
|
||||||
|
run_data["tracked_item_effects"] = RunData.init_tracked_effects()
|
||||||
|
|
||||||
|
player["linked_stats"] = {}
|
||||||
|
player["consumables_to_process"] = []
|
||||||
|
player["linked_stats"]["stats"] = RunData.init_stats(true)
|
||||||
|
player["linked_stats"]["update_on_gold_chance"] = false
|
||||||
|
|
||||||
|
player["temp_stats"] = {}
|
||||||
|
player["temp_stats"]["stats"] = RunData.init_stats(true)
|
||||||
|
player["run_data"] = run_data
|
||||||
|
|
||||||
|
func start_game(_game_info: Dictionary):
|
||||||
|
print_debug("game controller game would have started here but we had to remove all the logic")
|
||||||
|
|
||||||
|
|
||||||
|
func send_death() -> void:
|
||||||
|
disable_pause = false
|
||||||
|
run_updates = false
|
||||||
|
if is_host:
|
||||||
|
receive_death(self_peer_id)
|
||||||
|
|
||||||
|
connection.send_death()
|
||||||
|
|
||||||
|
func receive_death(source_player_id:int) -> void:
|
||||||
|
tracked_players[source_player_id]["dead"] = true
|
||||||
|
if is_host:
|
||||||
|
connection.send_tracked_players(tracked_players)
|
||||||
|
if source_player_id != self_peer_id:
|
||||||
|
check_win()
|
||||||
|
|
||||||
|
func check_win() -> void:
|
||||||
|
var all_others_dead = true
|
||||||
|
var anyone_dead = false
|
||||||
|
var all_dead = true
|
||||||
|
for tracked_player_id in tracked_players:
|
||||||
|
if tracked_player_id == self_peer_id:
|
||||||
|
continue
|
||||||
|
var tracked_player = tracked_players[tracked_player_id]
|
||||||
|
if not tracked_player.has("dead") or not tracked_player.dead:
|
||||||
|
all_others_dead = false
|
||||||
|
all_dead = false
|
||||||
|
else:
|
||||||
|
anyone_dead = true
|
||||||
|
|
||||||
|
# TODO this doesn't actually work yet
|
||||||
|
var should_end_coop = false
|
||||||
|
if lobby_data["first_death_loss"]:
|
||||||
|
should_end_coop = anyone_dead
|
||||||
|
else:
|
||||||
|
should_end_coop = all_dead
|
||||||
|
|
||||||
|
if all_others_dead or (should_end_coop):
|
||||||
|
disable_pause = false
|
||||||
|
var main = get_tree().get_current_scene()
|
||||||
|
var did_win = not is_coop()
|
||||||
|
main._is_run_won = did_win
|
||||||
|
main._is_run_lost = not did_win
|
||||||
|
RunData.run_won = did_win
|
||||||
|
|
||||||
|
main.clean_up_room(false, main._is_run_lost, main._is_run_won)
|
||||||
|
|
||||||
|
if not is_host:
|
||||||
|
send_complete_player_request()
|
||||||
|
yield(self, "complete_player_update")
|
||||||
|
var _error = get_tree().change_scene("res://ui/menus/run/end_run.tscn")
|
||||||
|
|
||||||
|
func on_consumable_to_process_added(player_id, consumable_data) -> void:
|
||||||
|
if player_id == self_peer_id:
|
||||||
|
receive_add_consumable_to_process(player_id, consumable_data.get_path())
|
||||||
|
else:
|
||||||
|
connection.send_add_consumable_to_process(player_id, consumable_data.get_path())
|
||||||
|
|
||||||
|
func receive_add_consumable_to_process(player_id, consumable_data_path) -> void:
|
||||||
|
if player_id == self_peer_id:
|
||||||
|
var consumable_data = load(consumable_data_path)
|
||||||
|
tracked_players[self_peer_id].consumables_to_process.push_back(consumable_data)
|
||||||
|
get_tree().get_current_scene().emit_signal("consumable_to_process_added", consumable_data)
|
||||||
|
|
||||||
|
func on_upgrade_selected(upgrade_data:UpgradeData)->void :
|
||||||
|
if is_host:
|
||||||
|
receive_uprade_selected(upgrade_data.my_id, self_peer_id)
|
||||||
|
else:
|
||||||
|
connection.send_upgrade_selection(upgrade_data.my_id)
|
||||||
|
|
||||||
|
func send_complete_player_request() -> void:
|
||||||
|
connection.send_complete_player_request()
|
||||||
|
|
||||||
|
func send_complete_player(player_id:int) -> void:
|
||||||
|
if not is_host:
|
||||||
|
return
|
||||||
|
|
||||||
|
var player_dict = tracked_players[player_id].duplicate()
|
||||||
|
if not player_dict.has("run_data"):
|
||||||
|
player_dict.run_data = {}
|
||||||
|
player_dict.run_data = player_dict.run_data.duplicate()
|
||||||
|
player_dict.run_data.effects = player_dict.run_data.effects.duplicate()
|
||||||
|
|
||||||
|
var new_items = []
|
||||||
|
|
||||||
|
if player_dict.run_data.has("items"):
|
||||||
|
for item in player_dict.run_data.items:
|
||||||
|
var to_add = {}
|
||||||
|
to_add["my_id"] = item.my_id
|
||||||
|
new_items.push_back(to_add)
|
||||||
|
player_dict.run_data["items"] = new_items
|
||||||
|
|
||||||
|
if player_dict.run_data.has("current_character"):
|
||||||
|
player_dict.run_data.current_character = player_dict.run_data.current_character.my_id
|
||||||
|
|
||||||
|
var new_weapons = []
|
||||||
|
if player_dict.run_data.has("weapons"):
|
||||||
|
for weapon in player_dict.run_data.weapons:
|
||||||
|
var to_add = {}
|
||||||
|
to_add["my_id"] = weapon.my_id
|
||||||
|
new_weapons.push_back(to_add)
|
||||||
|
player_dict.run_data["weapons"] = new_weapons
|
||||||
|
|
||||||
|
var burn_chance = {}
|
||||||
|
|
||||||
|
if player_dict.run_data.has("effects"):
|
||||||
|
burn_chance.chance = player_dict.run_data.effects.burn_chance.chance
|
||||||
|
burn_chance.damage = player_dict.run_data.effects.burn_chance.damage
|
||||||
|
burn_chance.duration = player_dict.run_data.effects.burn_chance.duration
|
||||||
|
player_dict.run_data.effects.burn_chance = burn_chance
|
||||||
|
|
||||||
|
var elites = []
|
||||||
|
for elite in RunData.elites_spawn:
|
||||||
|
elites.push_back([elite[0], elite[1]])
|
||||||
|
player_dict["elites"] = elites
|
||||||
|
|
||||||
|
connection.send_complete_player(player_id, player_dict)
|
||||||
|
|
||||||
|
func receive_complete_player(player_id:int, player_dict: Dictionary) -> void:
|
||||||
|
if player_id == self_peer_id:
|
||||||
|
tracked_players[player_id]["run_data"] = player_dict.run_data
|
||||||
|
|
||||||
|
var new_items = []
|
||||||
|
|
||||||
|
for item in player_dict.run_data.items:
|
||||||
|
var found : bool = false
|
||||||
|
|
||||||
|
for query_item in ItemService.items:
|
||||||
|
if query_item.my_id == item.my_id:
|
||||||
|
new_items.push_back(query_item.duplicate())
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
if not found:
|
||||||
|
for query_item in ItemService.characters:
|
||||||
|
if query_item.my_id == item.my_id:
|
||||||
|
new_items.push_back(query_item.duplicate())
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
tracked_players[player_id]["run_data"]["items"] = new_items
|
||||||
|
|
||||||
|
for query_character in ItemService.characters:
|
||||||
|
if player_dict.run_data.has("current_character"):
|
||||||
|
if query_character.my_id == player_dict.run_data.current_character:
|
||||||
|
player_dict.run_data.current_character = query_character
|
||||||
|
break
|
||||||
|
|
||||||
|
var new_weapons = []
|
||||||
|
|
||||||
|
for weapon in player_dict.run_data.weapons:
|
||||||
|
for query_weapon in ItemService.weapons:
|
||||||
|
if query_weapon.my_id == weapon.my_id:
|
||||||
|
new_weapons.push_back(query_weapon.duplicate())
|
||||||
|
tracked_players[player_id]["run_data"]["weapons"] = new_weapons
|
||||||
|
|
||||||
|
if tracked_players[player_id]["run_data"].has("gold"):
|
||||||
|
RunData.emit_signal("gold_changed", tracked_players[player_id]["run_data"].gold)
|
||||||
|
var elites_spawn = []
|
||||||
|
for elite in player_dict["elites"]:
|
||||||
|
elites_spawn.push_back([elite[0], elite[1], "some_boss_id"])
|
||||||
|
RunData.elites_spawn = elites_spawn
|
||||||
|
emit_signal("complete_player_update")
|
||||||
|
|
||||||
|
func on_item_box_take_button_pressed(item_data:ItemParentData) -> void:
|
||||||
|
if is_host:
|
||||||
|
receive_item_box_take(item_data.my_id, self_peer_id)
|
||||||
|
else:
|
||||||
|
connection.send_take_item_box(self_peer_id, item_data.my_id)
|
||||||
|
|
||||||
|
func receive_item_box_take(item_id, player_id) -> void:
|
||||||
|
var run_data_node = $"/root/MultiplayerRunData"
|
||||||
|
|
||||||
|
for item in ItemService.items:
|
||||||
|
if item.my_id == item_id:
|
||||||
|
run_data_node.add_item(player_id, item)
|
||||||
|
return
|
||||||
|
|
||||||
|
func reroll_upgrades() -> void:
|
||||||
|
var upgrades_ui = get_tree().get_current_scene()._upgrades_ui
|
||||||
|
var reroll_price = upgrades_ui._reroll_price
|
||||||
|
if is_host:
|
||||||
|
receive_reroll_upgrades(self_peer_id, reroll_price)
|
||||||
|
else:
|
||||||
|
connection.send_reroll_upgrades(reroll_price)
|
||||||
|
|
||||||
|
func receive_reroll_upgrades(_player_id:int, _reroll_price:int) -> void:
|
||||||
|
print_debug("receive_reroll_upgrades")
|
||||||
|
|
||||||
|
|
||||||
|
func on_item_discard_button_pressed(weapon_data:WeaponData) -> void:
|
||||||
|
if is_host:
|
||||||
|
receive_item_discard(weapon_data.my_id, self_peer_id)
|
||||||
|
else:
|
||||||
|
connection.send_weapon_discard(weapon_data.my_id)
|
||||||
|
|
||||||
|
func receive_item_discard(weapon_id, player_id) -> void:
|
||||||
|
var run_data_node = $"/root/MultiplayerRunData"
|
||||||
|
|
||||||
|
var run_data = tracked_players[player_id].run_data
|
||||||
|
var weapon_data = null
|
||||||
|
|
||||||
|
for weapon in run_data.weapons:
|
||||||
|
if weapon.my_id == weapon_id:
|
||||||
|
weapon_data = weapon
|
||||||
|
|
||||||
|
var _weapon = run_data_node.remove_weapon(player_id, weapon_data)
|
||||||
|
run_data_node.add_gold(player_id, ItemService.get_recycling_value(RunData.current_wave, weapon_data.value, true))
|
||||||
|
|
||||||
|
if player_id != self_peer_id:
|
||||||
|
send_complete_player(player_id)
|
||||||
|
|
||||||
|
func receive_player_enter_shop(player_id:int) -> void:
|
||||||
|
var run_data = tracked_players[player_id].run_data
|
||||||
|
var run_data_node = $"/root/MultiplayerRunData"
|
||||||
|
|
||||||
|
if run_data.effects["destroy_weapons"]:
|
||||||
|
run_data_node.remove_all_weapons(player_id)
|
||||||
|
|
||||||
|
if run_data.effects["upgrade_random_weapon"].size() > 0:
|
||||||
|
for effect in run_data.effects["upgrade_random_weapon"]:
|
||||||
|
|
||||||
|
var possible_upgrades = []
|
||||||
|
|
||||||
|
for weapon in run_data.weapons:
|
||||||
|
if weapon.upgrades_into != null and weapon.tier < run_data.effects["max_weapon_tier"]:
|
||||||
|
possible_upgrades.push_back(weapon)
|
||||||
|
|
||||||
|
if possible_upgrades.size() > 0:
|
||||||
|
var weapon_to_upgrade = Utils.get_rand_element(possible_upgrades)
|
||||||
|
receive_item_combine(weapon_to_upgrade.my_id, true, player_id)
|
||||||
|
else :
|
||||||
|
run_data_node.add_stat(player_id, effect[0], effect[1])
|
||||||
|
|
||||||
|
if player_id != self_peer_id:
|
||||||
|
send_complete_player(player_id)
|
||||||
|
|
||||||
|
func on_item_combine_button_pressed(weapon_data:WeaponData, is_upgrade:bool = false) -> void:
|
||||||
|
if is_host:
|
||||||
|
receive_item_combine(weapon_data.my_id, is_upgrade, self_peer_id)
|
||||||
|
else:
|
||||||
|
connection.send_combine_item(weapon_data.my_id, is_upgrade, self_peer_id)
|
||||||
|
|
||||||
|
func receive_item_combine(weapon_id, is_upgrade, player_id) -> void:
|
||||||
|
var run_data_node = $"/root/MultiplayerRunData"
|
||||||
|
|
||||||
|
var nb_to_remove = 2
|
||||||
|
var removed_weapons_tracked_value = 0
|
||||||
|
|
||||||
|
if is_upgrade:
|
||||||
|
nb_to_remove = 1
|
||||||
|
|
||||||
|
var run_data = tracked_players[player_id].run_data
|
||||||
|
var weapon_data = null
|
||||||
|
|
||||||
|
for weapon in run_data.weapons:
|
||||||
|
if weapon.my_id == weapon_id:
|
||||||
|
weapon_data = weapon
|
||||||
|
|
||||||
|
removed_weapons_tracked_value += run_data_node.remove_weapon(player_id, weapon_data)
|
||||||
|
|
||||||
|
if not is_upgrade:
|
||||||
|
removed_weapons_tracked_value += run_data_node.remove_weapon(player_id, weapon_data)
|
||||||
|
|
||||||
|
var new_weapon = run_data_node.add_weapon(player_id, weapon_data.upgrades_into)
|
||||||
|
|
||||||
|
new_weapon.tracked_value = removed_weapons_tracked_value
|
||||||
|
|
||||||
|
if is_upgrade:
|
||||||
|
new_weapon.dmg_dealt_last_wave = weapon_data.dmg_dealt_last_wave
|
||||||
|
|
||||||
|
if player_id == self_peer_id:
|
||||||
|
var shop = $"/root/Shop"
|
||||||
|
shop._weapons_container._elements.remove_element(weapon_data, nb_to_remove)
|
||||||
|
shop.reset_item_popup_focus()
|
||||||
|
shop._stats_container.update_stats()
|
||||||
|
shop._weapons_container._elements.add_element(new_weapon)
|
||||||
|
SoundManager.play(Utils.get_rand_element(shop.combine_sounds), 0, 0.1, true)
|
||||||
|
shop._weapons_container.set_label(shop.get_weapons_label_text())
|
||||||
|
if Input.get_mouse_mode() == Input.MOUSE_MODE_HIDDEN:
|
||||||
|
shop._weapons_container._elements.focus_element(new_weapon)
|
||||||
|
|
||||||
|
func receive_uprade_selected(upgrade_data_id, player_id):
|
||||||
|
for upgrade in ItemService.upgrades:
|
||||||
|
if upgrade.my_id == upgrade_data_id:
|
||||||
|
var run_data = tracked_players[player_id].run_data
|
||||||
|
var run_data_node = $"/root/MultiplayerRunData"
|
||||||
|
run_data_node.apply_item_effects(player_id, upgrade, run_data)
|
||||||
|
|
||||||
|
# Send normal item
|
||||||
|
func send_bought_item_by_id(item_id:String, value:int) -> void:
|
||||||
|
if is_host:
|
||||||
|
receive_bought_item_by_id(item_id, self_peer_id, value)
|
||||||
|
else:
|
||||||
|
connection.send_bought_item_by_id(item_id, value)
|
||||||
|
|
||||||
|
func receive_bought_item_by_id(item_id:String, player_id:int, value:int) -> void:
|
||||||
|
var run_data_node = $"/root/MultiplayerRunData"
|
||||||
|
var run_data = tracked_players[player_id].run_data
|
||||||
|
run_data_node.remove_currency(player_id, value)
|
||||||
|
var nb_coupons = run_data_node.get_nb_item(player_id, "item_coupon")
|
||||||
|
|
||||||
|
var shop_item_data = null
|
||||||
|
|
||||||
|
for weapon in ItemService.weapons:
|
||||||
|
if weapon.my_id == item_id:
|
||||||
|
shop_item_data = weapon
|
||||||
|
for item in ItemService.items:
|
||||||
|
if item.my_id == item_id:
|
||||||
|
shop_item_data = item
|
||||||
|
|
||||||
|
if nb_coupons > 0:
|
||||||
|
# var coupon_value = get_coupon_value() reimplemented in place
|
||||||
|
var coupon_value = 0
|
||||||
|
for item in run_data.items:
|
||||||
|
if item.my_id == "item_coupon":
|
||||||
|
coupon_value = abs(item.effects[0].value)
|
||||||
|
break
|
||||||
|
|
||||||
|
var coupon_effect = nb_coupons * (coupon_value / 100.0)
|
||||||
|
var base_value = ItemService.get_value(RunData.current_wave, shop_item_data.value, false, shop_item_data is WeaponData, shop_item_data.my_id)
|
||||||
|
run_data.tracked_item_effects["item_coupon"] += (base_value * coupon_effect) as int
|
||||||
|
|
||||||
|
if shop_item_data.get_category() == Category.ITEM:
|
||||||
|
run_data_node.add_item(player_id, shop_item_data)
|
||||||
|
elif shop_item_data.get_category() == Category.WEAPON:
|
||||||
|
if not run_data_node.has_weapon_slot_available(player_id, shop_item_data.type):
|
||||||
|
for weapon in run_data.weapons:
|
||||||
|
if weapon.my_id == shop_item_data.my_id and weapon.upgrades_into != null:
|
||||||
|
var _weapon = run_data_node.add_weapon(player_id, shop_item_data)
|
||||||
|
receive_item_combine(weapon.my_id, false, player_id)
|
||||||
|
break
|
||||||
|
else :
|
||||||
|
var _weapon = run_data_node.add_weapon(player_id, shop_item_data)
|
||||||
|
|
||||||
|
|
||||||
|
func send_reroll(price) -> void:
|
||||||
|
if is_host:
|
||||||
|
receive_reroll(price, self_peer_id)
|
||||||
|
else:
|
||||||
|
connection.send_reroll(price)
|
||||||
|
|
||||||
|
|
||||||
|
func receive_reroll(price, player_id):
|
||||||
|
var run_data = tracked_players[player_id].run_data
|
||||||
|
run_data.gold -= price
|
||||||
|
|
||||||
|
|
||||||
|
func send_bought_item(shop_item:Resource) -> void:
|
||||||
|
if is_host:
|
||||||
|
receive_bought_item(shop_item, self_peer_id)
|
||||||
|
else:
|
||||||
|
connection.send_bought_item(shop_item)
|
||||||
|
|
||||||
|
func send_client_entered_shop() -> void:
|
||||||
|
connection.send_client_entered_shop()
|
||||||
|
|
||||||
|
func receive_bought_item(shop_item:Resource, source_player_id:int) -> void:
|
||||||
|
var effect_path = shop_item.effect.get_path()
|
||||||
|
for player_id in tracked_players:
|
||||||
|
if player_id != source_player_id:
|
||||||
|
var effect = shop_item.effect
|
||||||
|
if effect is WaveGroupData:
|
||||||
|
if not tracked_players[player_id]["extra_enemies_next_wave"].has(effect_path):
|
||||||
|
tracked_players[player_id]["extra_enemies_next_wave"][effect_path] = 0
|
||||||
|
tracked_players[player_id]["extra_enemies_next_wave"][effect_path] = tracked_players[player_id]["extra_enemies_next_wave"][effect_path] + 1
|
||||||
|
elif effect is Effect:
|
||||||
|
if not tracked_players[player_id]["effects"].has(effect_path):
|
||||||
|
tracked_players[player_id]["effects"][effect_path] = 0
|
||||||
|
tracked_players[player_id]["effects"][effect_path] = tracked_players[player_id]["effects"][effect_path] + 1
|
||||||
|
|
||||||
|
if is_host:
|
||||||
|
connection.send_tracked_players(tracked_players)
|
||||||
|
if $"/root/Shop/Content/MarginContainer/HBoxContainer/VBoxContainer2/StatsContainer":
|
||||||
|
$"/root/Shop/Content/MarginContainer/HBoxContainer/VBoxContainer2/StatsContainer".update_bought_items(tracked_players)
|
||||||
|
|
||||||
|
func update_tracked_players(updated_tracked_players: Dictionary) -> void:
|
||||||
|
# Actual Player state is updated elsewhere
|
||||||
|
for player_id in updated_tracked_players:
|
||||||
|
if tracked_players.has(player_id) and tracked_players[player_id].has("player"):
|
||||||
|
updated_tracked_players[player_id]["player"] = tracked_players[player_id]["player"]
|
||||||
|
else:
|
||||||
|
updated_tracked_players[player_id].erase("player")
|
||||||
|
|
||||||
|
var scene_name = get_tree().get_current_scene().get_name()
|
||||||
|
|
||||||
|
tracked_players = updated_tracked_players
|
||||||
|
if scene_name == "Shop":
|
||||||
|
$"/root/Shop/Content/MarginContainer/HBoxContainer/VBoxContainer2/StatsContainer".update_bought_items(tracked_players)
|
||||||
|
elif scene_name == "Main":
|
||||||
|
check_win()
|
||||||
|
|
||||||
|
func create_ready_toggle() -> Node:
|
||||||
|
ready_toggle = toggle_scene.instance()
|
||||||
|
ready_toggle.connect("pressed", self, "_on_ready_toggle")
|
||||||
|
return ready_toggle
|
||||||
|
|
||||||
|
func _on_ready_toggle() -> void:
|
||||||
|
connection.send_ready(ready_toggle.pressed)
|
||||||
|
|
||||||
|
func discard_item_box(item_data:ItemParentData) -> void:
|
||||||
|
if is_host:
|
||||||
|
receive_discard_item_box(self_peer_id, item_data.my_id)
|
||||||
|
else:
|
||||||
|
connection.send_discard_item_box(item_data.my_id)
|
||||||
|
|
||||||
|
func receive_discard_item_box(_player_id:int, _item_id:String) -> void:
|
||||||
|
print_debug("receive_discard_item_box")
|
||||||
|
|
||||||
|
|
||||||
|
func end_wave():
|
||||||
|
run_updates = false
|
||||||
|
game_state_controller.reset_client_items()
|
||||||
|
|
||||||
|
if current_scene_name == "ClientMain":
|
||||||
|
var wave_timer = $"/root/ClientMain"._wave_timer
|
||||||
|
wave_timer.wait_time = 0.1
|
||||||
|
wave_timer.one_shot = true
|
||||||
|
wave_timer.start()
|
||||||
|
|
||||||
|
var end_wave_timer = $"/root/ClientMain"._end_wave_timer
|
||||||
|
end_wave_timer.one_shot = true
|
||||||
|
end_wave_timer.start()
|
||||||
|
|
||||||
|
for player_id in tracked_players:
|
||||||
|
tracked_players[player_id].erase("player")
|
||||||
|
|
||||||
|
func send_ready(is_ready:bool) -> void:
|
||||||
|
connection.send_ready(is_ready)
|
||||||
|
|
||||||
|
func send_game_state() -> void:
|
||||||
|
if run_updates:
|
||||||
|
connection.send_state(game_state_controller.get_game_state())
|
||||||
|
|
||||||
|
func send_start_game(game_info:Dictionary) -> void:
|
||||||
|
connection.send_start_game(game_info)
|
||||||
|
|
||||||
|
func send_display_floating_text(value:String, text_pos:Vector2, color:Color = Color.white) -> void:
|
||||||
|
batched_floating_text.push_back([value,text_pos, color])
|
||||||
|
|
||||||
|
func send_display_hit_effect(effect_pos, direction, effect_scale) -> void:
|
||||||
|
batched_hit_effects.push_back([effect_pos, direction, effect_scale])
|
||||||
|
|
||||||
|
func send_enemy_death(enemy_id:int) -> void:
|
||||||
|
batched_deaths.push_back(enemy_id)
|
||||||
|
# connection.send_enemy_death(enemy_id)
|
||||||
|
|
||||||
|
func send_end_wave() -> void:
|
||||||
|
connection.send_end_wave()
|
||||||
|
|
||||||
|
func send_flash_enemy(enemy_id:int) -> void:
|
||||||
|
batched_flash_enemy.push_back(enemy_id)
|
||||||
|
|
||||||
|
func send_shot(player_id:int, weapon_index:int) -> void:
|
||||||
|
connection.send_shot(player_id, weapon_index)
|
||||||
|
|
||||||
|
func receive_shot(player_id:int, weapon_index:int) -> void:
|
||||||
|
if tracked_players.has(player_id):
|
||||||
|
if tracked_players[player_id].has("player"):
|
||||||
|
var player = tracked_players[player_id]["player"]
|
||||||
|
|
||||||
|
if is_instance_valid(player):
|
||||||
|
var weapon = player.current_weapons[weapon_index]
|
||||||
|
if is_instance_valid(weapon):
|
||||||
|
SoundManager.play(Utils.get_rand_element(weapon.current_stats.shooting_sounds), weapon.current_stats.sound_db_mod, 0.2)
|
||||||
|
|
||||||
|
func send_explosion(pos: Vector2, scale: float) -> void:
|
||||||
|
connection.send_explosion(pos, scale)
|
||||||
|
|
||||||
|
func receive_explosion(pos: Vector2, scale: float) -> void:
|
||||||
|
var main = get_tree().current_scene
|
||||||
|
var instance = explosion_scene.instance()
|
||||||
|
instance.set_deferred("global_position", pos)
|
||||||
|
main.call_deferred("add_child", instance)
|
||||||
|
instance.call_deferred("set_area", scale)
|
||||||
|
|
||||||
|
func send_enemy_take_damage(enemy_id:int, is_dodge: bool) -> void:
|
||||||
|
batched_enemy_damage.push_back([enemy_id, is_dodge])
|
||||||
|
|
||||||
|
func send_flash_neutral(neutral_id:int) -> void:
|
||||||
|
connection.send_flash_neutral(neutral_id)
|
||||||
|
|
||||||
|
func send_lobby_update(lobby_info:Dictionary) -> void:
|
||||||
|
connection.send_lobby_update(lobby_info)
|
||||||
|
|
||||||
|
func receive_lobby_update(lobby_info:Dictionary) -> void:
|
||||||
|
if current_scene_name == "MultiplayerLobby":
|
||||||
|
lobby_data = lobby_info.duplicate()
|
||||||
|
$"/root/MultiplayerLobby".remote_update_lobby(lobby_info)
|
||||||
|
|
||||||
|
func update_multiplayer_lobby() -> void:
|
||||||
|
if current_scene_name == "MultiplayerLobby":
|
||||||
|
$"/root/MultiplayerLobby".update_selections()
|
||||||
|
|
||||||
|
func send_client_position() -> void:
|
||||||
|
if not tracked_players.has(self_peer_id) or not tracked_players[self_peer_id].has("player"):
|
||||||
|
return
|
||||||
|
var my_player = tracked_players[self_peer_id]["player"]
|
||||||
|
if not is_instance_valid(my_player):
|
||||||
|
return
|
||||||
|
var client_position = {}
|
||||||
|
client_position["player"] = my_player.position
|
||||||
|
client_position["id"] = self_peer_id
|
||||||
|
client_position["movement"] = my_player._current_movement
|
||||||
|
var weapons = []
|
||||||
|
for weapon in my_player.current_weapons:
|
||||||
|
var weapon_data = {}
|
||||||
|
weapon_data["weapon_id"] = weapon.weapon_id
|
||||||
|
weapon_data["position"] = weapon.sprite.position
|
||||||
|
weapon_data["rotation"] = weapon.sprite.rotation
|
||||||
|
weapon_data["hitbox_disabled"] = weapon._hitbox._collision.disabled
|
||||||
|
weapons.push_back(weapon_data)
|
||||||
|
client_position["weapons"] = weapons
|
||||||
|
|
||||||
|
connection.send_client_position(client_position)
|
||||||
|
|
||||||
|
func update_client_position(client_position:Dictionary) -> void:
|
||||||
|
if is_source_of_truth:
|
||||||
|
var id = client_position.id
|
||||||
|
if tracked_players.has(id):
|
||||||
|
if tracked_players[id].has("player"):
|
||||||
|
var player = tracked_players[id]["player"]
|
||||||
|
if not is_instance_valid(player):
|
||||||
|
return
|
||||||
|
player.position = client_position.player
|
||||||
|
player.maybe_update_animation(client_position.movement, true)
|
||||||
|
|
||||||
|
func update_ready_state(sender_id, is_ready):
|
||||||
|
if is_host:
|
||||||
|
tracked_players[sender_id]["is_ready"] = is_ready
|
||||||
|
if current_scene_name == "Shop":
|
||||||
|
update_go_button()
|
||||||
|
|
||||||
|
func reset_ready_map():
|
||||||
|
for player_id in tracked_players:
|
||||||
|
tracked_players[player_id]["is_ready"] = false
|
||||||
|
|
||||||
|
func reset_extra_creatures():
|
||||||
|
for player_id in tracked_players:
|
||||||
|
tracked_players[player_id]["extra_enemies_next_wave"] = {}
|
||||||
|
tracked_players[player_id]["effects"] = {}
|
||||||
|
|
||||||
|
func update_go_button():
|
||||||
|
var should_enable = true
|
||||||
|
|
||||||
|
for player_id in tracked_players:
|
||||||
|
if player_id != self_peer_id and not tracked_players[player_id]["is_ready"]:
|
||||||
|
should_enable = false
|
||||||
|
break
|
||||||
|
|
||||||
|
var shop_button = $"/root/Shop/Content/MarginContainer/HBoxContainer/VBoxContainer2/GoButton"
|
||||||
|
|
||||||
|
if not should_enable:
|
||||||
|
shop_button.disabled = true
|
||||||
|
else:
|
||||||
|
shop_button.disabled = false
|
||||||
|
|
||||||
|
func get_items_state() -> Dictionary:
|
||||||
|
var main = $"/root/Main"
|
||||||
|
var items = []
|
||||||
|
for item in main._items_container.get_children():
|
||||||
|
var item_data = {}
|
||||||
|
|
||||||
|
item_data["id"] = item.id
|
||||||
|
item_data["scale_x"] = item.scale.x
|
||||||
|
item_data["scale_y"] = item.scale.y
|
||||||
|
item_data["position"] = item.global_position
|
||||||
|
item_data["rotation"] = item.rotation
|
||||||
|
item_data["push_back_destination"] = item.push_back_destination
|
||||||
|
|
||||||
|
# TODO we may want textures propagated
|
||||||
|
items.push_back(item_data)
|
||||||
|
return items
|
||||||
|
|
||||||
|
func get_projectiles_state() -> Dictionary:
|
||||||
|
var main = $"/root/Main"
|
||||||
|
var projectiles = []
|
||||||
|
for child in main.get_children():
|
||||||
|
if child is PlayerProjectile:
|
||||||
|
var projectile_data = {}
|
||||||
|
projectile_data["id"] = child.id
|
||||||
|
projectile_data["filename"] = child.filename
|
||||||
|
projectile_data["position"] = child.position
|
||||||
|
projectile_data["global_position"] = child.global_position
|
||||||
|
projectile_data["rotation"] = child.rotation
|
||||||
|
|
||||||
|
projectiles.push_back(projectile_data)
|
||||||
|
return projectiles
|
||||||
|
|
||||||
|
func send_player_level_up(player_id: int, level:int) -> void:
|
||||||
|
connection.send_player_level_up(player_id, level)
|
||||||
|
|
||||||
|
func receive_player_level_up(player_id: int, level:int) -> void:
|
||||||
|
if player_id == self_peer_id:
|
||||||
|
var main = $"/root/ClientMain"
|
||||||
|
main._ui_upgrades_to_process.add_element(ItemService.upgrade_to_process_icon, level)
|
||||||
|
main._upgrades_to_process.push_back(level)
|
||||||
|
|
||||||
|
func receive_health_update(current_health:int, max_health:int, source_player_id:int) -> void:
|
||||||
|
tracked_players[source_player_id]["max_health"] = max_health
|
||||||
|
tracked_players[source_player_id]["current_health"] = current_health
|
||||||
|
|
||||||
|
# if is_host:
|
||||||
|
# connection.send_tracked_players(tracked_players)
|
||||||
|
# update_health_ui()
|
||||||
|
|
||||||
|
func update_health_ui() -> void:
|
||||||
|
if current_scene_name == "Main":
|
||||||
|
if $"/root/Main/UI/HealthTracker":
|
||||||
|
$"/root/Main/UI/HealthTracker".update_health_bars(tracked_players)
|
||||||
|
if current_scene_name == "ClientMain":
|
||||||
|
if $"/root/ClientMain/UI/HealthTracker":
|
||||||
|
$"/root/ClientMain/UI/HealthTracker".update_health_bars(tracked_players)
|
||||||
|
|
||||||
|
func update_health(current_health:int, max_health:int) -> void:
|
||||||
|
# If this player owns all the players, all the updates will come through
|
||||||
|
# here.
|
||||||
|
if is_coop() and is_host:
|
||||||
|
for player_id in tracked_players:
|
||||||
|
var player_dict = tracked_players[player_id]
|
||||||
|
if player_dict.has("player") and is_instance_valid(player_dict.player):
|
||||||
|
var player = player_dict.player
|
||||||
|
|
||||||
|
tracked_players[player_id]["max_health"] = player.max_stats.health
|
||||||
|
tracked_players[player_id]["current_health"] = player.current_stats.health
|
||||||
|
|
||||||
|
receive_health_update(current_health, max_health, self_peer_id)
|
||||||
|
connection.send_health_update(current_health, max_health)
|
||||||
|
|
||||||
|
func update_game_state(data: PoolByteArray) -> void:
|
||||||
|
if get_tree().get_current_scene().get_name() != "ClientMain":
|
||||||
|
return
|
||||||
|
game_state_controller.update_game_state(data)
|
||||||
|
update_health_ui()
|
||||||
|
|
||||||
|
func enemy_death(enemy_id):
|
||||||
|
game_state_controller.enemy_death(enemy_id)
|
||||||
|
|
||||||
|
func flash_neutral(neutral_id):
|
||||||
|
game_state_controller.flash_neutral(neutral_id)
|
||||||
|
|
||||||
|
func is_coop() -> bool:
|
||||||
|
return game_mode == GameMode.COOP
|
||||||
|
|
||||||
|
|
||||||
|
func on_danger_selected(danger) -> void:
|
||||||
|
if is_host:
|
||||||
|
received_danger_selected(self_peer_id, danger)
|
||||||
|
else:
|
||||||
|
connection.send_danger_selected(danger)
|
||||||
|
|
||||||
|
|
||||||
|
func received_danger_selected(player_id, danger) -> void:
|
||||||
|
lobby_data["players"][player_id]["danger"] = danger
|
||||||
|
emit_signal("lobby_info_updated")
|
||||||
|
|
||||||
|
|
||||||
|
func on_character_selected(character) -> void:
|
||||||
|
if is_host:
|
||||||
|
received_character_selected(self_peer_id, character)
|
||||||
|
else:
|
||||||
|
connection.send_character_selected(character)
|
||||||
|
|
||||||
|
|
||||||
|
func received_character_selected(player_id, character) -> void:
|
||||||
|
lobby_data["players"][player_id]["character"] = character
|
||||||
|
lobby_data["players"][player_id].erase("weapon")
|
||||||
|
emit_signal("lobby_info_updated")
|
||||||
|
|
||||||
|
|
||||||
|
func on_weapon_selected(weapon) -> void:
|
||||||
|
if is_host:
|
||||||
|
received_weapon_selected(self_peer_id, weapon)
|
||||||
|
else:
|
||||||
|
connection.send_weapon_selected(weapon)
|
||||||
|
|
||||||
|
|
||||||
|
func received_weapon_selected(player_id, weapon) -> void:
|
||||||
|
lobby_data["players"][player_id]["weapon"] = weapon
|
||||||
|
emit_signal("lobby_info_updated")
|
||||||
|
|
||||||
|
|
||||||
|
func on_mp_lobby_ready_changed(is_ready:bool) -> void:
|
||||||
|
if is_host:
|
||||||
|
receive_mp_lobby_ready_changed(self_peer_id, is_ready)
|
||||||
|
else:
|
||||||
|
connection.send_mp_lobby_readied(is_ready)
|
||||||
|
|
||||||
|
|
||||||
|
func receive_mp_lobby_ready_changed(player_id, is_ready:bool) -> void:
|
||||||
|
lobby_data["players"][player_id]["ready"] = is_ready
|
||||||
|
emit_signal("lobby_info_updated")
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,453 @@
|
|||||||
|
extends "res://mods-unpacked/Brogether-Brogether/networking/connection.gd"
|
||||||
|
|
||||||
|
var lobby_id = 0
|
||||||
|
var parent
|
||||||
|
var established_p2p_connections = {}
|
||||||
|
|
||||||
|
var rpcs_by_type = {}
|
||||||
|
var prev_sec = 0
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
print_debug("steam connection ready?")
|
||||||
|
lobby_id = 0
|
||||||
|
var _connect_error = Steam.connect("lobby_created", self, "_on_Lobby_Created")
|
||||||
|
print_debug("connect error? ", _connect_error)
|
||||||
|
_connect_error = Steam.connect("lobby_match_list", self, "_on_Lobby_Match_List")
|
||||||
|
_connect_error = Steam.connect("lobby_joined", self, "_on_Lobby_Joined")
|
||||||
|
_connect_error = Steam.connect("lobby_chat_update", self, "_on_Lobby_Chat_Update")
|
||||||
|
_connect_error = Steam.connect("p2p_session_request", self, "_on_P2P_Session_Request")
|
||||||
|
|
||||||
|
func _process(_delta):
|
||||||
|
if lobby_id > 0:
|
||||||
|
while read_p2p_packet():
|
||||||
|
pass
|
||||||
|
|
||||||
|
func read_p2p_packet() -> bool:
|
||||||
|
var packet_size = Steam.getAvailableP2PPacketSize(0)
|
||||||
|
|
||||||
|
var sec = Time.get_time_dict_from_system()["second"]
|
||||||
|
if sec != prev_sec:
|
||||||
|
prev_sec = sec
|
||||||
|
|
||||||
|
if packet_size > 0:
|
||||||
|
var packet = Steam.readP2PPacket(packet_size, 0)
|
||||||
|
|
||||||
|
var sender = packet["steam_id_remote"]
|
||||||
|
var data = bytes2var(packet["data"].decompress_dynamic(-1, File.COMPRESSION_GZIP))
|
||||||
|
var type = data.type
|
||||||
|
|
||||||
|
if not rpcs_by_type.has(type):
|
||||||
|
rpcs_by_type[type] = 0
|
||||||
|
rpcs_by_type[type] += 1
|
||||||
|
|
||||||
|
if type == "start_game":
|
||||||
|
parent.start_game(data.game_info)
|
||||||
|
elif type == "reroll_upgrades":
|
||||||
|
parent.receive_reroll_upgrades(sender, data.reroll_price)
|
||||||
|
elif type == "weapon_discard":
|
||||||
|
parent.receive_item_discard(data.weapon_id, sender)
|
||||||
|
elif type == "send_combine_item":
|
||||||
|
parent.receive_item_combine(data.weapon_data_id, data.is_upgrade, data.player_id)
|
||||||
|
elif type == "discard_item_box":
|
||||||
|
parent.receive_discard_item_box(sender, data.item_id)
|
||||||
|
elif type == "send_take_item_box":
|
||||||
|
parent.receive_item_box_take(data.item_id, data.player_id)
|
||||||
|
elif type == "client_entered_shop":
|
||||||
|
parent.receive_player_enter_shop(data.player_id)
|
||||||
|
elif type == "client_started":
|
||||||
|
parent.receive_client_start(data.player_id)
|
||||||
|
elif type == "add_consumable_to_process":
|
||||||
|
parent.receive_add_consumable_to_process(data.player_id, data.consumable_data_path)
|
||||||
|
elif type == "end_wave":
|
||||||
|
parent.end_wave()
|
||||||
|
elif type == "level_up":
|
||||||
|
parent.receive_player_level_up(data.player_id, data.level)
|
||||||
|
elif type == "flash_neutral":
|
||||||
|
parent.flash_neutral(data.neutral_id)
|
||||||
|
elif type == "client_position_update":
|
||||||
|
parent.update_client_position(data.client_position)
|
||||||
|
elif type == "send_bought_item":
|
||||||
|
parent.receive_bought_item(load(data.shop_item), sender)
|
||||||
|
elif type == "send_bought_item_by_id":
|
||||||
|
parent.receive_bought_item_by_id(data.item_id, sender, data.value)
|
||||||
|
elif type == "send_ready":
|
||||||
|
parent.update_ready_state(sender, data.is_ready)
|
||||||
|
elif type == "request_complete_player":
|
||||||
|
parent.send_complete_player(sender)
|
||||||
|
elif type == "complete_player":
|
||||||
|
parent.receive_complete_player(data.player_id, data.player_dict)
|
||||||
|
elif type == "handshake":
|
||||||
|
# completes the handshake?
|
||||||
|
established_p2p_connections[sender] = true
|
||||||
|
update_tracked_players()
|
||||||
|
send_welcomes()
|
||||||
|
elif type == "update_tracked_players":
|
||||||
|
parent.update_tracked_players(data.tracked_players)
|
||||||
|
elif type == "lobby_update":
|
||||||
|
print_debug("received lobby update")
|
||||||
|
parent.receive_lobby_update(data.lobby_info)
|
||||||
|
elif type == "reroll":
|
||||||
|
parent.receive_reroll(data.price, sender)
|
||||||
|
elif type == "health_update":
|
||||||
|
parent.receive_health_update(data.current_health, data.max_health, sender)
|
||||||
|
elif type == "death":
|
||||||
|
parent.receive_death(sender)
|
||||||
|
elif type == "select_upgrade":
|
||||||
|
parent.receive_uprade_selected(data.upgrade_data_id, sender)
|
||||||
|
elif type == "shot":
|
||||||
|
parent.receive_shot(data.player_id, data.weapon_index)
|
||||||
|
elif type == "explosion":
|
||||||
|
parent.receive_explosion(Vector2(data.pos_x, data.pos_y), data.scale)
|
||||||
|
elif type == "character_selected":
|
||||||
|
parent.received_character_selected(data.player_id, data.character)
|
||||||
|
elif type == "weapon_selected":
|
||||||
|
parent.received_weapon_selected(data.player_id, data.weapon)
|
||||||
|
elif type == "danger_selected":
|
||||||
|
parent.received_danger_selected(data.player_id, data.danger)
|
||||||
|
elif type == "mp_lobby_readied":
|
||||||
|
parent.receive_mp_lobby_ready_changed(data.player_id, data.is_ready)
|
||||||
|
elif type == "request_lobby_update":
|
||||||
|
print_debug("received updated request")
|
||||||
|
if get_tree().get_current_scene().get_name() == "MultiplayerLobby":
|
||||||
|
send_lobby_update(parent.lobby_data)
|
||||||
|
else:
|
||||||
|
print_debug("unhandled type " , type)
|
||||||
|
return true
|
||||||
|
return false
|
||||||
|
|
||||||
|
func _on_Lobby_Match_List(lobbies: Array):
|
||||||
|
var scene_name = get_tree().get_current_scene().get_name()
|
||||||
|
if scene_name == "MultiplayerMenu":
|
||||||
|
$"/root/MultiplayerMenu".update_lobbies(lobbies)
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# if lobbies.size() == 1:
|
||||||
|
# Steam.joinLobby(lobbies[0])
|
||||||
|
# pass
|
||||||
|
|
||||||
|
func _on_Lobby_Created(connect: int, connected_lobby_id: int) -> void:
|
||||||
|
print_debug("lobby created")
|
||||||
|
if connect == 1:
|
||||||
|
lobby_id = connected_lobby_id
|
||||||
|
|
||||||
|
var _set_error = Steam.setLobbyData(lobby_id, "game", "Brotatogether")
|
||||||
|
_set_error = Steam.setLobbyData(lobby_id, "host", Steam.getPersonaName())
|
||||||
|
|
||||||
|
var _error = Steam.allowP2PPacketRelay(false)
|
||||||
|
|
||||||
|
func close_lobby() -> void:
|
||||||
|
# TODO this probably isn't the correct way to close a lobby but at least no one will find it
|
||||||
|
# for now.
|
||||||
|
var _set_error = Steam.setLobbyData(lobby_id, "game", "Not At All Brotatogether, Go Away")
|
||||||
|
|
||||||
|
func _on_Lobby_Joined(joined_lobby_id: int, _permissions: int, _locked: bool, response: int) -> void:
|
||||||
|
if response == 1:
|
||||||
|
print_debug("on lobby joined")
|
||||||
|
lobby_id = joined_lobby_id
|
||||||
|
parent.self_peer_id = Steam.getSteamID()
|
||||||
|
var _scene_error = get_tree().change_scene("res://mods-unpacked/Brogether-Brogether/ui/multiplayer_lobby.tscn")
|
||||||
|
update_tracked_players()
|
||||||
|
send_handshakes()
|
||||||
|
|
||||||
|
if not parent.is_host:
|
||||||
|
request_lobby_update()
|
||||||
|
|
||||||
|
func _on_Lobby_Chat_Update(_update_lobby_id: int, change_id: int, _making_change_id: int, chat_state: int) -> void:
|
||||||
|
var username = Steam.getFriendPersonaName(change_id)
|
||||||
|
update_tracked_players()
|
||||||
|
|
||||||
|
if chat_state == 1:
|
||||||
|
print_debug(username, " joined the lobby ", change_id)
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Else if a player has left the lobby
|
||||||
|
elif chat_state == 2:
|
||||||
|
print_debug(username, " has left the lobby.")
|
||||||
|
|
||||||
|
# Else if a player has been kicked
|
||||||
|
elif chat_state == 8:
|
||||||
|
print_debug(username, " has been kicked from the lobby.")
|
||||||
|
|
||||||
|
# Else if a player has been banned
|
||||||
|
elif chat_state == 16:
|
||||||
|
print_debug(username, " has been banned from the lobby.")
|
||||||
|
|
||||||
|
# clears tracked_players and resets tracked players based
|
||||||
|
func update_tracked_players() -> void:
|
||||||
|
# Clear your previous lobby list
|
||||||
|
parent.tracked_players.clear()
|
||||||
|
|
||||||
|
# Get the number of members from this lobby from Steam
|
||||||
|
var num_members = Steam.getNumLobbyMembers(lobby_id)
|
||||||
|
var all_players_ready = true
|
||||||
|
|
||||||
|
# Get the data of these players from Steam
|
||||||
|
for member_index in range(num_members):
|
||||||
|
var member_steam_id = Steam.getLobbyMemberByIndex(lobby_id, member_index)
|
||||||
|
var member_username: String = Steam.getFriendPersonaName(member_steam_id)
|
||||||
|
|
||||||
|
if not established_p2p_connections.has(member_steam_id) or not established_p2p_connections[member_steam_id]:
|
||||||
|
if member_steam_id != parent.self_peer_id:
|
||||||
|
all_players_ready = false
|
||||||
|
if parent.is_host:
|
||||||
|
member_username = member_username
|
||||||
|
|
||||||
|
parent.tracked_players[member_steam_id] = {"username": member_username}
|
||||||
|
|
||||||
|
parent.all_players_ready = all_players_ready
|
||||||
|
parent.update_multiplayer_lobby()
|
||||||
|
|
||||||
|
func send_state(game_state:PoolByteArray) -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["game_state"] = game_state
|
||||||
|
send_data["type"] = "game_state"
|
||||||
|
|
||||||
|
for player_id in parent.tracked_players:
|
||||||
|
if player_id == parent.self_peer_id:
|
||||||
|
continue
|
||||||
|
var compressed_data = var2bytes(send_data).compress(File.COMPRESSION_GZIP)
|
||||||
|
|
||||||
|
# State updates get their own channel
|
||||||
|
var _error = Steam.sendP2PPacket(player_id, compressed_data, Steam.P2P_SEND_RELIABLE, 1)
|
||||||
|
|
||||||
|
func send_start_game(game_info:Dictionary) -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "start_game"
|
||||||
|
send_data["game_info"] = game_info
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func send_end_wave():
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "end_wave"
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func send_shot(player_id:int, weapon_index:int) -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "shot"
|
||||||
|
send_data["player_id"] = player_id
|
||||||
|
send_data["weapon_index"] = weapon_index
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func send_flash_neutral(neutral_id):
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "flash_neutral"
|
||||||
|
send_data["neutral_id"] = neutral_id
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func send_data_to_all(packet_data: Dictionary):
|
||||||
|
for player_id in parent.tracked_players:
|
||||||
|
if player_id == parent.self_peer_id:
|
||||||
|
continue
|
||||||
|
send_data(packet_data, player_id)
|
||||||
|
|
||||||
|
func send_data(packet_data: Dictionary, target: int):
|
||||||
|
# TODO actually compress
|
||||||
|
var compressed_data = var2bytes(packet_data).compress(File.COMPRESSION_GZIP)
|
||||||
|
|
||||||
|
# Just use channel 0 for everything for now
|
||||||
|
var _error = Steam.sendP2PPacket(target, compressed_data, Steam.P2P_SEND_RELIABLE, 0)
|
||||||
|
|
||||||
|
# Done to trigger p2p session requests
|
||||||
|
func send_handshakes() -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "handshake"
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func send_welcomes() -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "welcome"
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func _on_P2P_Session_Request(remote_id: int) -> void:
|
||||||
|
var _error = Steam.acceptP2PSessionWithUser(remote_id)
|
||||||
|
|
||||||
|
# Make the initial handshake
|
||||||
|
send_handshakes()
|
||||||
|
|
||||||
|
func send_client_position(client_position:Dictionary) -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "client_position_update"
|
||||||
|
send_data["client_position"] = client_position
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func send_bought_item(shop_item:Resource) -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "send_bought_item"
|
||||||
|
send_data["shop_item"] = shop_item.get_path()
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func send_bought_item_by_id(item_id:String, value:int) -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "send_bought_item_by_id"
|
||||||
|
send_data["item_id"] = item_id
|
||||||
|
send_data["value"] = value
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func send_ready(is_ready:bool) -> void:
|
||||||
|
print_debug("sending ready")
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "send_ready"
|
||||||
|
send_data["is_ready"] = is_ready
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func send_tracked_players(tracked_players:Dictionary) -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "update_tracked_players"
|
||||||
|
send_data["tracked_players"] = tracked_players
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func send_lobby_update(lobby_info:Dictionary) -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "lobby_update"
|
||||||
|
send_data["lobby_info"] = lobby_info
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func request_lobby_update() -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "request_lobby_update"
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func send_health_update(current_health:int, max_health:int) -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "health_update"
|
||||||
|
send_data["current_health"] = current_health
|
||||||
|
send_data["max_health"] = max_health
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func send_death() -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "death"
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func send_explosion(pos: Vector2, scale: float) -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "explosion"
|
||||||
|
send_data["pos_x"] = pos.x
|
||||||
|
send_data["pos_y"] = pos.y
|
||||||
|
send_data["scale"] = scale
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func get_lobby_host() -> String:
|
||||||
|
return Steam.getLobbyData(lobby_id,"host")
|
||||||
|
|
||||||
|
func send_upgrade_selection(upgrade_data_id) -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "select_upgrade"
|
||||||
|
send_data["upgrade_data_id"] = upgrade_data_id
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func send_player_level_up(player_id:int, level:int) -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "level_up"
|
||||||
|
send_data["player_id"] = player_id
|
||||||
|
send_data["level"] = level
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func send_complete_player_request() -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "request_complete_player"
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func send_complete_player(player_id:int, player_dict:Dictionary) -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "complete_player"
|
||||||
|
send_data["player_id"] = player_id
|
||||||
|
send_data["player_dict"] = player_dict
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func send_add_consumable_to_process(player_id:int, consumable_data_path) -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "add_consumable_to_process"
|
||||||
|
send_data["player_id"] = player_id
|
||||||
|
send_data["consumable_data_path"] = consumable_data_path
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func send_take_item_box(player_id:int, item_id) -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "send_take_item_box"
|
||||||
|
send_data["player_id"] = player_id
|
||||||
|
send_data["item_id"] = item_id
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func send_combine_item(weapon_data_id, is_upgrade, player_id) -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "send_combine_item"
|
||||||
|
send_data["player_id"] = player_id
|
||||||
|
send_data["is_upgrade"] = is_upgrade
|
||||||
|
send_data["weapon_data_id"] = weapon_data_id
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func send_discard_item_box(item_id) -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "discard_item_box"
|
||||||
|
send_data["item_id"] = item_id
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func send_reroll_upgrades(reroll_price) -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "reroll_upgrades"
|
||||||
|
send_data["reroll_price"] = reroll_price
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func send_weapon_discard(weapon_id) -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "weapon_discard"
|
||||||
|
send_data["weapon_id"] = weapon_id
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func send_client_entered_shop() -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "client_entered_shop"
|
||||||
|
send_data["player_id"] = parent.self_peer_id
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
func send_client_started() -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "client_started"
|
||||||
|
send_data["player_id"] = parent.self_peer_id
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
|
||||||
|
func send_danger_selected(danger) -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "danger_selected"
|
||||||
|
send_data["player_id"] = parent.self_peer_id
|
||||||
|
send_data["danger"] = danger
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
|
||||||
|
func send_character_selected(character) -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "character_selected"
|
||||||
|
send_data["player_id"] = parent.self_peer_id
|
||||||
|
send_data["character"] = character
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
|
||||||
|
func send_weapon_selected(weapon) -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "weapon_selected"
|
||||||
|
send_data["player_id"] = parent.self_peer_id
|
||||||
|
send_data["weapon"] = weapon
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
|
||||||
|
func send_mp_lobby_readied(is_ready) -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "mp_lobby_readied"
|
||||||
|
send_data["player_id"] = parent.self_peer_id
|
||||||
|
send_data["is_ready"] = is_ready
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
|
||||||
|
func send_reroll(price) -> void:
|
||||||
|
var send_data = {}
|
||||||
|
send_data["type"] = "reroll"
|
||||||
|
send_data["player_id"] = parent.self_peer_id
|
||||||
|
send_data["price"] = price
|
||||||
|
send_data_to_all(send_data)
|
||||||
|
|
||||||
|
|
||||||
|
func send_game_state() -> void:
|
||||||
|
pass
|
||||||
1197
src/mods-unpacked/Brogether-Brogether/steam_connection.gd
Normal file
1197
src/mods-unpacked/Brogether-Brogether/steam_connection.gd
Normal file
File diff suppressed because it is too large
Load Diff
13
src/mods-unpacked/Brogether-Brogether/ui/button.tscn
Normal file
13
src/mods-unpacked/Brogether-Brogether/ui/button.tscn
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[gd_scene load_steps=2 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://ui/menus/global/my_menu_button.gd" type="Script" id=1]
|
||||||
|
|
||||||
|
[node name="GoButton" type="Button"]
|
||||||
|
margin_top = 1522.0
|
||||||
|
margin_right = 411.0
|
||||||
|
margin_bottom = 1587.0
|
||||||
|
focus_neighbour_top = NodePath("../../VBoxContainer/HBoxContainer2/ShopItemsContainer/ShopItem4/PanelContainer/MarginContainer/VBoxContainer/BuyButton")
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 8
|
||||||
|
text = "MORE_BADDIES"
|
||||||
|
script = ExtResource( 1 )
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
extends HBoxContainer
|
||||||
|
|
||||||
|
var username := "Test Username"
|
||||||
|
var message := "Test Message"
|
||||||
|
|
||||||
|
onready var username_label = $"%Username"
|
||||||
|
onready var message_label = $"%Message"
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
username_label.text = username
|
||||||
|
message_label.text = message
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
[gd_scene load_steps=3 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://mods-unpacked/Brogether-Brogether/ui/chat/chat_message.gd" type="Script" id=1]
|
||||||
|
[ext_resource path="res://resources/themes/panel/stat_panel.tres" type="StyleBox" id=2]
|
||||||
|
|
||||||
|
[node name="ChatMessage" type="HBoxContainer"]
|
||||||
|
margin_right = 710.0
|
||||||
|
margin_bottom = 45.0
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
custom_constants/separation = 35
|
||||||
|
script = ExtResource( 1 )
|
||||||
|
|
||||||
|
[node name="Username" type="Label" parent="."]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
margin_top = 45.0
|
||||||
|
margin_right = 64.0
|
||||||
|
margin_bottom = 64.0
|
||||||
|
custom_styles/normal = ExtResource( 2 )
|
||||||
|
text = "username"
|
||||||
|
|
||||||
|
[node name="Message" type="Label" parent="."]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
margin_left = 99.0
|
||||||
|
margin_right = 710.0
|
||||||
|
margin_bottom = 109.0
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
custom_styles/normal = ExtResource( 2 )
|
||||||
|
text = "Very Long TextVery Long TextVery Long TextVery Long TextVery Long TextVery Long TextVery Long TextVery Long TextVery Long TextVery Long TextVery Long TextVery Long TextVery Long TextVery Long TextVery Long TextVery Long TextVery Long TextVery Long TextVery Long TextVery Long TextVery Long TextVery Long TextVery Long TextVery Long TextVery Long TextVery Long TextVery Long Text
|
||||||
|
"
|
||||||
|
autowrap = true
|
||||||
73
src/mods-unpacked/Brogether-Brogether/ui/chat_panel.tscn
Normal file
73
src/mods-unpacked/Brogether-Brogether/ui/chat_panel.tscn
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
[gd_scene load_steps=3 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://ui/menus/global/arrow_right.png" type="Texture" id=3]
|
||||||
|
[ext_resource path="res://ui/menus/global/arrow_left.png" type="Texture" id=4]
|
||||||
|
|
||||||
|
[node name="ChatPanel" type="PanelContainer"]
|
||||||
|
margin_left = 1540.0
|
||||||
|
margin_right = 1853.0
|
||||||
|
margin_bottom = 500.0
|
||||||
|
rect_min_size = Vector2( 0, 500 )
|
||||||
|
|
||||||
|
[node name="MarginContainer" type="MarginContainer" parent="."]
|
||||||
|
margin_left = 7.0
|
||||||
|
margin_top = 7.0
|
||||||
|
margin_right = 343.0
|
||||||
|
margin_bottom = 493.0
|
||||||
|
custom_constants/margin_right = 25
|
||||||
|
custom_constants/margin_top = 25
|
||||||
|
custom_constants/margin_left = 25
|
||||||
|
custom_constants/margin_bottom = 25
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
|
||||||
|
margin_left = 25.0
|
||||||
|
margin_top = 25.0
|
||||||
|
margin_right = 311.0
|
||||||
|
margin_bottom = 461.0
|
||||||
|
custom_constants/separation = 25
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
|
||||||
|
margin_right = 286.0
|
||||||
|
margin_bottom = 34.0
|
||||||
|
custom_constants/separation = 15
|
||||||
|
alignment = 1
|
||||||
|
|
||||||
|
[node name="LeftArrow" type="TextureButton" parent="MarginContainer/VBoxContainer/HBoxContainer"]
|
||||||
|
margin_right = 33.0
|
||||||
|
margin_bottom = 34.0
|
||||||
|
texture_normal = ExtResource( 4 )
|
||||||
|
|
||||||
|
[node name="ChatTitle" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer"]
|
||||||
|
margin_left = 48.0
|
||||||
|
margin_top = 1.0
|
||||||
|
margin_right = 238.0
|
||||||
|
margin_bottom = 32.0
|
||||||
|
rect_min_size = Vector2( 190, 0 )
|
||||||
|
text = "Global Chat"
|
||||||
|
clip_text = true
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[node name="RightArrow" type="TextureButton" parent="MarginContainer/VBoxContainer/HBoxContainer"]
|
||||||
|
margin_left = 253.0
|
||||||
|
margin_right = 286.0
|
||||||
|
margin_bottom = 34.0
|
||||||
|
texture_normal = ExtResource( 3 )
|
||||||
|
|
||||||
|
[node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer/VBoxContainer"]
|
||||||
|
margin_top = 59.0
|
||||||
|
margin_right = 286.0
|
||||||
|
margin_bottom = 387.0
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
scroll_horizontal_enabled = false
|
||||||
|
|
||||||
|
[node name="ChatMessages" type="VBoxContainer" parent="MarginContainer/VBoxContainer/ScrollContainer"]
|
||||||
|
margin_right = 286.0
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="ChatInput" type="LineEdit" parent="MarginContainer/VBoxContainer"]
|
||||||
|
margin_top = 412.0
|
||||||
|
margin_right = 286.0
|
||||||
|
margin_bottom = 436.0
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
extends VBoxContainer
|
||||||
|
|
||||||
|
var health_bar_map = {}
|
||||||
|
|
||||||
|
const HealthBar = preload("res://ui/hud/ui_progress_bar.tscn")
|
||||||
|
|
||||||
|
func init(tracked_players:Dictionary) -> void:
|
||||||
|
var life_bar = $TemplateLifeBar
|
||||||
|
|
||||||
|
for tracked_player_id in tracked_players:
|
||||||
|
var health_bar = life_bar.duplicate()
|
||||||
|
add_child(health_bar)
|
||||||
|
health_bar_map[tracked_player_id] = health_bar
|
||||||
|
|
||||||
|
remove_child(life_bar)
|
||||||
|
update_health_bars(tracked_players)
|
||||||
|
|
||||||
|
func update_health_bars(tracked_players:Dictionary) -> void:
|
||||||
|
for tracked_player_id in tracked_players:
|
||||||
|
var player = tracked_players[tracked_player_id]
|
||||||
|
var health_bar = health_bar_map[tracked_player_id]
|
||||||
|
|
||||||
|
if player.has("username"):
|
||||||
|
var name_label = health_bar.get_node("NameLabel")
|
||||||
|
name_label.text = str(player.username)
|
||||||
|
|
||||||
|
var current_health = 15
|
||||||
|
var max_health = 15
|
||||||
|
|
||||||
|
|
||||||
|
if player.has("player") and is_instance_valid(player.player):
|
||||||
|
current_health = player.player.current_stats.health
|
||||||
|
max_health = player.player.max_stats.health
|
||||||
|
|
||||||
|
|
||||||
|
if max_health != 0:
|
||||||
|
health_bar.update_value(current_health, max_health)
|
||||||
|
|
||||||
|
var life_label = health_bar.get_node("MarginContainer/LifeLabel")
|
||||||
|
life_label.text = str(max(current_health, 0.0)) + " / " + str(max_health)
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
[gd_scene load_steps=3 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://ui/hud/ui_progress_bar.tscn" type="PackedScene" id=1]
|
||||||
|
[ext_resource path="res://mods-unpacked/Brogether-Brogether/ui/health_tracker/health_tracker.gd" type="Script" id=3]
|
||||||
|
|
||||||
|
[node name="HealthTracker" type="VBoxContainer"]
|
||||||
|
margin_left = 30.0
|
||||||
|
margin_top = 300.0
|
||||||
|
margin_right = 350.0
|
||||||
|
margin_bottom = 452.0
|
||||||
|
script = ExtResource( 3 )
|
||||||
|
|
||||||
|
[node name="TemplateLifeBar" parent="." instance=ExtResource( 1 )]
|
||||||
|
margin_bottom = 48.0
|
||||||
|
size_flags_horizontal = 0
|
||||||
|
tint_progress = Color( 0.721569, 0, 0, 1 )
|
||||||
|
progress_color = Color( 0.721569, 0, 0, 1 )
|
||||||
|
|
||||||
|
[node name="NameLabel" type="Label" parent="TemplateLifeBar"]
|
||||||
|
anchor_left = 1.0
|
||||||
|
anchor_right = 1.0
|
||||||
|
margin_left = 12.0
|
||||||
|
margin_top = 8.0
|
||||||
|
margin_right = 308.0
|
||||||
|
margin_bottom = 39.0
|
||||||
|
grow_horizontal = 0
|
||||||
|
text = "8 / 8"
|
||||||
|
valign = 1
|
||||||
|
uppercase = true
|
||||||
|
|
||||||
|
[node name="MarginContainer" type="MarginContainer" parent="TemplateLifeBar"]
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
custom_constants/margin_right = 12
|
||||||
|
custom_constants/margin_top = 7
|
||||||
|
custom_constants/margin_left = 12
|
||||||
|
custom_constants/margin_bottom = 7
|
||||||
|
|
||||||
|
[node name="LifeLabel" type="Label" parent="TemplateLifeBar/MarginContainer"]
|
||||||
|
margin_left = 12.0
|
||||||
|
margin_top = 8.0
|
||||||
|
margin_right = 308.0
|
||||||
|
margin_bottom = 39.0
|
||||||
|
grow_horizontal = 0
|
||||||
|
text = "8 / 8"
|
||||||
|
align = 1
|
||||||
|
valign = 1
|
||||||
|
uppercase = true
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[editable path="TemplateLifeBar"]
|
||||||
17
src/mods-unpacked/Brogether-Brogether/ui/lobby_entry.gd
Normal file
17
src/mods-unpacked/Brogether-Brogether/ui/lobby_entry.gd
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
extends HBoxContainer
|
||||||
|
|
||||||
|
var lobby_id
|
||||||
|
var lobby_name
|
||||||
|
|
||||||
|
var steam_connection
|
||||||
|
|
||||||
|
onready var lobby_name_label = $"%LobbyName"
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
steam_connection = $"/root/SteamConnection"
|
||||||
|
lobby_name_label.text = lobby_name
|
||||||
|
|
||||||
|
|
||||||
|
func _on_join_button_pressed():
|
||||||
|
Steam.joinLobby(lobby_id)
|
||||||
25
src/mods-unpacked/Brogether-Brogether/ui/lobby_entry.tscn
Normal file
25
src/mods-unpacked/Brogether-Brogether/ui/lobby_entry.tscn
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
[gd_scene load_steps=2 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://mods-unpacked/Brogether-Brogether/ui/lobby_entry.gd" type="Script" id=1]
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer"]
|
||||||
|
margin_right = 789.0
|
||||||
|
margin_bottom = 65.0
|
||||||
|
custom_constants/separation = 30
|
||||||
|
script = ExtResource( 1 )
|
||||||
|
|
||||||
|
[node name="JoinButton" type="Button" parent="."]
|
||||||
|
margin_right = 35.0
|
||||||
|
margin_bottom = 65.0
|
||||||
|
text = "Join"
|
||||||
|
|
||||||
|
[node name="LobbyName" type="Label" parent="."]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
margin_left = 65.0
|
||||||
|
margin_top = 25.0
|
||||||
|
margin_right = 145.0
|
||||||
|
margin_bottom = 39.0
|
||||||
|
text = "Lobby Name"
|
||||||
|
align = 1
|
||||||
|
|
||||||
|
[connection signal="pressed" from="JoinButton" to="." method="_on_join_button_pressed"]
|
||||||
103
src/mods-unpacked/Brogether-Brogether/ui/multiplayer_menu.gd
Normal file
103
src/mods-unpacked/Brogether-Brogether/ui/multiplayer_menu.gd
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
extends Control
|
||||||
|
|
||||||
|
# must be greater than 1024
|
||||||
|
var SERVER_PORT = 11111
|
||||||
|
var MAX_PLAYERS = 5
|
||||||
|
|
||||||
|
const ChatMessage = preload("res://mods-unpacked/Brogether-Brogether/ui/chat/chat_message.tscn")
|
||||||
|
const LobbyEntry = preload("res://mods-unpacked/Brogether-Brogether/ui/lobby_entry.tscn")
|
||||||
|
|
||||||
|
const DirectConnection = preload("res://mods-unpacked/Brogether-Brogether/networking/direct_connection.gd")
|
||||||
|
|
||||||
|
var GameController = load("res://mods-unpacked/Brogether-Brogether/networking/game_controller.gd")
|
||||||
|
|
||||||
|
var direct_connection
|
||||||
|
var game_controller
|
||||||
|
|
||||||
|
var DEBUG = false
|
||||||
|
|
||||||
|
onready var chat_messages = $"%ChatMessages"
|
||||||
|
onready var lobbies_list = $"%Lobbies"
|
||||||
|
onready var chat_input : LineEdit = $"%ChatInput"
|
||||||
|
onready var create_lobby_button : Button = $"%CreateLobbyButton"
|
||||||
|
|
||||||
|
# Manual on ready vars
|
||||||
|
var steam_connection
|
||||||
|
var brotatogether_options
|
||||||
|
|
||||||
|
# Called when the node enters the scene tree for the first time.
|
||||||
|
func _ready():
|
||||||
|
steam_connection = $"/root/SteamConnection"
|
||||||
|
steam_connection.connect("global_chat_received", self, "_received_global_chat")
|
||||||
|
steam_connection.connect("game_lobby_found", self, "_game_lobby_found")
|
||||||
|
|
||||||
|
brotatogether_options = $"/root/BrotogetherOptions"
|
||||||
|
|
||||||
|
for message in steam_connection.pending_system_messages:
|
||||||
|
var new_message_node = ChatMessage.instance()
|
||||||
|
new_message_node.message = message
|
||||||
|
new_message_node.username = "SYSTEM"
|
||||||
|
chat_messages.add_child(new_message_node)
|
||||||
|
steam_connection.pending_system_messages.clear()
|
||||||
|
create_lobby_button.grab_focus()
|
||||||
|
CoopService.clear_coop_players()
|
||||||
|
|
||||||
|
# var solo_test_btn = Button.new()
|
||||||
|
# solo_test_btn.text = "Solo Test"
|
||||||
|
# create_lobby_button.get_parent().add_child(solo_test_btn)
|
||||||
|
# solo_test_btn.connect("pressed", self, "_on_solo_test_button_pressed")
|
||||||
|
|
||||||
|
|
||||||
|
func _input(event:InputEvent)->void :
|
||||||
|
manage_back(event)
|
||||||
|
|
||||||
|
|
||||||
|
func manage_back(event:InputEvent)->void :
|
||||||
|
if event.is_action_pressed("ui_cancel"):
|
||||||
|
RunData.current_zone = 0
|
||||||
|
RunData.reload_music = false
|
||||||
|
var _error = get_tree().change_scene(MenuData.title_screen_scene)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_back_button_pressed():
|
||||||
|
RunData.reload_music = false
|
||||||
|
var _error = get_tree().change_scene(MenuData.title_screen_scene)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_chat_input_text_entered(message):
|
||||||
|
steam_connection.send_global_chat_message(message)
|
||||||
|
chat_input.clear()
|
||||||
|
|
||||||
|
|
||||||
|
func _received_global_chat(user, message) -> void:
|
||||||
|
var new_message_node = ChatMessage.instance()
|
||||||
|
new_message_node.message = message
|
||||||
|
new_message_node.username = user
|
||||||
|
chat_messages.add_child(new_message_node)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_solo_test_button_pressed() -> void:
|
||||||
|
steam_connection.game_lobby_id = 1
|
||||||
|
steam_connection.game_lobby_owner_id = steam_connection.steam_id
|
||||||
|
steam_connection.lobby_members = [steam_connection.steam_id]
|
||||||
|
steam_connection.lobby_member_names = [Steam.getFriendPersonaName(steam_connection.steam_id)]
|
||||||
|
brotatogether_options.is_solo_test = true
|
||||||
|
brotatogether_options.joining_multiplayer_lobby = true
|
||||||
|
var _error = get_tree().change_scene(MenuData.character_selection_scene)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_create_lobby_button_pressed():
|
||||||
|
steam_connection.create_new_game_lobby()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_refresh_lobbies_button_pressed():
|
||||||
|
for child in lobbies_list.get_children():
|
||||||
|
lobbies_list.remove_child(child)
|
||||||
|
steam_connection.request_lobby_search()
|
||||||
|
|
||||||
|
|
||||||
|
func _game_lobby_found(lobby_id, lobby_name) -> void:
|
||||||
|
var new_lobby_entry = LobbyEntry.instance()
|
||||||
|
new_lobby_entry.lobby_id = lobby_id
|
||||||
|
new_lobby_entry.lobby_name = lobby_name
|
||||||
|
lobbies_list.add_child(new_lobby_entry)
|
||||||
107
src/mods-unpacked/Brogether-Brogether/ui/multiplayer_menu.tscn
Normal file
107
src/mods-unpacked/Brogether-Brogether/ui/multiplayer_menu.tscn
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
[gd_scene load_steps=4 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://resources/themes/base_theme.tres" type="Theme" id=2]
|
||||||
|
[ext_resource path="res://mods-unpacked/Brogether-Brogether/ui/multiplayer_menu.gd" type="Script" id=3]
|
||||||
|
[ext_resource path="res://ui/menus/global/my_menu_button.gd" type="Script" id=4]
|
||||||
|
|
||||||
|
[node name="MultiplayerMenu" type="Control"]
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
margin_left = -3.0
|
||||||
|
margin_bottom = 10.0
|
||||||
|
theme = ExtResource( 2 )
|
||||||
|
script = ExtResource( 3 )
|
||||||
|
|
||||||
|
[node name="TitleLabel" type="Label" parent="."]
|
||||||
|
self_modulate = Color( 1, 0.6, 0.1, 1 )
|
||||||
|
margin_left = 300.0
|
||||||
|
margin_top = 48.0
|
||||||
|
margin_right = 1000.0
|
||||||
|
margin_bottom = 148.0
|
||||||
|
text = "Brogether"
|
||||||
|
|
||||||
|
|
||||||
|
[node name="BackButton" type="Button" parent="."]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
self_modulate = Color( 1, 1, 1, 0.862745 )
|
||||||
|
margin_left = 48.0
|
||||||
|
margin_top = 48.0
|
||||||
|
margin_right = 233.0
|
||||||
|
margin_bottom = 99.0
|
||||||
|
size_flags_horizontal = 4
|
||||||
|
size_flags_vertical = 4
|
||||||
|
text = "MENU_BACK"
|
||||||
|
script = ExtResource( 4 )
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="."]
|
||||||
|
margin_left = 300.0
|
||||||
|
margin_top = 173.0
|
||||||
|
margin_right = 1883.0
|
||||||
|
margin_bottom = 1066.0
|
||||||
|
|
||||||
|
[node name="ChatContainer2" type="VBoxContainer" parent="HBoxContainer"]
|
||||||
|
margin_right = 789.0
|
||||||
|
margin_bottom = 893.0
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="HBoxContainer/ChatContainer2"]
|
||||||
|
margin_right = 789.0
|
||||||
|
margin_bottom = 893.0
|
||||||
|
custom_constants/separation = 28
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="HBoxContainer/ChatContainer2/VBoxContainer"]
|
||||||
|
margin_right = 789.0
|
||||||
|
margin_bottom = 65.0
|
||||||
|
|
||||||
|
[node name="CreateLobbyButton" type="Button" parent="HBoxContainer/ChatContainer2/VBoxContainer/HBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
margin_right = 303.0
|
||||||
|
margin_bottom = 65.0
|
||||||
|
text = "Create Lobby"
|
||||||
|
|
||||||
|
[node name="RefreshLobbiesButton" type="Button" parent="HBoxContainer/ChatContainer2/VBoxContainer/HBoxContainer"]
|
||||||
|
margin_left = 307.0
|
||||||
|
margin_right = 666.0
|
||||||
|
margin_bottom = 65.0
|
||||||
|
text = "Refresh Lobbies"
|
||||||
|
|
||||||
|
[node name="ScrollContainer" type="ScrollContainer" parent="HBoxContainer/ChatContainer2/VBoxContainer"]
|
||||||
|
margin_top = 93.0
|
||||||
|
margin_right = 789.0
|
||||||
|
margin_bottom = 893.0
|
||||||
|
rect_min_size = Vector2( 0, 800 )
|
||||||
|
|
||||||
|
[node name="Lobbies" type="VBoxContainer" parent="HBoxContainer/ChatContainer2/VBoxContainer/ScrollContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
margin_right = 789.0
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
custom_constants/separation = 15
|
||||||
|
|
||||||
|
[node name="ChatContainer" type="VBoxContainer" parent="HBoxContainer"]
|
||||||
|
margin_left = 793.0
|
||||||
|
margin_right = 1583.0
|
||||||
|
margin_bottom = 893.0
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="ScrollContainer" type="ScrollContainer" parent="HBoxContainer/ChatContainer"]
|
||||||
|
margin_right = 790.0
|
||||||
|
margin_bottom = 800.0
|
||||||
|
rect_min_size = Vector2( 0, 800 )
|
||||||
|
|
||||||
|
[node name="ChatMessages" type="VBoxContainer" parent="HBoxContainer/ChatContainer/ScrollContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
margin_right = 790.0
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
custom_constants/separation = 15
|
||||||
|
|
||||||
|
[node name="ChatInput" type="LineEdit" parent="HBoxContainer/ChatContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
margin_top = 804.0
|
||||||
|
margin_right = 790.0
|
||||||
|
margin_bottom = 858.0
|
||||||
|
placeholder_text = "Type to Chat..."
|
||||||
|
|
||||||
|
[connection signal="pressed" from="BackButton" to="." method="_on_back_button_pressed"]
|
||||||
|
[connection signal="pressed" from="HBoxContainer/ChatContainer2/VBoxContainer/HBoxContainer/CreateLobbyButton" to="." method="_on_create_lobby_button_pressed"]
|
||||||
|
[connection signal="pressed" from="HBoxContainer/ChatContainer2/VBoxContainer/HBoxContainer/RefreshLobbiesButton" to="." method="_on_refresh_lobbies_button_pressed"]
|
||||||
|
[connection signal="text_entered" from="HBoxContainer/ChatContainer/ChatInput" to="." method="_on_chat_input_text_entered"]
|
||||||
102
src/mods-unpacked/Brogether-Brogether/ui/player_selections.gd
Normal file
102
src/mods-unpacked/Brogether-Brogether/ui/player_selections.gd
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
extends HBoxContainer
|
||||||
|
|
||||||
|
signal ready_toggled(is_ready)
|
||||||
|
|
||||||
|
onready var selected_character_element := get_node("%SelectedCharacter")
|
||||||
|
onready var selected_weapon_element := get_node("%SelectedWeapon")
|
||||||
|
onready var selected_danger_element := get_node("%SelectedDanger")
|
||||||
|
onready var username_label := get_node("%Username")
|
||||||
|
onready var ready_toggle := get_node("%ReadyToggle")
|
||||||
|
|
||||||
|
var unpicked_icon = load("res://items/global/random_icon.png")
|
||||||
|
|
||||||
|
|
||||||
|
func set_player_name(name:String) -> void:
|
||||||
|
username_label.text = name
|
||||||
|
|
||||||
|
|
||||||
|
func disable_selections() -> void:
|
||||||
|
selected_character_element.disabled = true
|
||||||
|
selected_weapon_element.disabled = true
|
||||||
|
selected_danger_element.disabled = true
|
||||||
|
|
||||||
|
|
||||||
|
func hide_ready_toggle() -> void:
|
||||||
|
ready_toggle.hide()
|
||||||
|
|
||||||
|
|
||||||
|
func disable_ready_toggle() -> void:
|
||||||
|
ready_toggle.disabled = true
|
||||||
|
|
||||||
|
|
||||||
|
func _on_SelectedCharacter_element_pressed(_element):
|
||||||
|
$"/root/GameController".back_to_lobby = true
|
||||||
|
var _error = get_tree().change_scene(MenuData.character_selection_scene)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_SelectedWeapon_element_pressed(_element):
|
||||||
|
$"/root/GameController".back_to_lobby = true
|
||||||
|
var _error = get_tree().change_scene(MenuData.weapon_selection_scene)
|
||||||
|
|
||||||
|
|
||||||
|
func set_player_selections(selections_dict : Dictionary, is_me:bool = false, lock_danger: bool = false) -> void:
|
||||||
|
var weapon_required = true
|
||||||
|
if selections_dict.has("character"):
|
||||||
|
var character_id = selections_dict["character"]
|
||||||
|
for character in ItemService.characters:
|
||||||
|
if character.my_id == character_id:
|
||||||
|
selected_character_element.set_element(character)
|
||||||
|
if character.starting_weapons.empty():
|
||||||
|
weapon_required = false
|
||||||
|
break
|
||||||
|
if is_me:
|
||||||
|
if weapon_required:
|
||||||
|
selected_weapon_element.disabled = false
|
||||||
|
else:
|
||||||
|
selected_weapon_element.disabled = true
|
||||||
|
selected_danger_element.disabled = false
|
||||||
|
else:
|
||||||
|
selected_character_element.icon = unpicked_icon
|
||||||
|
selected_weapon_element.disabled = true
|
||||||
|
selected_danger_element.disabled = true
|
||||||
|
|
||||||
|
if selections_dict.has("weapon"):
|
||||||
|
var weapon_id = selections_dict["weapon"]
|
||||||
|
for weapon in ItemService.weapons:
|
||||||
|
if weapon.my_id == weapon_id:
|
||||||
|
selected_weapon_element.set_element(weapon)
|
||||||
|
break
|
||||||
|
if is_me:
|
||||||
|
selected_danger_element.disabled = false
|
||||||
|
else:
|
||||||
|
selected_weapon_element.icon = unpicked_icon
|
||||||
|
selected_danger_element.disabled = weapon_required
|
||||||
|
|
||||||
|
if selections_dict.has("danger"):
|
||||||
|
var danger_id = selections_dict["danger"]
|
||||||
|
for difficulty in ItemService.difficulties:
|
||||||
|
if difficulty.my_id == danger_id:
|
||||||
|
selected_danger_element.set_element(difficulty)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
selected_danger_element.icon = unpicked_icon
|
||||||
|
|
||||||
|
if selections_dict.has("ready"):
|
||||||
|
ready_toggle.pressed = selections_dict["ready"]
|
||||||
|
|
||||||
|
if lock_danger:
|
||||||
|
selected_danger_element.disabled = true
|
||||||
|
|
||||||
|
if is_me:
|
||||||
|
selected_character_element.disabled = false
|
||||||
|
if not is_me:
|
||||||
|
disable_selections()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_select_danger_element_pressed(_element):
|
||||||
|
$"/root/GameController".back_to_lobby = true
|
||||||
|
var _error = get_tree().change_scene(MenuData.difficulty_selection_scene)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_ReadyToggle_toggled(button_pressed):
|
||||||
|
emit_signal("ready_toggled", button_pressed)
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
[gd_scene load_steps=4 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://mods-unpacked/Brogether-Brogether/ui/player_selections.gd" type="Script" id=1]
|
||||||
|
[ext_resource path="res://items/global/inventory_element.tscn" type="PackedScene" id=2]
|
||||||
|
[ext_resource path="res://items/global/random_icon.png" type="Texture" id=5]
|
||||||
|
|
||||||
|
[node name="PlayerSelections" type="HBoxContainer"]
|
||||||
|
margin_right = 1120.0
|
||||||
|
margin_bottom = 105.0
|
||||||
|
custom_constants/separation = 5
|
||||||
|
script = ExtResource( 1 )
|
||||||
|
|
||||||
|
[node name="SelectedCharacter" parent="." instance=ExtResource( 2 )]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
margin_right = 108.0
|
||||||
|
margin_bottom = 105.0
|
||||||
|
rect_min_size = Vector2( 105, 105 )
|
||||||
|
size_flags_horizontal = 0
|
||||||
|
size_flags_vertical = 0
|
||||||
|
icon = ExtResource( 5 )
|
||||||
|
expand_icon = false
|
||||||
|
|
||||||
|
[node name="SelectedWeapon" parent="." instance=ExtResource( 2 )]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
margin_left = 113.0
|
||||||
|
margin_right = 218.0
|
||||||
|
margin_bottom = 105.0
|
||||||
|
rect_min_size = Vector2( 105, 105 )
|
||||||
|
size_flags_horizontal = 0
|
||||||
|
size_flags_vertical = 0
|
||||||
|
icon = ExtResource( 5 )
|
||||||
|
|
||||||
|
[node name="SelectedDanger" parent="." instance=ExtResource( 2 )]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
margin_left = 223.0
|
||||||
|
margin_right = 328.0
|
||||||
|
margin_bottom = 105.0
|
||||||
|
rect_min_size = Vector2( 105, 105 )
|
||||||
|
size_flags_horizontal = 0
|
||||||
|
size_flags_vertical = 0
|
||||||
|
icon = ExtResource( 5 )
|
||||||
|
|
||||||
|
[node name="Username" type="Label" parent="."]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
margin_left = 333.0
|
||||||
|
margin_top = 30.0
|
||||||
|
margin_right = 970.0
|
||||||
|
margin_bottom = 75.0
|
||||||
|
rect_min_size = Vector2( 500, 0 )
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = "USERNAME"
|
||||||
|
clip_text = true
|
||||||
|
|
||||||
|
[node name="ReadyToggle" type="CheckButton" parent="."]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
margin_left = 975.0
|
||||||
|
margin_top = 32.0
|
||||||
|
margin_right = 1120.0
|
||||||
|
margin_bottom = 72.0
|
||||||
|
size_flags_vertical = 4
|
||||||
|
text = "Ready"
|
||||||
|
align = 1
|
||||||
|
|
||||||
|
[connection signal="element_pressed" from="SelectedCharacter" to="." method="_on_SelectedCharacter_element_pressed"]
|
||||||
|
[connection signal="element_pressed" from="SelectedWeapon" to="." method="_on_SelectedWeapon_element_pressed"]
|
||||||
|
[connection signal="element_pressed" from="SelectedDanger" to="." method="_on_select_danger_element_pressed"]
|
||||||
|
[connection signal="toggled" from="ReadyToggle" to="." method="_on_ReadyToggle_toggled"]
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
[gd_scene load_steps=8 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://resources/fonts/raw/NotoSansSC-Medium.otf" type="DynamicFontData" id=1]
|
||||||
|
[ext_resource path="res://resources/themes/base_theme.tres" type="Theme" id=2]
|
||||||
|
[ext_resource path="res://resources/fonts/raw/Anybody-Medium.ttf" type="DynamicFontData" id=3]
|
||||||
|
[ext_resource path="res://resources/fonts/raw/NotoSansJP-Medium.otf" type="DynamicFontData" id=4]
|
||||||
|
[ext_resource path="res://resources/fonts/raw/NotoSansTC-Medium.otf" type="DynamicFontData" id=5]
|
||||||
|
[ext_resource path="res://resources/fonts/raw/NotoSansKR-Medium.otf" type="DynamicFontData" id=6]
|
||||||
|
|
||||||
|
[sub_resource type="DynamicFont" id=1]
|
||||||
|
size = 18
|
||||||
|
extra_spacing_top = 10
|
||||||
|
font_data = ExtResource( 3 )
|
||||||
|
fallback/0 = ExtResource( 4 )
|
||||||
|
fallback/1 = ExtResource( 6 )
|
||||||
|
fallback/2 = ExtResource( 1 )
|
||||||
|
fallback/3 = ExtResource( 5 )
|
||||||
|
|
||||||
|
[node name="Label" type="Label"]
|
||||||
|
margin_left = 136.0
|
||||||
|
margin_right = 191.0
|
||||||
|
margin_bottom = 23.0
|
||||||
|
theme = ExtResource( 2 )
|
||||||
|
custom_fonts/font = SubResource( 1 )
|
||||||
|
text = "User 1 - 1"
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
extends StatsContainer
|
||||||
|
|
||||||
|
onready var game_controller = $"/root/GameController"
|
||||||
|
|
||||||
|
const shop_options_resource = preload("res://mods-unpacked/Brogether-Brogether/opponents_shop/data/opponents_shop_options.tres")
|
||||||
|
const shop_monster_container_scene = preload("res://mods-unpacked/Brogether-Brogether/ui/shop/shop_monster_container.tscn")
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
if not $"/root".has_node("GameController") or $"/root/GameController".is_coop():
|
||||||
|
$"/root/Shop/Content/MarginContainer/HBoxContainer/VBoxContainer2/StatsContainer/MarginContainer/VBoxContainer2/OpponentsButton".hide()
|
||||||
|
|
||||||
|
var opponents_shop = $MarginContainer/VBoxContainer2/OpponentsShop
|
||||||
|
for opponents_shop_option in shop_options_resource.shop_options:
|
||||||
|
var shop_option = shop_monster_container_scene.instance()
|
||||||
|
shop_option.init(opponents_shop_option, game_controller)
|
||||||
|
opponents_shop.add_child(shop_option)
|
||||||
|
|
||||||
|
func update_tab(tab:int)->void :
|
||||||
|
var has_opponents_tab = $"/root/Shop/Content/MarginContainer/HBoxContainer/VBoxContainer2/StatsContainer/MarginContainer/VBoxContainer2".has_node("OpponentsButton")
|
||||||
|
|
||||||
|
if tab == 3:
|
||||||
|
if has_opponents_tab:
|
||||||
|
var opponents_button = $"/root/Shop/Content/MarginContainer/HBoxContainer/VBoxContainer2/StatsContainer/MarginContainer/VBoxContainer2/OpponentsButton"
|
||||||
|
var opponents_shop = $"/root/Shop/Content/MarginContainer/HBoxContainer/VBoxContainer2/StatsContainer/MarginContainer/VBoxContainer2/OpponentsShop"
|
||||||
|
opponents_button.flat = true
|
||||||
|
opponents_shop.show()
|
||||||
|
_primary_tab.flat = false
|
||||||
|
_secondary_tab.flat = false
|
||||||
|
_general_stats.hide()
|
||||||
|
_primary_stats.hide()
|
||||||
|
_secondary_stats.hide()
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if has_opponents_tab:
|
||||||
|
var opponents_button = $"/root/Shop/Content/MarginContainer/HBoxContainer/VBoxContainer2/StatsContainer/MarginContainer/VBoxContainer2/OpponentsButton"
|
||||||
|
var opponents_shop = $"/root/Shop/Content/MarginContainer/HBoxContainer/VBoxContainer2/StatsContainer/MarginContainer/VBoxContainer2/OpponentsShop"
|
||||||
|
opponents_button.flat = false
|
||||||
|
opponents_shop.hide()
|
||||||
|
.update_tab(tab)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_OpponentsButton_pressed():
|
||||||
|
update_tab(3)
|
||||||
|
|
||||||
|
func update_bought_items(tracked_players:Dictionary) -> void:
|
||||||
|
var opponents_shop = $MarginContainer/VBoxContainer2/OpponentsShop
|
||||||
|
for shop_item_container in opponents_shop.get_children():
|
||||||
|
shop_item_container.clear_player_counts()
|
||||||
|
for tracked_player_id in tracked_players:
|
||||||
|
var all_effects = {}
|
||||||
|
if tracked_players[tracked_player_id].has("extra_enemies_next_wave"):
|
||||||
|
all_effects.merge(tracked_players[tracked_player_id]["extra_enemies_next_wave"].duplicate())
|
||||||
|
if tracked_players[tracked_player_id].has("effects"):
|
||||||
|
all_effects.merge(tracked_players[tracked_player_id]["effects"])
|
||||||
|
for effect_path in all_effects:
|
||||||
|
if effect_path == shop_item_container._shop_option.effect.get_path():
|
||||||
|
var tracked_player = tracked_players[tracked_player_id]
|
||||||
|
var count = all_effects[effect_path]
|
||||||
|
var display_name = str(tracked_player_id)
|
||||||
|
if tracked_player.has("username"):
|
||||||
|
display_name = tracked_player["username"]
|
||||||
|
|
||||||
|
shop_item_container.add_player_count(display_name, count)
|
||||||
@@ -0,0 +1,368 @@
|
|||||||
|
[gd_scene load_steps=8 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://ui/menus/shop/secondary_stats_container.gd" type="Script" id=2]
|
||||||
|
[ext_resource path="res://resources/themes/base_theme.tres" type="Theme" id=3]
|
||||||
|
[ext_resource path="res://ui/menus/shop/stat_container.tscn" type="PackedScene" id=4]
|
||||||
|
[ext_resource path="res://ui/menus/shop/general_stats_container.tscn" type="PackedScene" id=5]
|
||||||
|
[ext_resource path="res://ui/menus/shop/secondary_stat_container.tscn" type="PackedScene" id=6]
|
||||||
|
[ext_resource path="res://ui/menus/global/my_menu_button.gd" type="Script" id=7]
|
||||||
|
[ext_resource path="res://mods-unpacked/Brogether-Brogether/ui/shop/multiplayer_stats_container.gd" type="Script" id=8]
|
||||||
|
|
||||||
|
[node name="MultiplayerStats" type="PanelContainer"]
|
||||||
|
self_modulate = Color( 1, 1, 1, 0.478431 )
|
||||||
|
margin_top = 132.0
|
||||||
|
margin_right = 384.0
|
||||||
|
margin_bottom = 368.0
|
||||||
|
rect_min_size = Vector2( 411, 782 )
|
||||||
|
theme = ExtResource( 3 )
|
||||||
|
script = ExtResource( 8 )
|
||||||
|
|
||||||
|
[node name="MarginContainer" type="MarginContainer" parent="."]
|
||||||
|
margin_left = 5.0
|
||||||
|
margin_top = 5.0
|
||||||
|
margin_right = 406.0
|
||||||
|
margin_bottom = 1332.0
|
||||||
|
custom_constants/margin_right = 10
|
||||||
|
custom_constants/margin_top = 10
|
||||||
|
custom_constants/margin_left = 10
|
||||||
|
custom_constants/margin_bottom = 10
|
||||||
|
|
||||||
|
[node name="VBoxContainer2" type="VBoxContainer" parent="MarginContainer"]
|
||||||
|
margin_left = 10.0
|
||||||
|
margin_top = 10.0
|
||||||
|
margin_right = 391.0
|
||||||
|
margin_bottom = 1317.0
|
||||||
|
custom_constants/separation = 20
|
||||||
|
|
||||||
|
[node name="OpponentsButton" type="Button" parent="MarginContainer/VBoxContainer2"]
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 51.0
|
||||||
|
rect_min_size = Vector2( 150, 0 )
|
||||||
|
text = "Opponents Shop"
|
||||||
|
clip_text = true
|
||||||
|
script = ExtResource( 7 )
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer2"]
|
||||||
|
margin_top = 71.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 122.0
|
||||||
|
custom_constants/separation = 10
|
||||||
|
alignment = 1
|
||||||
|
|
||||||
|
[node name="Primary" type="Button" parent="MarginContainer/VBoxContainer2/HBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
margin_left = 20.0
|
||||||
|
margin_right = 170.0
|
||||||
|
margin_bottom = 51.0
|
||||||
|
rect_min_size = Vector2( 150, 0 )
|
||||||
|
text = "PRIMARY"
|
||||||
|
clip_text = true
|
||||||
|
script = ExtResource( 7 )
|
||||||
|
|
||||||
|
[node name="Secondary" type="Button" parent="MarginContainer/VBoxContainer2/HBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
margin_left = 180.0
|
||||||
|
margin_right = 360.0
|
||||||
|
margin_bottom = 51.0
|
||||||
|
rect_min_size = Vector2( 180, 0 )
|
||||||
|
text = "SECONDARY"
|
||||||
|
clip_text = true
|
||||||
|
script = ExtResource( 7 )
|
||||||
|
|
||||||
|
[node name="GeneralStats" parent="MarginContainer/VBoxContainer2" instance=ExtResource( 5 )]
|
||||||
|
margin_top = 142.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 172.0
|
||||||
|
|
||||||
|
[node name="PrimaryStats" type="VBoxContainer" parent="MarginContainer/VBoxContainer2"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
margin_top = 192.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 687.0
|
||||||
|
custom_constants/separation = 1
|
||||||
|
|
||||||
|
[node name="MaxHPContainer" parent="MarginContainer/VBoxContainer2/PrimaryStats" instance=ExtResource( 4 )]
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 30.0
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
key = "STAT_MAX_HP"
|
||||||
|
|
||||||
|
[node name="HPRegenerationContainer" parent="MarginContainer/VBoxContainer2/PrimaryStats" instance=ExtResource( 4 )]
|
||||||
|
margin_top = 31.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 61.0
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
key = "STAT_HP_REGENERATION"
|
||||||
|
|
||||||
|
[node name="LifeStealContainer" parent="MarginContainer/VBoxContainer2/PrimaryStats" instance=ExtResource( 4 )]
|
||||||
|
margin_top = 62.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 92.0
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
key = "STAT_LIFESTEAL"
|
||||||
|
|
||||||
|
[node name="PercentDamageContainer" parent="MarginContainer/VBoxContainer2/PrimaryStats" instance=ExtResource( 4 )]
|
||||||
|
margin_top = 93.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 123.0
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
key = "STAT_PERCENT_DAMAGE"
|
||||||
|
|
||||||
|
[node name="MeleeDamageContainer" parent="MarginContainer/VBoxContainer2/PrimaryStats" instance=ExtResource( 4 )]
|
||||||
|
margin_top = 124.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 154.0
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
key = "STAT_MELEE_DAMAGE"
|
||||||
|
|
||||||
|
[node name="RangedDamageContainer" parent="MarginContainer/VBoxContainer2/PrimaryStats" instance=ExtResource( 4 )]
|
||||||
|
margin_top = 155.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 185.0
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
key = "STAT_RANGED_DAMAGE"
|
||||||
|
|
||||||
|
[node name="ElementalDamageContainer" parent="MarginContainer/VBoxContainer2/PrimaryStats" instance=ExtResource( 4 )]
|
||||||
|
margin_top = 186.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 216.0
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
key = "STAT_ELEMENTAL_DAMAGE"
|
||||||
|
|
||||||
|
[node name="AttackSpeedContainer" parent="MarginContainer/VBoxContainer2/PrimaryStats" instance=ExtResource( 4 )]
|
||||||
|
margin_top = 217.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 247.0
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
key = "STAT_ATTACK_SPEED"
|
||||||
|
|
||||||
|
[node name="CritChanceContainer" parent="MarginContainer/VBoxContainer2/PrimaryStats" instance=ExtResource( 4 )]
|
||||||
|
margin_top = 248.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 278.0
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
key = "STAT_CRIT_CHANCE"
|
||||||
|
|
||||||
|
[node name="EngineeringContainer" parent="MarginContainer/VBoxContainer2/PrimaryStats" instance=ExtResource( 4 )]
|
||||||
|
margin_top = 279.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 309.0
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
key = "STAT_ENGINEERING"
|
||||||
|
|
||||||
|
[node name="RangeContainer" parent="MarginContainer/VBoxContainer2/PrimaryStats" instance=ExtResource( 4 )]
|
||||||
|
margin_top = 310.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 340.0
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
key = "STAT_RANGE"
|
||||||
|
|
||||||
|
[node name="ArmorContainer" parent="MarginContainer/VBoxContainer2/PrimaryStats" instance=ExtResource( 4 )]
|
||||||
|
margin_top = 341.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 371.0
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
key = "STAT_ARMOR"
|
||||||
|
|
||||||
|
[node name="DodgeContainer" parent="MarginContainer/VBoxContainer2/PrimaryStats" instance=ExtResource( 4 )]
|
||||||
|
margin_top = 372.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 402.0
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
key = "STAT_DODGE"
|
||||||
|
|
||||||
|
[node name="SpeedContainer" parent="MarginContainer/VBoxContainer2/PrimaryStats" instance=ExtResource( 4 )]
|
||||||
|
margin_top = 403.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 433.0
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
key = "STAT_SPEED"
|
||||||
|
|
||||||
|
[node name="LuckContainer" parent="MarginContainer/VBoxContainer2/PrimaryStats" instance=ExtResource( 4 )]
|
||||||
|
margin_top = 434.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 464.0
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
key = "STAT_LUCK"
|
||||||
|
|
||||||
|
[node name="HarvestingContainer" parent="MarginContainer/VBoxContainer2/PrimaryStats" instance=ExtResource( 4 )]
|
||||||
|
margin_top = 465.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 495.0
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
key = "STAT_HARVESTING"
|
||||||
|
|
||||||
|
[node name="SecondaryStats" type="VBoxContainer" parent="MarginContainer/VBoxContainer2"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
margin_top = 707.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 1307.0
|
||||||
|
custom_constants/separation = 0
|
||||||
|
script = ExtResource( 2 )
|
||||||
|
|
||||||
|
[node name="ConsumableHealContainer" parent="MarginContainer/VBoxContainer2/SecondaryStats" instance=ExtResource( 6 )]
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 30.0
|
||||||
|
key = "CONSUMABLE_HEAL"
|
||||||
|
|
||||||
|
[node name="MaterialsHealContainer" parent="MarginContainer/VBoxContainer2/SecondaryStats" instance=ExtResource( 6 )]
|
||||||
|
margin_top = 30.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 60.0
|
||||||
|
key = "heal_when_pickup_gold"
|
||||||
|
custom_text_key = "CHANCE_HEAL_ON_GOLD"
|
||||||
|
|
||||||
|
[node name="XPGainContainer" parent="MarginContainer/VBoxContainer2/SecondaryStats" instance=ExtResource( 6 )]
|
||||||
|
margin_top = 60.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 90.0
|
||||||
|
key = "XP_GAIN"
|
||||||
|
|
||||||
|
[node name="PickupRangeContainer" parent="MarginContainer/VBoxContainer2/SecondaryStats" instance=ExtResource( 6 )]
|
||||||
|
margin_top = 90.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 120.0
|
||||||
|
key = "PICKUP_RANGE"
|
||||||
|
|
||||||
|
[node name="ItemPriceContainer" parent="MarginContainer/VBoxContainer2/SecondaryStats" instance=ExtResource( 6 )]
|
||||||
|
margin_top = 120.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 150.0
|
||||||
|
key = "ITEMS_PRICE"
|
||||||
|
reverse = true
|
||||||
|
|
||||||
|
[node name="ExplosionDamageContainer" parent="MarginContainer/VBoxContainer2/SecondaryStats" instance=ExtResource( 6 )]
|
||||||
|
margin_top = 150.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 180.0
|
||||||
|
key = "EXPLOSION_DAMAGE"
|
||||||
|
|
||||||
|
[node name="ExplosionSizeContainer" parent="MarginContainer/VBoxContainer2/SecondaryStats" instance=ExtResource( 6 )]
|
||||||
|
margin_top = 180.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 210.0
|
||||||
|
key = "EXPLOSION_SIZE"
|
||||||
|
|
||||||
|
[node name="BounceContainer" parent="MarginContainer/VBoxContainer2/SecondaryStats" instance=ExtResource( 6 )]
|
||||||
|
margin_top = 210.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 240.0
|
||||||
|
key = "BOUNCE"
|
||||||
|
|
||||||
|
[node name="PiercingContainer" parent="MarginContainer/VBoxContainer2/SecondaryStats" instance=ExtResource( 6 )]
|
||||||
|
margin_top = 240.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 270.0
|
||||||
|
key = "PIERCING"
|
||||||
|
|
||||||
|
[node name="PiercingDamageContainer" parent="MarginContainer/VBoxContainer2/SecondaryStats" instance=ExtResource( 6 )]
|
||||||
|
margin_top = 270.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 300.0
|
||||||
|
key = "PIERCING_DAMAGE"
|
||||||
|
|
||||||
|
[node name="DamageAgainstBossesContainer" parent="MarginContainer/VBoxContainer2/SecondaryStats" instance=ExtResource( 6 )]
|
||||||
|
margin_top = 300.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 330.0
|
||||||
|
key = "DAMAGE_AGAINST_BOSSES"
|
||||||
|
|
||||||
|
[node name="BurningCooldownReductionContainer" parent="MarginContainer/VBoxContainer2/SecondaryStats" instance=ExtResource( 6 )]
|
||||||
|
margin_top = 330.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 360.0
|
||||||
|
key = "BURNING_COOLDOWN_REDUCTION"
|
||||||
|
|
||||||
|
[node name="BurningSpreadContainer" parent="MarginContainer/VBoxContainer2/SecondaryStats" instance=ExtResource( 6 )]
|
||||||
|
margin_top = 360.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 390.0
|
||||||
|
key = "BURNING_SPREAD"
|
||||||
|
|
||||||
|
[node name="KnockbackContainer" parent="MarginContainer/VBoxContainer2/SecondaryStats" instance=ExtResource( 6 )]
|
||||||
|
margin_top = 390.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 420.0
|
||||||
|
key = "KNOCKBACK"
|
||||||
|
|
||||||
|
[node name="ChanceDoubleGoldContainer" parent="MarginContainer/VBoxContainer2/SecondaryStats" instance=ExtResource( 6 )]
|
||||||
|
margin_top = 420.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 450.0
|
||||||
|
key = "CHANCE_DOUBLE_GOLD"
|
||||||
|
|
||||||
|
[node name="ItemBoxGoldContainer" parent="MarginContainer/VBoxContainer2/SecondaryStats" instance=ExtResource( 6 )]
|
||||||
|
margin_top = 450.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 480.0
|
||||||
|
key = "ITEM_BOX_GOLD"
|
||||||
|
|
||||||
|
[node name="FreeRerollsContainer" parent="MarginContainer/VBoxContainer2/SecondaryStats" instance=ExtResource( 6 )]
|
||||||
|
margin_top = 480.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 510.0
|
||||||
|
key = "FREE_REROLLS"
|
||||||
|
|
||||||
|
[node name="TreesContainer" parent="MarginContainer/VBoxContainer2/SecondaryStats" instance=ExtResource( 6 )]
|
||||||
|
margin_top = 510.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 540.0
|
||||||
|
key = "TREES"
|
||||||
|
|
||||||
|
[node name="NumberOfEnemiesContainer" parent="MarginContainer/VBoxContainer2/SecondaryStats" instance=ExtResource( 6 )]
|
||||||
|
margin_top = 540.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 570.0
|
||||||
|
key = "NUMBER_OF_ENEMIES"
|
||||||
|
custom_text_key = "PCT_NUMBER_OF_ENEMIES"
|
||||||
|
|
||||||
|
[node name="EnemySpeedContainer" parent="MarginContainer/VBoxContainer2/SecondaryStats" instance=ExtResource( 6 )]
|
||||||
|
margin_top = 570.0
|
||||||
|
margin_right = 381.0
|
||||||
|
margin_bottom = 600.0
|
||||||
|
key = "ENEMY_SPEED"
|
||||||
|
custom_text_key = "PCT_ENEMY_SPEED"
|
||||||
|
reverse = true
|
||||||
|
|
||||||
|
[node name="OpponentsShop" type="VBoxContainer" parent="MarginContainer/VBoxContainer2"]
|
||||||
|
visible = false
|
||||||
|
margin_top = 1327.0
|
||||||
|
margin_right = 354.0
|
||||||
|
margin_bottom = 1327.0
|
||||||
|
custom_constants/separation = 10
|
||||||
|
|
||||||
|
[connection signal="pressed" from="MarginContainer/VBoxContainer2/OpponentsButton" to="." method="_on_OpponentsButton_pressed"]
|
||||||
|
[connection signal="pressed" from="MarginContainer/VBoxContainer2/HBoxContainer/Primary" to="." method="_on_Primary_pressed"]
|
||||||
|
[connection signal="pressed" from="MarginContainer/VBoxContainer2/HBoxContainer/Secondary" to="." method="_on_Secondary_pressed"]
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
extends VBoxContainer
|
||||||
|
class_name ShopMonsterContainer
|
||||||
|
|
||||||
|
var _shop_option
|
||||||
|
var game_controller
|
||||||
|
|
||||||
|
const count_label_scene = preload("res://mods-unpacked/Brogether-Brogether/ui/shop/count_label.tscn")
|
||||||
|
|
||||||
|
# TODO rename to work for all types
|
||||||
|
func init(shop_option: Resource, parent_game_controller) -> void:
|
||||||
|
game_controller = parent_game_controller
|
||||||
|
_shop_option = shop_option
|
||||||
|
var price: int = shop_option.price
|
||||||
|
var effect: Resource = shop_option.effect
|
||||||
|
var display_text: String = shop_option.display_text
|
||||||
|
|
||||||
|
get_node("ShopItem/Title").text = display_text
|
||||||
|
var _connection_error = get_node("ShopItem/VBoxContainer/BuyButton").connect("pressed", self, "_on_buyButton_pressed", [shop_option])
|
||||||
|
|
||||||
|
if effect is WaveGroupData:
|
||||||
|
for wave_unit_data in effect.wave_units_data:
|
||||||
|
var enemy = wave_unit_data.unit_scene.instance()
|
||||||
|
get_node("ShopItem/Icon").texture = enemy.get_node("Animation/Sprite").texture
|
||||||
|
elif effect is Effect:
|
||||||
|
if effect.key.begins_with("stat_"):
|
||||||
|
get_node("ShopItem/Icon").texture = ItemService.get_stat_icon(effect.key)
|
||||||
|
|
||||||
|
var adjusted_price = ItemService.get_value(RunData.current_wave, price, true, true)
|
||||||
|
get_node("ShopItem/VBoxContainer/BuyButton").text = str(adjusted_price)
|
||||||
|
|
||||||
|
func _on_buyButton_pressed(shop_option: Resource) -> void:
|
||||||
|
var adjusted_price = ItemService.get_value(RunData.current_wave, shop_option.price, true, true)
|
||||||
|
if RunData.gold >= adjusted_price:
|
||||||
|
RunData.remove_gold(adjusted_price)
|
||||||
|
game_controller.send_bought_item(shop_option)
|
||||||
|
|
||||||
|
$"/root/Shop"._shop_items_container.update_buttons_color()
|
||||||
|
|
||||||
|
func add_player_count(username:String, count: int) -> void:
|
||||||
|
var label = count_label_scene.instance()
|
||||||
|
label.text = str(username, "-", count)
|
||||||
|
|
||||||
|
get_node("PurchaseTracker").add_child(label)
|
||||||
|
|
||||||
|
func clear_player_counts() -> void:
|
||||||
|
var purchase_tracker = get_node("PurchaseTracker")
|
||||||
|
for child in purchase_tracker.get_children():
|
||||||
|
purchase_tracker.remove_child(child)
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
[gd_scene load_steps=4 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://items/materials/material_ui.png" type="Texture" id=1]
|
||||||
|
[ext_resource path="res://entities/units/enemies/001/1.png" type="Texture" id=4]
|
||||||
|
[ext_resource path="res://mods-unpacked/Brogether-Brogether/ui/shop/shop_monster_container.gd" type="Script" id=5]
|
||||||
|
|
||||||
|
[node name="ShopMonsterContainer" type="VBoxContainer"]
|
||||||
|
margin_left = -212.5
|
||||||
|
margin_right = 114.5
|
||||||
|
margin_bottom = 116.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
size_flags_vertical = 0
|
||||||
|
alignment = 1
|
||||||
|
script = ExtResource( 5 )
|
||||||
|
|
||||||
|
[node name="ShopItem" type="HBoxContainer" parent="."]
|
||||||
|
margin_top = 18.0
|
||||||
|
margin_right = 327.0
|
||||||
|
margin_bottom = 93.0
|
||||||
|
custom_constants/separation = 5
|
||||||
|
alignment = 2
|
||||||
|
|
||||||
|
[node name="Icon" type="TextureRect" parent="ShopItem"]
|
||||||
|
margin_left = 30.0
|
||||||
|
margin_right = 105.0
|
||||||
|
margin_bottom = 75.0
|
||||||
|
rect_min_size = Vector2( 75, 75 )
|
||||||
|
texture = ExtResource( 4 )
|
||||||
|
expand = true
|
||||||
|
stretch_mode = 6
|
||||||
|
|
||||||
|
[node name="Title" type="Label" parent="ShopItem"]
|
||||||
|
margin_left = 110.0
|
||||||
|
margin_top = 25.0
|
||||||
|
margin_right = 222.0
|
||||||
|
margin_bottom = 49.0
|
||||||
|
text = "Baby Alien"
|
||||||
|
align = 2
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="ShopItem"]
|
||||||
|
margin_left = 227.0
|
||||||
|
margin_right = 327.0
|
||||||
|
margin_bottom = 75.0
|
||||||
|
alignment = 1
|
||||||
|
|
||||||
|
[node name="BuyButton" type="Button" parent="ShopItem/VBoxContainer"]
|
||||||
|
margin_top = 19.0
|
||||||
|
margin_right = 100.0
|
||||||
|
margin_bottom = 56.0
|
||||||
|
grow_horizontal = 0
|
||||||
|
grow_vertical = 0
|
||||||
|
rect_min_size = Vector2( 100, 0 )
|
||||||
|
focus_neighbour_left = NodePath("../../../ShopItem/HBoxContainer/LockButton")
|
||||||
|
focus_neighbour_right = NodePath("../../../ShopItem3/HBoxContainer/LockButton")
|
||||||
|
size_flags_horizontal = 12
|
||||||
|
size_flags_vertical = 0
|
||||||
|
toggle_mode = true
|
||||||
|
text = "1500"
|
||||||
|
icon = ExtResource( 1 )
|
||||||
|
icon_align = 2
|
||||||
|
expand_icon = true
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[node name="PurchaseTracker" type="HBoxContainer" parent="."]
|
||||||
|
margin_top = 97.0
|
||||||
|
margin_right = 327.0
|
||||||
|
margin_bottom = 97.0
|
||||||
|
custom_constants/separation = 10
|
||||||
|
alignment = 1
|
||||||
10
src/mods-unpacked/Brogether-Brogether/ui/toggle.tscn
Normal file
10
src/mods-unpacked/Brogether-Brogether/ui/toggle.tscn
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[gd_scene load_steps=1 format=2]
|
||||||
|
|
||||||
|
|
||||||
|
[node name="DamageDisplayButton" type="CheckButton"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
margin_top = 365.0
|
||||||
|
margin_right = 780.0
|
||||||
|
margin_bottom = 435.0
|
||||||
|
focus_neighbour_right = NodePath("../../../../Column2/SoundContainer/PauseOnFocusLostButton")
|
||||||
|
text = "Ready"
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
[gd_scene format=2]
|
||||||
|
|
||||||
|
[node name="username_label" type="Label"]
|
||||||
|
size_flags_vertical = 1
|
||||||
|
text = "Username"
|
||||||
|
align = 1
|
||||||
Reference in New Issue
Block a user