From ec95192907034115d6114e1e1ba5e5f7b9c3d9db Mon Sep 17 00:00:00 2001 From: UnShame Date: Mon, 19 Feb 2018 22:34:28 +0300 Subject: [PATCH] mutators: comments --- .../scripts/mods/vmf/modules/mutators.lua | 80 +++++++++++++++---- 1 file changed, 66 insertions(+), 14 deletions(-) diff --git a/vmf_source/scripts/mods/vmf/modules/mutators.lua b/vmf_source/scripts/mods/vmf/modules/mutators.lua index 8f2e719..d5f1d73 100644 --- a/vmf_source/scripts/mods/vmf/modules/mutators.lua +++ b/vmf_source/scripts/mods/vmf/modules/mutators.lua @@ -1,14 +1,34 @@ 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 = {} -local mutators_sequence = {} + +-- This lists mutators and which ones should be enabled after them +-- This is populated via VMFMod.register_as_mutator +local mutators_sequence = { + --[[ + this_mutator = { + "will be enabled", + "before these ones" + } + ]]-- +} + +-- So we don't sort after each one is added local mutators_sorted = false -local function update_mutators_sequence(mutator_name, load_these_after) + +--[[ + PRIVATE METHODS +]]-- + +-- 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 mutators_sequence[mutator_name] = {} end - for _, other_mutator_name in ipairs(load_these_after) do + for _, other_mutator_name in ipairs(enable_these_after) do if mutators_sequence[other_mutator_name] and table.has_item(mutators_sequence[other_mutator_name], mutator_name) then vmf:error("Mutators '" .. mutator_name .. "' and '" .. other_mutator_name .. "' are both set to load after the other one.") @@ -17,36 +37,48 @@ local function update_mutators_sequence(mutator_name, load_these_after) end end - table.combine(mutators_sequence[mutator_name], load_these_after) + table.combine(mutators_sequence[mutator_name], enable_these_after) end +-- This shouldn't happen local function error_endless_loop() vmf:error("Mutators: too many iterations. Check for loops in 'enable_before_these'/'enable_after_these'.") end +-- Sorts mutators in order they should be enabled local function sort_mutators() + -- LOG -- vmf:dump(mutators_sequence, "seq", 5) for i, v in ipairs(mutators) do print(i, v:get_name()) end print("-----------") + -- /LOG -- - local maxIter = #mutators * #mutators * #mutators + -- Preventing endless loops (worst case is n*n*(n+1)/2 I believe) + local maxIter = #mutators * #mutators * (#mutators + 1)/2 local numIter = 0 + -- The idea is that all mutators before the current one are already in the right order + -- Starting from second mutator local i = 2 while i <= #mutators do local mutator = mutators[i] local mutator_name = mutator:get_name() - local load_these_after = mutators_sequence[mutator_name] or {} + local enable_these_after = mutators_sequence[mutator_name] or {} + -- Going back from the previous mutator local j = i - 1 while j > 0 do local other_mutator = mutators[j] - if table.has_item(load_these_after, other_mutator:get_name()) then + + -- Moving it after the current one if it is to be enabled after it + if table.has_item(enable_these_after, other_mutator:get_name()) then table.remove(mutators, j) table.insert(mutators, i, other_mutator) + + -- This will shift the current mutator back, so adjust the index i = i - 1 end j = j - 1 @@ -62,29 +94,37 @@ local function sort_mutators() end mutators_sorted = true + -- LOG -- for i, v in ipairs(mutators) do print(i, v:get_name()) end print("-----------") + -- /LOG -- end +-- Enables/disables mutator while preserving the sequence in which they were enabled local function set_mutator_state(self, state) + local i = table.index_of(mutators, self) if i == nil then self:error("Mutator isn't in the list") return end + -- Sort mutators if this is the first call if not mutators_sorted then sort_mutators() end local disabled_mutators = {} - local load_these_after = mutators_sequence[self:get_name()] + local enable_these_after = mutators_sequence[self:get_name()] - if load_these_after and #mutators > i then + -- 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 + -- Yeah this is super confusing + if enable_these_after and #mutators > i then for j = #mutators, i + 1, -1 do - if mutators[j]:is_enabled() and table.has_item(load_these_after, mutators[j]:get_name()) then + if mutators[j]:is_enabled() and table.has_item(enable_these_after, mutators[j]:get_name()) then print("Disabled ", mutators[j]:get_name()) mutators[j]:disable() table.insert(disabled_mutators, 1, mutators[j]) @@ -92,6 +132,7 @@ local function set_mutator_state(self, state) end end + -- Enable/disable current mutator if state then print("Enabled ", self:get_name(), "!") VMFMod.enable(self) @@ -100,6 +141,8 @@ local function set_mutator_state(self, state) VMFMod.disable(self) end + -- Re-enable disabled mutators + -- This will be recursive if #disabled_mutators > 0 then for j = #disabled_mutators, 1, -1 do print("Enabled ", disabled_mutators[j]:get_name()) @@ -109,14 +152,23 @@ local function set_mutator_state(self, state) print("---------") end +-- Enables mutator (pcall for now) local function enable_mutator(self) vmf:pcall(function() set_mutator_state(self, true) end) end +-- Disables mutator (pcall for now) local function disable_mutator(self) vmf:pcall(function() set_mutator_state(self, false) end) 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 @@ -148,7 +200,10 @@ VMFMod.register_as_mutator = function(self, config) self:init_state(false) end --- Testing + +--[[ + Testing +--]] local mutation = new_mod("mutation") local deathwish = new_mod("deathwish") local mutator3 = new_mod("mutator3") @@ -166,9 +221,6 @@ mutator555.on_disabled = function() end deathwish:register_as_mutator({ - enable_after_these = { - "mutation" - }, enable_before_these = { "mutator555", "mutator3",