From a7e289cb0d7109778e6439d233abe901af0ccbd3 Mon Sep 17 00:00:00 2001 From: brmley Date: Thu, 15 May 2025 17:44:12 +0300 Subject: [PATCH] init research info --- gui/spectate.lua | 1 + internal/research-info/info.lua | 126 +++++++++++++++++++++++++++++ internal/research-info/overlay.lua | 43 ++++++++++ research-info.lua | 69 ++++++++++++++++ 4 files changed, 239 insertions(+) create mode 100644 internal/research-info/info.lua create mode 100644 internal/research-info/overlay.lua create mode 100644 research-info.lua diff --git a/gui/spectate.lua b/gui/spectate.lua index 558e281b5..c4131b383 100644 --- a/gui/spectate.lua +++ b/gui/spectate.lua @@ -244,6 +244,7 @@ function Spectate:init() create_row({t=27}, 'Job', 'J', 'job', colFollow, colHover), create_row({t=28}, 'Activity', 'A', 'activity', colFollow, colHover), + create_row({t=27}, 'Research', 'R', 'research', colFollow, colHover), create_row({t=29}, 'Name', 'N', 'name', colFollow, colHover), create_row({t=30}, 'Stress', 'S', 'stress', colFollow, colHover), create_stress_list({t=31}, colFollow, colHover), diff --git a/internal/research-info/info.lua b/internal/research-info/info.lua new file mode 100644 index 000000000..5bb6e0f60 --- /dev/null +++ b/internal/research-info/info.lua @@ -0,0 +1,126 @@ +-- Main module for research-info +--@ module = true + +---@param unit_id df.unit.id +function getHistoricalFigure(unit_id) + for _, historical_figure in ipairs(df.global.world.history.figures) do + if historical_figure.unit_id == unit_id then + return historical_figure + end + end + print("No historical figure found for unit ID: " .. unit_id) + return nil +end + +function getKnowledgeGoalCategoryInfo(category_id) + -- alt: df.scholar_knowledgest + local topic_categories = { + [-1] = "None", -- None + [0] = "Philosophy", -- PHILOSOPHY_FLAG + [1] = "Philosophy Adv", -- PHILOSOPHY_FLAG2 + [2] = "Mathematics", -- MATHEMATICS_FLAG + [3] = "Mathematics Adv", -- MATHEMATICS_FLAG2 + [4] = "History", -- HISTORY_FLAG + [5] = "Astronomy", -- ASTRONOMY_FLAG + [6] = "Naturalist", -- NATURALIST_FLAG + [7] = "Chemistry", -- CHEMISTRY_FLAG + [8] = "Geography", -- GEOGRAPHY_FLAG + [9] = "Medicine 1", -- MEDICINE_FLAG + [10] = "Medicine 2", -- MEDICINE_FLAG2 + [11] = "Medicine 3", -- MEDICINE_FLAG3 + [12] = "Engineering", -- ENGINEERING_FLAG + [13] = "Engineering Adv" -- ENGINEERING_FLAG2 + } + return topic_categories[category_id] or string.format("Unknown Category: %s", category_id) +end + +function getGoalInfo(goal, category) + local goal_info = '' + if not goal then + return goal_info + end + + local goal_info = "" + for i = 0, 31 do + if goal[i] then + local global_flag_index = category * 32 + i -- wizards move + goal_info = string.format("%s", df.dfhack_knowledge_scholar_flag[global_flag_index]) or string.format("Unknown Flag: %s", i) + end + end + return goal_info +end + +local function getTopicInfo(topic) + if not topic then + return "No topic information available." + end + + local topic_info = "" + + for key, value in pairs(topic) do + if type(value) == "boolean" and value then + -- Если значение булевое и равно true, выводим тему как изученную + topic_info = topic_info .. string.format("\n\t\t%s", key) + end + end + + if topic_info == "" then + return "No learned topics." + end + + return topic_info +end + +---@param historical_figure df.historical_figure +function getHistoricKnowledge(historical_figure) + if not historical_figure then + print("Historical figure not found.") + return nil, "Historical figure not found." + end + + local known_info = historical_figure.info.known_info + + if not known_info then + return nil, "No known_info found." + end + + local knowledge = known_info.knowledge + + if not knowledge then + return nil, "No knowledge found." + end + + return knowledge +end + +---@param unit_id df.unit.id +function getUnitKnowledge(unit_id) + return getHistoricKnowledge(getHistoricalFigure(unit_id)) +end + +---@param historical_figure df.historical_figure +function getResearchData(historical_figure) + local knowledge = getHistoricKnowledge(historical_figure) + local data = { + + name = dfhack.translation.translateName(historical_figure.name), --dfhack.translation.TranslateName(historical_figure.name), + knowledge_goal_category = getKnowledgeGoalCategoryInfo(knowledge.knowledge_goal_category), + --knowledge_goal = getGoalInfo(knowledge.knowledge_goal), + knowledge_goal = getGoalInfo(knowledge.knowledge_goal, knowledge.knowledge_goal_category), + research_points = knowledge.research_points, + research_percentage = string.format("%.2f", (knowledge.research_points / 100000) * 100), + times_pondered = knowledge.times_pondered, + research_topics = {} + } + + for i, topic in pairs(knowledge) do + if type(topic) == "userdata" and i ~= "knowledge_goal" then + local topic_info = getTopicInfo(topic) + if topic_info ~= "\tNo topic information available." and topic_info ~= "No learned topics." then + table.insert(data.research_topics, {name = i, info = topic_info}) + end + end + end + + return {data} +end diff --git a/internal/research-info/overlay.lua b/internal/research-info/overlay.lua new file mode 100644 index 000000000..dd6e5d54d --- /dev/null +++ b/internal/research-info/overlay.lua @@ -0,0 +1,43 @@ +-- Spectate-Overlay module for research-info +--@ module = true + +local researchInfo = reqscript("internal/research-info/info") + +local function formatKnowledgeString(str) + if not str or type(str) ~= "string" or str == "" then + return str or "" + end + + local parts = {} + for part in str:gmatch("[^_]+") do + -- Первую букву делаем заглавной, остальные - строчными + local formatted = part:sub(1,1):upper() .. part:sub(2):lower() + table.insert(parts, formatted) + end + + return table.concat(parts, " ") +end + +function GetUnitResearchInfo(unit_id) + local info = '' + + historical_figure = researchInfo.getHistoricalFigure(unit_id) + local knowledge = researchInfo.getHistoricKnowledge(historical_figure) + local data = { + knowledge_goal_category = researchInfo.getKnowledgeGoalCategoryInfo(knowledge.knowledge_goal_category), + knowledge_goal = formatKnowledgeString(researchInfo.getGoalInfo(knowledge.knowledge_goal, knowledge.knowledge_goal_category)), + research_points = knowledge.research_points, --TOTAL: 100'000 + research_percentage = string.format("%.2f", (knowledge.research_points / 100000) * 100), + times_pondered = knowledge.times_pondered + } + + if((data.knowledge_goal ~= 'nil') and ((data.times_pondered > 0) or (knowledge.research_points > 0))) then + info = data.knowledge_goal..string.format(' %s%%', data.research_percentage)..string.format(' [%d] ', data.times_pondered) + end + + return info +end + +function GetUnitKnowledge(unit_id) + return researchInfo.getUnitKnowledge(unit_id) +end diff --git a/research-info.lua b/research-info.lua new file mode 100644 index 000000000..b937d8b2f --- /dev/null +++ b/research-info.lua @@ -0,0 +1,69 @@ +local researchInfo = reqscript("internal/research-info/info") + +local function sortResearchDataByPercAndPondered(data_list) + table.sort(data_list, function(a, b) + if tonumber(a.research_percentage) == tonumber(b.research_percentage) then + return a.times_pondered > b.times_pondered + end + return tonumber(a.research_percentage) > tonumber(b.research_percentage) + end) + + return data_list +end + +local function printResearchData(data) + if not data then + print("No data to display.") + return + end + + if data.research_points == 0 and data.knowledge_goal == "" and data.times_pondered == 0 then + return + end + + print("==================") + print("Dwarf: " .. data.name) + print("\tKnowledge Goal Category: " .. data.knowledge_goal_category) + print("\tKnowledge Goal: " .. data.knowledge_goal) + print("\tResearch Points: " .. data.research_points .. "/100000") + print("\tResearch Percentage: " .. data.research_percentage .. "%") + print("\tTimes Pondered: " .. data.times_pondered) + + if #data.research_topics > 0 then + print("Knowledge:") + for _, topic in ipairs(data.research_topics) do + print("\t" .. topic.name .. ": " .. topic.info) + end + end +end + +-- +local unit = dfhack.units.getCitizens() +local selected_unit = dfhack.gui.getSelectedUnit() + +if unit then + local research_data_list = {} + for i, unit in pairs(dfhack.units.getCitizens()) do + + if selected_unit and selected_unit.id ~= unit.id then + goto continue + end + + local historical_figure = researchInfo.getHistoricalFigure(unit.id) + if historical_figure then + local research_data, error_msg = researchInfo.getResearchData(historical_figure) + if research_data then + for _, data in ipairs(research_data) do + table.insert(research_data_list, data) + end + end + end + ::continue:: + end + + research_data_list = sortResearchDataByPercAndPondered(research_data_list) + + for _, data in ipairs(research_data_list) do + printResearchData(data) + end +end \ No newline at end of file