diff --git a/vmf_source/resource_packages/vmf.package b/vmf_source/resource_packages/vmf.package index 88810b0..bee278a 100644 --- a/vmf_source/resource_packages/vmf.package +++ b/vmf_source/resource_packages/vmf.package @@ -20,4 +20,5 @@ lua = [ "scripts/mods/vmf/modules/debug/*" "scripts/mods/vmf/modules/gui/*" "scripts/mods/vmf/modules/options_menu/*" + "scripts/mods/vmf/modules/mutators/*" ] \ No newline at end of file diff --git a/vmf_source/scripts/mods/vmf/modules/mutators/default_config.lua b/vmf_source/scripts/mods/vmf/modules/mutators/default_config.lua new file mode 100644 index 0000000..6f07938 --- /dev/null +++ b/vmf_source/scripts/mods/vmf/modules/mutators/default_config.lua @@ -0,0 +1,21 @@ +return { + dice = { + grims = 0, + tomes = 0, + bonus = 0 + }, + server_name = "", + title = "default_title", + --short_title = "", + difficulties = { + "easy", + "normal", + "hard", + "harder", + "hardest", + + "survival_hard", + "survival_harder", + "survival_hardest" + } +} diff --git a/vmf_source/scripts/mods/vmf/modules/mutators/dice.lua b/vmf_source/scripts/mods/vmf/modules/mutators/dice.lua new file mode 100644 index 0000000..ebda96e --- /dev/null +++ b/vmf_source/scripts/mods/vmf/modules/mutators/dice.lua @@ -0,0 +1,66 @@ +local vmf = get_mod("VMF") + +local missions = { + "bonus_dice_hidden_mission", + "tome_bonus_mission", + "grimoire_hidden_mission" +} + +local num_dice_per_mission = { + bonus_dice_hidden_mission = 0, + tome_bonus_mission = 0, + grimoire_hidden_mission = 0 +} + +vmf:hook("GameModeManager.complete_level", function(func, self) + local num_dice = 0 + local max_dice = 7 + local mission_system = Managers.state.entity:system("mission_system") + local active_mission = mission_system.active_missions + + for _, mission in ipairs(missions) do + for _ = 1, num_dice_per_mission[mission] do + mission_system:request_mission(mission, nil, Network.peer_id()) + mission_system:update_mission(mission, true, nil, Network.peer_id(), nil, true) + end + end + + for name, obj in pairs(active_mission) do + if table.has_item(missions, name) then + num_dice = num_dice + obj.current_amount + end + end + + for _, mission in ipairs(missions) do + if active_mission[mission] then + for _ = 1, active_mission[mission].current_amount do + if num_dice > max_dice then + mission_system:request_mission(mission, nil, Network.peer_id()) + mission_system:update_mission(mission, false, nil, Network.peer_id(), nil, true) + num_dice = num_dice - 1 + else break end + end + end + if num_dice <= max_dice then break end + end + + return func(self) +end) + +local function adjustDice(grims, tomes, bonus, multiplier) + if grims then num_dice_per_mission.grimoire_hidden_mission = num_dice_per_mission.grimoire_hidden_mission + grims * multiplier end + if tomes then num_dice_per_mission.tome_bonus_mission = num_dice_per_mission.tome_bonus_mission + tomes * multiplier end + if bonus then num_dice_per_mission.bonus_dice_hidden_mission = num_dice_per_mission.bonus_dice_hidden_mission + bonus * multiplier end +end + +local addDice = function(dice) + dice = dice or {} + adjustDice(dice.grims, dice.tomes, dice.bonus, 1) +end + +local removeDice = function(dice) + dice = dice or {} + adjustDice(dice.grims, dice.tomes, dice.bonus, -1) +end + +return addDice, removeDice diff --git a/vmf_source/scripts/mods/vmf/modules/mutators/info.lua b/vmf_source/scripts/mods/vmf/modules/mutators/info.lua new file mode 100644 index 0000000..77c657d --- /dev/null +++ b/vmf_source/scripts/mods/vmf/modules/mutators/info.lua @@ -0,0 +1,79 @@ +local vmf = get_mod("VMF") +local mutators = vmf.mutators + +local function get_enabled_mutators_names(short) + local name = "" + for _, mutator in ipairs(mutators) do + local config = mutator:get_config() + if mutator:is_enabled() then + name = name .. " " .. (short and config.short_title or config.title) + end + end + return name +end + +local function set_lobby_data() + + if not Managers.matchmaking then return end + + local name = get_enabled_mutators_names(true) + + local default_name = LobbyAux.get_unique_server_name() + if name then + name = "||" .. name .. "|| " .. default_name + else + name = default_name + end + + local lobby_data = Managers.matchmaking.lobby:get_stored_lobby_data() + lobby_data.unique_server_name = name + + Managers.matchmaking.lobby:set_lobby_data(lobby_data) +end + +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,"-")))) + end + peer_id = string.sub(peer_id, 2) + peer_id = string.reverse(peer_id) + peer_id = string.sub(peer_id, 2) + peer_id = string.reverse(peer_id) + + return function() + for _, v in ipairs(Managers.matchmaking.lobby:members():get_members()) do + if v == peer_id then + return {v} + end + end + return Managers.matchmaking.lobby:members():get_members() + end +end + + +vmf:hook("IngamePlayerListUI.set_difficulty_name", function(func, self, name) + local mutators_name = get_enabled_mutators_names(true) + if mutators_name then + name = name .. " " .. mutators_name + end + self.headers.content.game_difficulty = name +end) + +vmf:hook("MatchmakingStateHostGame.host_game", function(func, self, ...) + func(self, ...) + set_lobby_data() +end) + +vmf:hook("MatchmakingManager.rpc_matchmaking_request_join_lobby", function(func, self, sender, client_cookie, host_cookie, lobby_id, friend_join) + local name = get_enabled_mutators_names(false) + if name then + local message = "[Automated message] This lobby has the following difficulty mod active : " .. name + vmf:hook("Managers.chat.channels[1].members_func", get_member_func(client_cookie)) + Managers.chat:send_system_chat_message(1, message, 0, true) + vmf:hook_remove("Managers.chat.channels[1].members_func") + end + func(self, sender, client_cookie, host_cookie, lobby_id, friend_join) +end) + +return set_lobby_data \ No newline at end of file diff --git a/vmf_source/scripts/mods/vmf/modules/mutators/mutators.lua b/vmf_source/scripts/mods/vmf/modules/mutators/mutators.lua index a981424..e0ad34a 100644 --- a/vmf_source/scripts/mods/vmf/modules/mutators/mutators.lua +++ b/vmf_source/scripts/mods/vmf/modules/mutators/mutators.lua @@ -1,8 +1,13 @@ local vmf = get_mod("VMF") + -- List of mods that are also mutators in order in which they should be enabled -- This is populated via VMFMod.register_as_mutator local mutators = {} +vmf.mutators = mutators + +local mutators_config = {} +local default_config = dofile("scripts/mods/vmf/modules/mutators/default_config") -- This lists mutators and which ones should be enabled after them -- This is populated via VMFMod.register_as_mutator @@ -23,6 +28,9 @@ local mutators_sorted = false PRIVATE METHODS ]]-- +local addDice, removeDice = dofile("scripts/mods/vmf/modules/mutators/dice") +local set_lobby_data = dofile("scripts/mods/vmf/modules/mutators/info") + -- Adds mutator names from enable_these_after to the list of mutators that should be enabled after the mutator_name local function update_mutators_sequence(mutator_name, enable_these_after) if not mutators_sequence[mutator_name] then @@ -82,7 +90,7 @@ local function sort_mutators() i = i + 1 numIter = numIter + 1 - if numIter > maxIter then + if numIter > maxIter then vmf:error("Mutators: too many iterations. Check for loops in 'enable_before_these'/'enable_after_these'.") return end @@ -97,12 +105,33 @@ local function sort_mutators() -- /LOG -- end --- Enables/disables mutator while preserving the sequence in which they were enabled -local function set_mutator_state(self, state) +local function mutator_can_be_enabled(mutator) + return (not Managers.state or not Managers.state.difficulty:get_difficulty()) or table.has_item(mutator:get_config().difficulties, Managers.state.difficulty:get_difficulty()) +end - local i = table.index_of(mutators, self) +local function on_enabled(mutator) + local config = mutator:get_config() + addDice(config.dice) + set_lobby_data() +end + +local function on_disabled(mutator) + local config = mutator:get_config() + removeDice(config.dice) + set_lobby_data() +end + +-- Enables/disables mutator while preserving the sequence in which they were enabled +local function set_mutator_state(mutator, state) + + local i = table.index_of(mutators, mutator) if i == nil then - self:error("Mutator isn't in the list") + mutator:error("Mutator isn't in the list") + return + end + + if state and not mutator_can_be_enabled(mutator) then + mutator:error("Can't enable mutator - incorrect difficulty") return end @@ -112,7 +141,7 @@ local function set_mutator_state(self, state) end local disabled_mutators = {} - local enable_these_after = mutators_sequence[self:get_name()] + local enable_these_after = mutators_sequence[mutator:get_name()] -- Disable mutators that were and are required to be enabled after the current one -- This will be recursive so that if mutator2 requires mutator3 to be enabled after it, mutator3 will be disabled before mutator2 @@ -130,11 +159,13 @@ local function set_mutator_state(self, state) -- Enable/disable current mutator -- We're calling methods on the class object because we've overwritten them on the current one if state then - print("Enabled ", self:get_name(), "!") - VMFMod.enable(self) + print("Enabled ", mutator:get_name(), "!") + VMFMod.enable(mutator) + on_enabled(mutator) else - print("Disabled ", self:get_name(), "!") - VMFMod.disable(self) + print("Disabled ", mutator:get_name(), "!") + VMFMod.disable(mutator) + on_disabled(mutator) end -- Re-enable disabled mutators @@ -158,13 +189,16 @@ local function disable_mutator(self) vmf:pcall(function() set_mutator_state(self, false) end) end +local function get_config(self) + return mutators_config[self:get_name()] +end + --[[ PUBLIC METHODS ]]-- -- Turns a mod into a mutator --- For now all it does is creates a sequence in which they need to be enabled/disabled VMFMod.register_as_mutator = function(self, config) if not config then config = {} end @@ -177,6 +211,16 @@ VMFMod.register_as_mutator = function(self, config) table.insert(mutators, self) + -- Save 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 + _config[k] = config[k] + end + end + if _config.short_title == "" then _config.short_title = nil end + if config.enable_before_these then update_mutators_sequence(mod_name, config.enable_before_these) end @@ -190,12 +234,42 @@ VMFMod.register_as_mutator = function(self, config) self.enable = enable_mutator self.disable = disable_mutator + self.get_config = get_config + mutators_sorted = false -- Always init in the off state self:init_state(false) end +--[[ + HOOKS +]]-- +vmf:hook("DifficultyManager.set_difficulty", function(func, self, difficulty) + for _, mutator in ipairs(mutators) do + if mutator:is_enabled() and not mutator_can_be_enabled(mutator:get_config()) then + mutator:disable() + end + end + return func(self, difficulty) +end) + + + + + + + + + + + + + + + + + --[[ Testing @@ -221,10 +295,13 @@ deathwish:register_as_mutator({ "mutator555", "mutator3", "mutation" + }, + difficulties = { + "hardest" } }) deathwish:create_options({}, true, "deathwish", "deathwish description") -deathwish.on_enabled = function() +deathwish.on_enabled = function() print(tostring(Breeds.skaven_gutter_runner == Breeds.skaven_pack_master)) end deathwish.on_disabled = function() end diff --git a/vmf_source/scripts/mods/vmf/vmf_loader.lua b/vmf_source/scripts/mods/vmf/vmf_loader.lua index 80e33c2..d5e393c 100644 --- a/vmf_source/scripts/mods/vmf/vmf_loader.lua +++ b/vmf_source/scripts/mods/vmf/vmf_loader.lua @@ -21,7 +21,7 @@ return { dofile("scripts/mods/vmf/modules/options_menu/vmf_options_view") dofile("scripts/mods/vmf/modules/vmf_options") - dofile("scripts/mods/vmf/modules/mutators") + dofile("scripts/mods/vmf/modules/mutators/mutators") object.vmf = get_mod("VMF")