--- @class flib_technology local flib_technology = {} --- Gets the active or saved research progress for the given technology. --- @param technology LuaTechnology --- @param level uint --- @return double function flib_technology.get_research_progress(technology, level) local force = technology.force local current_research = force.current_research if current_research and current_research.name == technology.name then if technology.level == level or not flib_technology.is_multilevel(technology) then return force.research_progress else return 0 end elseif technology.level == level then return technology.saved_progress else return 0 end end --- Gets the research unit count for the given technology. --- @param technology LuaTechnology --- @param level uint? --- @return uint function flib_technology.get_research_unit_count(technology, level) local formula = technology.research_unit_count_formula if formula then local level = level or technology.level return math.floor(helpers.evaluate_expression(formula, { l = level, L = level })) end return math.floor(technology.research_unit_count) end --- Returns whether the technology has multiple levels. --- @param technology LuaTechnology|LuaTechnologyPrototype --- @return boolean function flib_technology.is_multilevel(technology) if technology.object_name == "LuaTechnology" then technology = technology.prototype end return technology.level ~= technology.max_level end --- Returns `true` if the first technology should be ordered before the second technology. For use in `table.sort`. --- @param tech_a LuaTechnologyPrototype --- @param tech_b LuaTechnologyPrototype --- @return boolean function flib_technology.sort_predicate(tech_a, tech_b) local ingredients_a = tech_a.research_unit_ingredients local ingredients_b = tech_b.research_unit_ingredients local len_a = #ingredients_a local len_b = #ingredients_b -- Always put technologies with zero ingredients at the front if (len_a == 0) ~= (len_b == 0) then return len_a == 0 end if #ingredients_a > 0 then -- Compare ingredient order strings -- Check the most expensive packs first, and sort based on the first difference for i = 0, math.min(len_a, len_b) - 1 do local ingredient_a = ingredients_a[len_a - i] local ingredient_b = ingredients_b[len_b - i] local order_a = prototypes.item[ingredient_a.name].order local order_b = prototypes.item[ingredient_b.name].order -- Cheaper pack goes in front if order_a ~= order_b then return order_a < order_b end end -- Sort the technology with fewer ingredients in front if len_a ~= len_b then return len_a < len_b end end -- Compare technology order strings local order_a = tech_a.order local order_b = tech_b.order if order_a ~= order_b then return order_a < order_b end -- Compare prototype names return tech_a.name < tech_b.name end --- Returns the technology's prototype name with the level suffix stripped. --- @param technology LuaTechnology|LuaTechnologyPrototype --- @return string function flib_technology.get_base_name(technology) local result = string.gsub(technology.name, "%-%d*$", "") return result end --- If the technology is multi-level, returns the technology's base name with that level appended, otherwise returns the technology name. --- @param technology LuaTechnology --- @param level uint --- @return string function flib_technology.get_leveled_name(technology, level) if flib_technology.is_multilevel(technology) then return flib_technology.get_base_name(technology) .. "-" .. level else return technology.name end end --- @enum TechnologyResearchState flib_technology.research_state = { available = 1, conditionally_available = 2, not_available = 3, researched = 4, disabled = 5, } return flib_technology