mutators: comments

This commit is contained in:
UnShame 2018-02-19 22:34:28 +03:00
parent 4d5a0e64e2
commit ec95192907

View file

@ -1,14 +1,34 @@
local vmf = get_mod("VMF") 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 = {}
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 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 if not mutators_sequence[mutator_name] then
mutators_sequence[mutator_name] = {} mutators_sequence[mutator_name] = {}
end 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 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.") 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
end end
table.combine(mutators_sequence[mutator_name], load_these_after) table.combine(mutators_sequence[mutator_name], enable_these_after)
end end
-- This shouldn't happen
local function error_endless_loop() local function error_endless_loop()
vmf:error("Mutators: too many iterations. Check for loops in 'enable_before_these'/'enable_after_these'.") vmf:error("Mutators: too many iterations. Check for loops in 'enable_before_these'/'enable_after_these'.")
end end
-- Sorts mutators in order they should be enabled
local function sort_mutators() local function sort_mutators()
-- LOG --
vmf:dump(mutators_sequence, "seq", 5) vmf:dump(mutators_sequence, "seq", 5)
for i, v in ipairs(mutators) do for i, v in ipairs(mutators) do
print(i, v:get_name()) print(i, v:get_name())
end end
print("-----------") 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 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 local i = 2
while i <= #mutators do while i <= #mutators do
local mutator = mutators[i] local mutator = mutators[i]
local mutator_name = mutator:get_name() 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 local j = i - 1
while j > 0 do while j > 0 do
local other_mutator = mutators[j] 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.remove(mutators, j)
table.insert(mutators, i, other_mutator) table.insert(mutators, i, other_mutator)
-- This will shift the current mutator back, so adjust the index
i = i - 1 i = i - 1
end end
j = j - 1 j = j - 1
@ -62,29 +94,37 @@ local function sort_mutators()
end end
mutators_sorted = true mutators_sorted = true
-- LOG --
for i, v in ipairs(mutators) do for i, v in ipairs(mutators) do
print(i, v:get_name()) print(i, v:get_name())
end end
print("-----------") print("-----------")
-- /LOG --
end end
-- Enables/disables mutator while preserving the sequence in which they were enabled
local function set_mutator_state(self, state) local function set_mutator_state(self, state)
local i = table.index_of(mutators, self) local i = table.index_of(mutators, self)
if i == nil then if i == nil then
self:error("Mutator isn't in the list") self:error("Mutator isn't in the list")
return return
end end
-- Sort mutators if this is the first call
if not mutators_sorted then if not mutators_sorted then
sort_mutators() sort_mutators()
end end
local disabled_mutators = {} 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 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()) print("Disabled ", mutators[j]:get_name())
mutators[j]:disable() mutators[j]:disable()
table.insert(disabled_mutators, 1, mutators[j]) table.insert(disabled_mutators, 1, mutators[j])
@ -92,6 +132,7 @@ local function set_mutator_state(self, state)
end end
end end
-- Enable/disable current mutator
if state then if state then
print("Enabled ", self:get_name(), "!") print("Enabled ", self:get_name(), "!")
VMFMod.enable(self) VMFMod.enable(self)
@ -100,6 +141,8 @@ local function set_mutator_state(self, state)
VMFMod.disable(self) VMFMod.disable(self)
end end
-- Re-enable disabled mutators
-- This will be recursive
if #disabled_mutators > 0 then if #disabled_mutators > 0 then
for j = #disabled_mutators, 1, -1 do for j = #disabled_mutators, 1, -1 do
print("Enabled ", disabled_mutators[j]:get_name()) print("Enabled ", disabled_mutators[j]:get_name())
@ -109,14 +152,23 @@ local function set_mutator_state(self, state)
print("---------") print("---------")
end end
-- Enables mutator (pcall for now)
local function enable_mutator(self) local function enable_mutator(self)
vmf:pcall(function() set_mutator_state(self, true) end) vmf:pcall(function() set_mutator_state(self, true) end)
end end
-- Disables mutator (pcall for now)
local function disable_mutator(self) local function disable_mutator(self)
vmf:pcall(function() set_mutator_state(self, false) end) vmf:pcall(function() set_mutator_state(self, false) end)
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) VMFMod.register_as_mutator = function(self, config)
if not config then config = {} end if not config then config = {} end
@ -148,7 +200,10 @@ VMFMod.register_as_mutator = function(self, config)
self:init_state(false) self:init_state(false)
end end
-- Testing
--[[
Testing
--]]
local mutation = new_mod("mutation") local mutation = new_mod("mutation")
local deathwish = new_mod("deathwish") local deathwish = new_mod("deathwish")
local mutator3 = new_mod("mutator3") local mutator3 = new_mod("mutator3")
@ -166,9 +221,6 @@ mutator555.on_disabled = function() end
deathwish:register_as_mutator({ deathwish:register_as_mutator({
enable_after_these = {
"mutation"
},
enable_before_these = { enable_before_these = {
"mutator555", "mutator555",
"mutator3", "mutator3",