diff --git a/vmf_source/scripts/mods/vmf/modules/mutators/default_config.lua b/vmf_source/scripts/mods/vmf/modules/mutators/default_config.lua index 4c4d85c..b36d451 100644 --- a/vmf_source/scripts/mods/vmf/modules/mutators/default_config.lua +++ b/vmf_source/scripts/mods/vmf/modules/mutators/default_config.lua @@ -4,7 +4,6 @@ return { tomes = 0, bonus = 0 }, - server_name = "", title = "", short_title = "", difficulties = { @@ -17,5 +16,9 @@ return { "survival_hard", "survival_harder", "survival_hardest" - } + }, + incompatible_with_all = false, + compatible_with_all = false, + incompatible_with = {}, + compatible_with = {} } diff --git a/vmf_source/scripts/mods/vmf/modules/mutators/gui.lua b/vmf_source/scripts/mods/vmf/modules/mutators/gui.lua index 9bfe2cd..e0f4b70 100644 --- a/vmf_source/scripts/mods/vmf/modules/mutators/gui.lua +++ b/vmf_source/scripts/mods/vmf/modules/mutators/gui.lua @@ -2,10 +2,26 @@ local vmf = get_mod("VMF") local mutators = vmf.mutators +local banner_level_widget = UIWidgets.create_texture_with_text_and_tooltip("title_bar", "Mutators", "map_level_setting_tooltip", "banner_level", "banner_level_text", { + vertical_alignment = "center", + scenegraph_id = "banner_level_text", + localize = false, + font_size = 28, + horizontal_alignment = "center", + font_type = "hell_shark", + text_color = Colors.get_color_table_with_alpha("cheeseburger", 255) +}) +local banner_level = UIWidget.init(banner_level_widget) + local window = nil local button = nil local window_opened = false +local function get_map_view() + local ingame_ui = Managers.matchmaking and Managers.matchmaking.ingame_ui + return ingame_ui and ingame_ui.views and ingame_ui.views.map_view +end + local function update_window_visibility(map_view) if not window then return end button.visible = map_view and map_view.friends and not map_view.friends:is_active() @@ -24,10 +40,8 @@ local function destroy_window(map_view) end local function create_window(map_view) - destroy_window(map_view) - vmf.sort_mutators() - vmf.disable_impossible_mutators() + destroy_window(map_view) local window_size = {0, 0} local window_position = {50, 500} @@ -35,13 +49,16 @@ local function create_window(map_view) window = get_mod("gui").create_window("mutators_window", window_position, window_size) for i, mutator in ipairs(mutators) do - window:create_checkbox("label" .. mutator:get_name(), {10, 40 * i}, {30, 30}, mutator:get_config().title, mutator:is_enabled(), function() - if not mutator:is_enabled() and mutator:can_be_enabled() then - mutator:enable() + local title = mutator:get_config().title or mutator:get_name() + window:create_checkbox("checkbox_" .. mutator:get_name(), {30, 360 - 40 * (i - 1)}, {30, 30}, title, mutator:is_enabled(), function(self) + if self.value then + if not mutator:is_enabled() and mutator:can_be_enabled() then + mutator:enable() + elseif not mutator:is_enabled() then + create_window(map_view) + end elseif mutator:is_enabled() then mutator:disable() - else - create_window(map_view) end end) end @@ -61,27 +78,43 @@ local function create_window(map_view) update_window_visibility(map_view) end +local function reload_window() + local map_view = get_map_view() + if map_view and map_view.active then + create_window(map_view) + end +end + vmf:hook("MapView.on_enter", function(func, self, ...) func(self, ...) print("on_enter") + + vmf.sort_mutators() + vmf.disable_impossible_mutators() vmf:pcall(function() create_window(self) end) end) vmf:hook("MapView.on_level_index_changed", function(func, self, ...) func(self, ...) print("on_level_index_changed") + + vmf.disable_impossible_mutators() vmf:pcall(function() create_window(self) end) end) vmf:hook("MapView.on_difficulty_index_changed", function(func, self, ...) func(self, ...) print("on_difficulty_index_changed") + + vmf.disable_impossible_mutators() vmf:pcall(function() create_window(self) end) end) vmf:hook("MapView.set_difficulty_stepper_index", function(func, self, ...) func(self, ...) print("set_difficulty_stepper_index") + + vmf.disable_impossible_mutators() vmf:pcall(function() create_window(self) end) end) @@ -121,16 +154,25 @@ vmf:hook("MapView.draw", function(func, self, input_service, gamepad_active, dt) UIRenderer.draw_widget(ui_renderer, widget) end - if not window_opened then - if self.settings_button_widget.content.toggled then - for widget_name, widget in pairs(self.advanced_settings_widgets) do - UIRenderer.draw_widget(ui_renderer, widget) - end - else - for widget_name, widget in pairs(self.normal_settings_widgets) do + if window_opened or not self.settings_button_widget.content.toggled then + for widget_name, widget in pairs(self.normal_settings_widgets) do + local skipped_widgets_keys = { + "stepper_level", + "level_preview", + "level_preview_text", + "banner_level" + } + if not window_opened or not table.has_item(skipped_widgets_keys, widget_name) then UIRenderer.draw_widget(ui_renderer, widget) end end + if window_opened then + vmf:pcall(function() UIRenderer.draw_widget(ui_renderer, banner_level) end) + end + else + for widget_name, widget in pairs(self.advanced_settings_widgets) do + UIRenderer.draw_widget(ui_renderer, widget) + end end UIRenderer.draw_widget(ui_renderer, self.player_list_conuter_text_widget) @@ -174,3 +216,5 @@ vmf:hook("MapView.draw", function(func, self, input_service, gamepad_active, dt) end end) + +return reload_window, get_map_view diff --git a/vmf_source/scripts/mods/vmf/modules/mutators/info.lua b/vmf_source/scripts/mods/vmf/modules/mutators/info.lua index c938fb0..f335cc4 100644 --- a/vmf_source/scripts/mods/vmf/modules/mutators/info.lua +++ b/vmf_source/scripts/mods/vmf/modules/mutators/info.lua @@ -38,7 +38,7 @@ local function set_lobby_data() Managers.matchmaking.lobby:set_lobby_data(lobby_data) end -local function get_member_func( client_cookie) +local function get_member_func(client_cookie) local peer_id = tostring(client_cookie) for _ = 1, 3 do peer_id = string.sub(peer_id, 1 + tonumber(tostring(string.find(peer_id,"-")))) diff --git a/vmf_source/scripts/mods/vmf/modules/mutators/mutators.lua b/vmf_source/scripts/mods/vmf/modules/mutators/mutators.lua index d9b03fd..fd182a7 100644 --- a/vmf_source/scripts/mods/vmf/modules/mutators/mutators.lua +++ b/vmf_source/scripts/mods/vmf/modules/mutators/mutators.lua @@ -89,11 +89,14 @@ end -- Disables mutators that cannot be enabled right now vmf.disable_impossible_mutators = function() + local disabled_mutators = {} for _, mutator in pairs(mutators) do if mutator:is_enabled() and not mutator:can_be_enabled() then mutator:disable() + table.insert(disabled_mutators, mutator) end end + return disabled_mutators end @@ -101,6 +104,7 @@ end PRIVATE METHODS ]]-- +local update_mutators_view, get_map_view = dofile("scripts/mods/vmf/modules/mutators/gui") local addDice, removeDice = dofile("scripts/mods/vmf/modules/mutators/dice") local set_lobby_data = dofile("scripts/mods/vmf/modules/mutators/info") @@ -121,6 +125,71 @@ local function update_mutators_sequence(mutator_name, enable_these_after) table.combine(mutators_sequence[mutator_name], enable_these_after) end +-- Checks if mutators are compatible both ways +local function is_compatible(mutator, other_mutator) + local config = mutator:get_config() + local name = mutator:get_name() + local other_config = other_mutator:get_config() + local other_name = other_mutator:get_name() + + local incompatible_specifically = ( + #config.incompatible_with > 0 and ( + table.has_item(config.incompatible_with, other_name) + ) or + #other_config.incompatible_with > 0 and ( + table.has_item(other_config.incompatible_with, name) + ) + ) + + local compatible_specifically = ( + #config.compatible_with > 0 and ( + table.has_item(config.compatible_with, other_name) + ) or + #other_config.compatible_with > 0 and ( + table.has_item(other_config.compatible_with, name) + ) + ) + + local compatible + if incompatible_specifically then + compatible = false + elseif compatible_specifically then + compatible = true + elseif config.compatible_with_all or other_config.compatible_with_all then + compatible = true + elseif config.incompatible_with_all or other_config.incompatible_with_all then + compatible = false + else + compatible = true + end + + return compatible +end + +-- Disables enabled mutators that aren't compatible with the specified +local function disable_incompatible_with(mutator) + local names = nil + for _, other_mutator in ipairs(mutators) do + if ( + other_mutator ~= mutator and + other_mutator:is_enabled() and + not is_compatible(mutator, other_mutator) + ) then + other_mutator:disable() + local name = other_mutator:get_config().title or other_mutator:get_name() + if names then + names = names .. " " .. name + else + names = name + end + end + end + if names then + -- TODO: output this to the menu instead of chat + vmf:echo("These mutators are incompatible with " .. mutator:get_name() .. " and were disabled: " .. names) + end +end + -- Called after mutator is enabled local function on_enabled(mutator) local config = mutator:get_config() @@ -157,6 +226,11 @@ local function set_mutator_state(mutator, state) vmf.sort_mutators() end + -- Disable mutators that aren't compatible + if state then + disable_incompatible_with(mutator) + end + local disabled_mutators = {} local enable_these_after = mutators_sequence[mutator:get_name()] @@ -193,6 +267,9 @@ local function set_mutator_state(mutator, state) disabled_mutators[j]:enable() end end + + update_mutators_view() + print("---------") end @@ -219,8 +296,7 @@ local function can_be_enabled(self) local actual_difficulty = Managers.state and Managers.state.difficulty:get_difficulty() local right_difficulty = not actual_difficulty or table.has_item(mutator_difficulties, actual_difficulty) - local ingame_ui = Managers.matchmaking and Managers.matchmaking.ingame_ui - local map_view = ingame_ui and ingame_ui.views and ingame_ui.views.map_view + local map_view = get_map_view() local map_view_active = map_view and map_view.active local right_unapplied_difficulty = false @@ -257,7 +333,7 @@ VMFMod.register_as_mutator = function(self, config) mutators_config[mod_name] = table.clone(default_config) local _config = mutators_config[mod_name] for k, _ in pairs(_config) do - if config[k] then + if config[k] ~= nil then _config[k] = config[k] end end @@ -291,16 +367,18 @@ end HOOKS ]]-- vmf:hook("DifficultyManager.set_difficulty", function(func, self, difficulty) - vmf.disable_impossible_mutators() + local disabled_mutators = vmf.disable_impossible_mutators() + if #disabled_mutators > 0 then + local message = "MUTATORS DISABLED DUE TO DIFFICULTY CHANGE:" + for _, mutator in ipairs(disabled_mutators) do + message = message .. " " .. mutator:get_config().title or mutator:get_name() + end + Managers.chat:send_system_chat_message(1, message, 0, true) + end return func(self, difficulty) end) ---[[ - GUI -]]-- -dofile("scripts/mods/vmf/modules/mutators/gui") - @@ -320,87 +398,36 @@ dofile("scripts/mods/vmf/modules/mutators/gui") --[[ Testing --]] -local mutation = new_mod("mutation") -local deathwish = new_mod("deathwish") +local mutator2 = new_mod("mutator2") local mutator3 = new_mod("mutator3") local mutator555 = new_mod("mutator555") -local mutator_whatever = new_mod("mutator_whatever") mutator555:register_as_mutator({ - enable_after_these = { - "mutation" - }, - title = "mutator555" + compatible_with_all = true, + incompatible_with = { + "mutator2" + } }) mutator555:create_options({}, true, "mutator555", "mutator555 description") mutator555.on_enabled = function() end mutator555.on_disabled = function() end -deathwish:register_as_mutator({ - enable_before_these = { - "mutator555", - "mutator3", - "mutation" - }, - difficulties = { - "hardest" - }, - title = "deathwish" -}) -deathwish:create_options({}, true, "deathwish", "deathwish description") -deathwish.on_enabled = function() - print(tostring(Breeds.skaven_gutter_runner == Breeds.skaven_pack_master)) -end -deathwish.on_disabled = function() end - - -------------------------------- -local breeds -mutation:register_as_mutator({ - enable_after_these = { - "deathwish" - }, - title = "mutation", - dice = { - grims = 5, - tomes = 1 - } -}) -mutation:create_options({}, true, "mutation", "mutation description") -mutation.on_enabled = function() - breeds = table.clone(Breeds) - Breeds.skaven_slave = Breeds.skaven_clan_rat - Breeds.skaven_clan_rat = Breeds.skaven_storm_vermin_commander - - Breeds.skaven_gutter_runner = Breeds.skaven_rat_ogre - Breeds.skaven_pack_master = Breeds.skaven_rat_ogre - Breeds.skaven_poison_wind_globadier = Breeds.skaven_rat_ogre - Breeds.skaven_ratling_gunner = Breeds.skaven_rat_ogre -end -mutation.on_disabled = function(initial) - if not initial then Breeds = breeds end -end -------------------------------- - mutator3:register_as_mutator({ - enable_before_these = { + compatible_with_all = true, + incompatible_with = { "mutator555" - }, - title = "mutator3", - dice = { - grims = 5, - tomes = 1, - bonus = 22 } }) mutator3:create_options({}, true, "mutator3", "mutator3 description") mutator3.on_enabled = function() end mutator3.on_disabled = function() end -mutator_whatever:register_as_mutator({ - title = "mutator_whatever" +mutator2:register_as_mutator({ + difficulties = { + "hardest" + } }) -mutator_whatever:create_options({}, true, "mutator_whatever", "mutator_whatever description") -mutator_whatever.on_enabled = function() end -mutator_whatever.on_disabled = function() end +mutator2:create_options({}, true, "mutator2", "mutator2 description") +mutator2.on_enabled = function() end +mutator2.on_disabled = function() end \ No newline at end of file