Skip to content

Commit

Permalink
*MASSIVE* update: shift_query 3.0
Browse files Browse the repository at this point in the history
Fixed improper range display in the settings window
Added force-update whenever any setting (except enable) is changed
Added support for colored output
Added rare material highlighting
Added configurable expansion of multi-material shifts
Added "flask resolving", which accurately lists past shifts
Added countdown timer to window title
Added sensible feedback if imgui isn't available
  • Loading branch information
Kaedenn committed Apr 8, 2024
1 parent ec3c75d commit bad825e
Show file tree
Hide file tree
Showing 13 changed files with 1,211 additions and 201 deletions.
2 changes: 1 addition & 1 deletion Makefile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,6 @@ fi

info "Detected differences between local and deployed directories"
if [[ "$ACTION" == "cp" ]]; then
info "Copying . to $DEST_DIR"

# Should we create a backup of the deployed directory?
if [[ -n "${BACKUP:-}" ]]; then
Expand All @@ -244,6 +243,7 @@ if [[ "$ACTION" == "cp" ]]; then
fi
fi

info "Copying . to $DEST_DIR"
# Deploy this mod to the destination directory
if dry checked rm -r "$DEST_DIR"; then
mkdir "$DEST_DIR" 2>/dev/null
Expand Down
Binary file added build/ui.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
89 changes: 48 additions & 41 deletions files/common.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,49 @@
-- When debugging is enabled and a shift uses a flask for either the
-- source or destination material, the other material should not have
-- the "(no flask)" designation, as it's redundant.
--
-- TODO:
--
-- Move the setting stuff into a class and allow stuff like
-- Config.previous_count.get()
-- Config.previous_count.set(num)
-- or something

dofile_once("data/scripts/lib/utilities.lua")
dofile_once("mods/shift_query/files/constants.lua")

MOD_ID = "shift_query"
K_CONFIG_LOG_ENABLE = MOD_ID .. "." .. "q_logging"
K_CONFIG_FORCE_UPDATE = MOD_ID .. "." .. "q_force_update"

-- Return either "Enable" or "Disable" based on the condition
--[[ Return either "Enable" or "Disable" based on the condition ]]
function f_enable(cond)
if cond then return "Enable" end
return "Disable"
end

-- Print a message to both the game and to the console
--[[ Trigger a force update ]]
function q_force_update()
GlobalsSetValue(K_CONFIG_FORCE_UPDATE, FLAG_ON)
end

--[[ Clear the force update flag ]]
function q_clear_force_update()
GlobalsSetValue(K_CONFIG_FORCE_UPDATE, FLAG_OFF)
end

--[[ True if an update is being forced ]]
function q_is_update_forced()
return GlobalsGetValue(K_CONFIG_FORCE_UPDATE, FLAG_OFF) ~= FLAG_OFF
end

--[[ Print a message to both the game and to the console ]]
function q_print(msg)
GamePrint(msg)
print(msg)
end

-- Format a "<nu> pending/previous shift(s)" message
--[[ Format a "<num> pending/previous shift(s)" message ]]
function f_shift_count(num, label)
local prefix = tostring(num)
local suffix = "shifts"
Expand All @@ -41,12 +64,12 @@ function f_shift_count(num, label)
return ("%s %s %s"):format(prefix, label, suffix)
end

-- Returns true if logging is enabled, false otherwise.
--[[ Returns true if logging is enabled, false otherwise. ]]
function q_logging()
return GlobalsGetValue(K_CONFIG_LOG_ENABLE, FLAG_OFF) ~= FLAG_OFF
end

-- Enable or disable logging
--[[ Enable or disable logging ]]
function q_set_logging(enable)
if enable then
GlobalsSetValue(K_CONFIG_LOG_ENABLE, FLAG_ON)
Expand All @@ -55,16 +78,17 @@ function q_set_logging(enable)
q_log("Disabling debugging")
GlobalsSetValue(K_CONFIG_LOG_ENABLE, FLAG_OFF)
end
q_force_update()
end

-- Display a logging message if logging is enabled.
--[[ Display a logging message if logging is enabled. ]]
function q_log(msg)
if q_logging() then
q_print("DEBUG: " .. msg)
end
end

-- Display a formatted logging message if logging is enabled.
--[[ Display a formatted logging message if logging is enabled. ]]
function q_logf(msg, ...)
if q_logging() then
q_log(msg:format(...))
Expand All @@ -80,6 +104,8 @@ end
-- The cache allows for these values to appear instantly. Cache entries
-- are stored when setting a value and cleared once that value is
-- properly stored.
--
-- FIXME: Just use ModSettingGetNextValue; this is unnecessary
--]]
local config_cache = {}

Expand Down Expand Up @@ -107,6 +133,9 @@ function q_setting_set(setting, value)
new_value = value
}
ModSettingSetNextValue(MOD_ID .. "." .. setting, value, false)
if old_value ~= value then
q_force_update()
end
end

-- Get the "enable gui?" setting's value
Expand All @@ -123,36 +152,14 @@ function q_disable_gui()
q_setting_set(SETTING_ENABLE, false)
end

-- Clear the logging global if set
function logger_clear()
local value = GlobalsGetValue("shift_query.logging") or ""
if value ~= "" then
GlobalsSetValue("shift_query.logging", "")
end
end

-- Add a component to the logging global
function logger_add(piece)
local old_log = GlobalsGetValue("shift_query.logging") or ""
local new_log = tostring(piece)
if old_log ~= "" then
new_log = old_log .. "\n" .. new_log
end
GlobalsSetValue("shift_query.logging", new_log)
end

-- Localize a material, either "name" or "$mat_name".
function localize_material(material)
local matid = CellFactory_GetType(material)
local mname = material
if matid ~= -1 then
mname = CellFactory_GetUIName(matid)
end
local name = GameTextGetTranslatedOrNot(mname)
if not name then -- handle nil
return ""
end
return name
return GameTextGetTranslatedOrNot(mname) or ""
end

-- Localize a material based on the mode argument
Expand All @@ -177,13 +184,13 @@ function localize_material_via(material, loc_mode)
return ("[%s]"):format(material)
end

-- Possibly localize a material based on q_logging, localize setting
--[[ Possibly localize a material based on q_logging, localize setting ]]
function maybe_localize_material(material)
local loc_mode = q_setting_get(SETTING_LOCALIZE)
return localize_material_via(material, loc_mode)
end

-- Format a material with the possibility of including a flask.
--[[ Format a material with the possibility of including a flask. ]]
function flask_or(material, use_flask)
local logging = q_logging()
local mname = maybe_localize_material(material)
Expand All @@ -196,7 +203,7 @@ function flask_or(material, use_flask)
return mname
end

-- Format a fungal shift. Returns a table of pairs of strings.
--[[ Format a fungal shift. Returns a table of pairs of strings. ]]
function format_shift(shift)
if not shift then return {{"invalid shift", "invalid shift"}} end
local source = shift.from
Expand All @@ -210,23 +217,23 @@ function format_shift(shift)
if not target then
s_target = "no data"
end
return {s_source, s_target}
return {{s_source, s_target}}
end
local s_target = flask_or(target.material, target.flask)
local material_pairs = {}
if source.name_material then
local want_expand = q_setting_get(SETTING_EXPAND)
if want_expand == EXPAND_ONE and source.name_material then
local s_source = flask_or(source.name_material, source.flask)
table.insert(material_pairs, {s_source, s_target})
else
for index, material in ipairs(source.materials) do
local s_source = flask_or(material, source.flask)
table.insert(material_pairs, {s_source, s_target})
end
local s_source = table.concat(source.materials, ", ")
s_source = flask_or(s_source, source.flask)
table.insert(material_pairs, {s_source, s_target})
end
return material_pairs
end

-- Format a number relative to its current value
--[[ Format a number relative to its current value ]]
function format_relative(curr, index)
local term = "invalid"
if index == curr then
Expand All @@ -244,7 +251,7 @@ function format_relative(curr, index)
return term
end

-- Format a duration of time
--[[ Format a duration of time ]]
function format_duration(nsecs)
local total = math.abs(nsecs)
local hours = math.floor(total / 60 / 60)
Expand Down
10 changes: 10 additions & 0 deletions files/constants.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ MAX_SHIFTS = 20 -- the game implicitly supports only 20 shifts

ALL_SHIFTS = -1 -- values < 0 mean "all"

CUTOFF_RARE = 0.2 -- shifts with this probability or lower are "rare"

FLAG_ON = "1"
FLAG_OFF = "0"

Expand All @@ -15,16 +17,24 @@ SETTING_PREVIOUS = "previous_count"
SETTING_NEXT = "next_count"
SETTING_LOCALIZE = "localize"
SETTING_ENABLE = "enable"
SETTING_EXPAND = "expand_from"
SETTING_APLC = "include_aplc"
SETTING_REAL = "flask_real"

CONF_PREVIOUS = ("%s.%s"):format(MOD_ID, SETTING_PREVIOUS)
CONF_NEXT = ("%s.%s"):format(MOD_ID, SETTING_NEXT)
CONF_LOCALIZE = ("%s.%s"):format(MOD_ID, SETTING_LOCALIZE)
CONF_ENABLE = ("%s.%s"):format(MOD_ID, SETTING_ENABLE)
CONF_EXPAND = ("%s.%s"):format(MOD_ID, SETTING_EXPAND)
CONF_APLC = ("%s.%s"):format(MOD_ID, SETTING_APLC)
CONF_REAL = ("%s.%s"):format(MOD_ID, SETTING_REAL)

--[[ Material formatting rules ]]
FORMAT_INTERNAL = "internal"
FORMAT_LOCALE = "locale"
FORMAT_BOTH = "both"

--[[ Source material expansion rules ]]
EXPAND_ONE = "one"
EXPAND_ALL = "all"

74 changes: 59 additions & 15 deletions files/materials.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
-- Fungal Query materials

-- The following appears to crash Noita (Dec 21, release)
--dofile("data/scripts/magic/fungal_shift.lua")
--[[ NOTE:
-- While it would be easy just to have
dofile("data/scripts/magic/fungal_shift.lua")
-- and expose those values here; that script (as of Feb 14 2024) crashes Noita
-- if executed during mod initialization. This is because the script attempts
-- to validate the material tables via the CellFactory (CellFactory_GetType)
-- the instant the script is executed. The CellFactory is not initialized by
-- this point and thus the game crashes.
--
-- To work around this, this file provides two solutions:
-- 1. Load data/scripts/magic/fungal_shift.lua only when requested, and
-- 2. Provide hard-coded material tables if the native ones are unavailable.
--]]

-- The tables below are taken directly from Noita's own fungal_shift.lua
-- script, with some formatting for good measure. Note that changes to
Expand Down Expand Up @@ -90,33 +101,66 @@ MATERIALS_TO_COPY = {
{ probability = 0.01, material = "cheese_static" },
}

function get_material_tables()
dofile("data/scripts/magic/fungal_shift.lua")
if materials_from and materials_to then
return materials_from, materials_to
end
GamePrint("shift_query - unable to get material tables; using local versions")
return MATERIALS_FROM_COPY, MATERIALS_TO_COPY
end

return {
--[[ Obtain the materials_from table.
-- This first attempts to determine the table directly from Noita, and then
-- falls back to the table defined above.
--]]
get_materials_from = function()
dofile("data/scripts/magic/fungal_shift.lua")
-- luacheck: globals materials_from materials_to
if materials_from and materials_to then
return materials_from
end
GamePrint("shift_query - unable to get source material table; using local copy")
return MATERIALS_FROM_COPY
local materials_from, materials_to = get_material_tables()
return materials_from
end,

--[[ Obtain the materials_to table.
-- This first attempts to determine the table directly from Noita, and then
-- falls back to the table defined above.
--]]
get_materials_to = function()
dofile("data/scripts/magic/fungal_shift.lua")
-- luacheck: globals materials_from materials_to
if materials_from and materials_to then
return materials_to
local materials_from, materials_to = get_material_tables()
return materials_to
end,

--[[ True if the given shift source is considered "rare" ]]
is_rare_source = function(material, cutoff)
if type(cutoff) ~= "number" then
cutoff = 0.2
end
local materials_from, materials_to = get_material_tables()
for _, entry in ipairs(materials_from) do
if entry.probability <= cutoff then
for _, shift_mat in ipairs(entry.materials) do
if shift_mat == material then
return true
end
end
end
end
return false
end,

--[[ True if the given shift destination is considered "rare" ]]
is_rare_target = function(material, cutoff)
if type(cutoff) ~= "number" then
cutoff = 0.2
end
local materials_from, materials_to = get_material_tables()
for _, entry in ipairs(materials_to) do
if entry.probability <= cutoff then
if entry.material == material then
return true
end
end
end
GamePrint("shift_query - unable to get source material table; using local copy")
return MATERIALS_TO_COPY
return false
end,

--[[ Material tables ]]
Expand Down
Loading

0 comments on commit bad825e

Please sign in to comment.