-- This is a player context script for MoO2 1.50 patch project. Script V5.1 -- -- This script gives you an explanation about miniaturization mechanics. -- For each research category, it lists all currently available tech and shows -- additional information to help you determine how much of a miniaturization -- benefit you will get from the next field of a given category. -- The script is compatible with rearrangements of the tech tree such as from -- the RANDTECH or TECH_SH mods. -- The script is also compatible with changes in the miniaturization config -- values that determine how much cost and space is reduced for the three kinds -- of tech groups that exist. -- -- To run the script press 4 in main screen (the file should be named MAIN4.LUA) -- -- Last update of this script: 3th December 2023; Tested with version 1.50.22 improved -- -- Questions etc. to: romanhable@web.de (Epirasque) -- The order in which the individual branche-pages are shown. Do not change the names, rearrange them. BRANCH_SORT_ORDER = {'CONSTRUCTION','POWER','CHEMISTRY','SOCIOLOGY','COMPUTERS','BIOLOGY','PHYSICS','FIELDS','TECH WITHOUT CATEGORY'} -- here is an example of a custom order, in this case it is alphabetical (comment out the line above with -- to disable it -- and remove the -- on the line below to activate it --BRANCH_SORT_ORDER = {'BIOLOGY','CHEMISTRY','COMPUTERS','CONSTRUCTION','FIELDS','PHYSICS','POWER','SOCIOLOGY','TECH WITHOUT CATEGORY'} -- another example which goes from top to bottom in the left column, then top to bottom in the right column --BRANCH_SORT_ORDER = {'CONSTRUCTION','CHEMISTRY','COMPUTERS','PHYSICS','POWER','SOCIOLOGY','BIOLOGY','FIELDS','TECH WITHOUT CATEGORY'} -- For a given field, also show which (0 to 4) techs are currently available for research in that field. SHOW_NEXT_TECH = true -- category C lists tech that does not shrink in size, only in cost (e.g. computers) HIDE_CATEGORY_C = false -- instead of showing space%, cost% it will show space% space. -- if set to true, customize the additional parameters below to your liking. if set to false, the parameters below will be ignored. SHOW_ABSOLUTE_SPACE_INSTEAD_OF_COST = true -- 1 = frigate, 2 = destroyer, 3 = cruiser, 4 = battleship, 5 = titan, 6 = doomstar SHIP_SIZE_USED_FOR_SHIELD_AND_SPECIAL_SYSTEM_SPACE = 4 -- if missile_x3_shot is set to 0 (default): x2, x5, x10, x15, x20 -- if missile_x3_shot is set to 1: x2, x3, x5 , x10, x20 AMMO_USED_FOR_MISSILE_SPACE = 'x2' -- e.g. use 125 for Eccm, 150 for Eccm+Fast (100+25+25=150), etc. MISSILE_SPACE_MULTIPLIER_TIMES_100 = 100 -- when disabled, hides the first page (with explanations but also including current LUA-settings) as well as header explanations for branches SHOW_EXPLANATIONS = true -- e.g. use 50 for Point Defense, 200 for Heavy Mount, 112 for Point Defense + Continuous + Auto Fire + 360 Degree (100+50+50+25)/2=112 etc. -- Note that Point Defense halves after all other modifiers are added up, Heavy Mount doubles after all other modifiers are added up. -- Note that space for weapons is rounded down at .5 (whereas space for a specials system is rounded up) so you should round down 112.5 to 112 as well. BEAM_SPACE_MULTIPLIER_TIMES_100 = 100 -- !!! values below are hardcoded, do not change !!! OWNED_STATUS = 3 NEXT_TO_RESEARCH_IN_BRANCH_STATUS = 2 RESEARCHABLE_STATUS = 1 local miniaturizable_tech_with_deviating_variable_name = { -- left of equals is tech name, right is weapon/special name bomber_bays="bomber",death_spores="death_spore",heavy_fighter_bays="heavy_fighter",assault_shuttles="assault_shuttle",disrupter_cannon="disrupter",fighter_bays="interceptor",shield_capacitors="shield_capacitor" } -- taken from HWMIRROR local function max(a, b) if a > b then return a else return b end end -- taken and adjusted from RANDTECH local function make_branches(ff, keep_gray_boxes) local advf = { advf_biology = 1, advf_power = 1, advf_physics = 1, advf_construction = 1, advf_fields = 1, advf_chemistry = 1, advf_computers = 1, advf_sociology = 1 } local branches = {} local starting_fields = rget_starting_fields() local map = { engineering = "advanced_engineering" } if keep_gray_boxes then map.chemistry = "advanced_metallurgy" map.nuclear_fission = "advanced_fusion" map.physics = "fusion_physics" map.electronics = "optronics" end for i, s in pairs(starting_fields) do if map[s] ~= nil then starting_fields[i] = map[s] end end for i, f in pairs(starting_fields) do local n = rawlen(branches) + 1 local b = { branch_last_field = "advf_" .. i, branchnum = n, field = f, name = i:upper() } table.insert(branches, b) ff[f].is_branch_root = 1 ff[f].tier = 1 end for i, b in ipairs(branches) do local fname = b.field local marks = {} local n = 1 while advf[fname] == nil and ff[fname] ~= nil do local f = ff[fname] if marks[fname] ~= nil then error(tostring("detected tech loop ", marks)) end marks[fname] = n n = n + 1 f.branch = i fname = f.next_field ff[fname].tier = f.tier + 1 end end return branches end -- taken from RANDTECH local function set_id(t, tag) for i, v in pairs(t) do v[tag] = i end end local function shorten_string(str, max_length) local formated_string = str if #formated_string > max_length then formated_string = formated_string:sub(0, max_length - 1) .. "." end return formated_string end -- note: lua's string.gsub, string.gmatch and string.find methods are not supported local function format_tech_string(str, cutoff) local result = str if str == 'anti_missile_rocket' then result = 'Anti-Missile Rockets' elseif str == 'anti_matter_bomb' then result = 'Anti-Matter Bomb' elseif str == 'anti_matter_drive' then result = 'Anti-Matter Drive' elseif str == 'anti_matter_torpedo' then result = 'Anti-Matter Torpedo' elseif str == 'anti_grav_harness' then result = 'Anti-Grav Harness' elseif str == 'bio_terminator' then result = 'Bio-Terminator' elseif str == 'class_iii_shield' then result = 'Class III Shield' elseif str == 'class_vii_shield' then result = 'Class VII Shield' elseif str == 'cyber_security_link' then result = 'Cyber-Security Link' elseif str == 'hyper_x_capacitors' then result = 'Hyper-X Capacitors' elseif str == 'multi_wave_ecm_jammer' then result = 'Multi-Wave Ecm Jammer' elseif str == 'robo_miners' then result = 'Robo-Miners' elseif str == 'sub_space_communications' then result = 'Sub-Space Communications' -- tech with variable names that differ from the equipment name elseif str == 'assault_shuttles' then result = 'Assault Shuttle' elseif str == 'bomber_bays' then result = 'Bomber' elseif str == 'death_spores' then result = 'Death Spore' elseif str == 'disrupter_cannon' then result = 'Disrupter' elseif str == 'fighter_bays' then result = 'Fighter' elseif str == 'heavy_fighter_bays' then result = 'Heavy Fighter' elseif str == 'shield_capacitors' then result = 'Shield Capacitor' end local formated_string = result:sub(1, 1):upper() local next_char_uppercase = false for i = 2, #result do if result:sub(i, i) == '_' then formated_string = formated_string .. ' ' next_char_uppercase = true else if next_char_uppercase then formated_string = formated_string .. result:sub(i, i):upper() next_char_uppercase = false else formated_string = formated_string .. result:sub(i, i) end end end if cutoff == true then if formated_string == 'Multi-Wave Ecm Jammer' or formated_string == 'Structural Analyzer' then formated_string = shorten_string(formated_string, 17) else formated_string = shorten_string(formated_string, 16) end end return formated_string end local function format_field_string(str) local result = str local formated_string = result:sub(1, 1):upper() local next_char_uppercase = false for i = 2, #result do if result:sub(i, i) == '_' then formated_string = formated_string .. ' ' next_char_uppercase = true else if next_char_uppercase then formated_string = formated_string .. result:sub(i, i):upper() next_char_uppercase = false else formated_string = formated_string .. result:sub(i, i) end end end return formated_string end local function format_positive_percentage(percentage) local number = tonumber(percentage) local result = number .. "%" if number < 10 then result = " " .. result elseif number < 100 then result = " " .. result end return result end -- todo: split method to save memory? (would it?) local function is_miniaturizable_tech_name(tech_name, weapons, specials, shields, computers) local m = false; if weapons[tech_name] ~= nil then m = true elseif specials[tech_name] ~= nil and tech_name ~= "battle_pods" then m = true elseif shields[tech_name] ~= nil then m = true elseif computers[tech_name] ~= nil then m = true elseif miniaturizable_tech_with_deviating_variable_name[tech_name] ~= nil then m = true end return m; end local function space_absolute(tech_name, space_relative, weapons, specials, shields, computers, missile_space, add_whitespaces) local base_space = 0 local extra_multiplier = 100 if miniaturizable_tech_with_deviating_variable_name[tech_name] ~= nil then tech_name = miniaturizable_tech_with_deviating_variable_name[tech_name] end if weapons[tech_name] ~= nil then local tech_name_without_last_characters = string.sub(tech_name,-8) if tech_name_without_last_characters == '_missile' then base_space = missile_space extra_multiplier = MISSILE_SPACE_MULTIPLIER_TIMES_100 else base_space = weapons[tech_name].space if weapons[tech_name].space == nil then -- e.g. gyro base_space = weapons[tech_name].size end if weapons[tech_name].available_mods ~= 'none' then --beams (not all have HV!) extra_multiplier = BEAM_SPACE_MULTIPLIER_TIMES_100 end end elseif specials[tech_name] ~= nil and tech_name ~= "battle_pods" then base_space = specials[tech_name]['size' .. tostring(SHIP_SIZE_USED_FOR_SHIELD_AND_SPECIAL_SYSTEM_SPACE)] elseif shields[tech_name] ~= nil then if SHIP_SIZE_USED_FOR_SHIELD_AND_SPECIAL_SYSTEM_SPACE == 1 then -- known issue: cost_ff and space_ff are currently swapped in the lua api base_space = shields[tech_name].space_ff elseif SHIP_SIZE_USED_FOR_SHIELD_AND_SPECIAL_SYSTEM_SPACE == 2 then base_space = shields[tech_name].space_dd elseif SHIP_SIZE_USED_FOR_SHIELD_AND_SPECIAL_SYSTEM_SPACE == 3 then base_space = shields[tech_name].space_ca elseif SHIP_SIZE_USED_FOR_SHIELD_AND_SPECIAL_SYSTEM_SPACE == 4 then base_space = shields[tech_name].space_bb elseif SHIP_SIZE_USED_FOR_SHIELD_AND_SPECIAL_SYSTEM_SPACE == 5 then base_space = shields[tech_name].space_tt elseif SHIP_SIZE_USED_FOR_SHIELD_AND_SPECIAL_SYSTEM_SPACE == 6 then base_space = shields[tech_name].space_ds else msgbox('ERROR: SHIP_SIZE_USED_FOR_SHIELD_SPACE must be a value from 1 to 6') base_space = 0 end elseif computers[tech_name] ~= nil then base_space = 0 end local result = base_space * space_relative * extra_multiplier if result % (100 * 100) >= (50 * 100) then -- round up if >.5 (the excess e.g. of .4 is then removed by the division later on) result = result + (100 * 100) end result = result / (100 * 100) local result_string = tostring(result) if result < 10 and add_whitespaces == true then result_string = ' ' .. result_string elseif result < 100 and add_whitespaces == true then result_string = ' ' .. result_string end return result_string end local function tech_group_to_type_char(tech_name, tech_mini, computers) local group_name = tech_mini[tech_name] -- computers have no size -> force them to group that does not reduce size for clarity if computers[tech_name] ~= nil then group_name = "group3" end local type_char = '?' if group_name == "group1" then type_char = 'A' elseif group_name == "group2" then type_char = 'B' elseif group_name == "group3" then type_char = 'C' end return type_char end local function get_rounded_percent(amount, total) local pro_mille = amount * 1000 / total local per_cent = amount * 100 / total if pro_mille % 10 >= 5 then per_cent = per_cent + 1 end return per_cent end local function explaination_message(cost_at_5, a_space_at_5, b_space_at_5, c_space_at_5) local explaination = "Report of miniaturization status of known techs." explaination = explaination .. "\n" explaination = explaination .. "\n" .. "Mechanics of Miniaturization:" explaination = explaination .. "\n" .. "Ship weapons and specials that benefit from miniaturization reduce in size and cost as advances are made in the tech category that provides them. Furthermore, some weapon modifications only become available when the weapon is miniaturized to a certain level." explaination = explaination .. "\n" explaination = explaination .. "\n" .. "Tiers and Groups:" explaination = explaination .. "\n" .. "The first technology field in a category is considered Tier 0, the field thereafter Tier 1, and so on. The technology's miniaturization group (A, B or C) determines its maximum reduction after 5 levels of miniaturization:" explaination = explaination .. "\n" explaination = explaination .. "\n" .. "A5: Space down to " .. format_positive_percentage(a_space_at_5) .. ", Cost down to " .. format_positive_percentage(cost_at_5) explaination = explaination .. "\n" .. "B5: Space down to " .. format_positive_percentage(b_space_at_5) .. ", Cost down to " .. format_positive_percentage(cost_at_5) explaination = explaination .. "\n" .. "C5: Space down to " .. format_positive_percentage(c_space_at_5) .. ", Cost down to " .. format_positive_percentage(cost_at_5) explaination = explaination .. "\n" explaination = explaination .. "\n" .. "LUA-Settings: " --explaination = explaination .. "\n" .. "Show next tech for given field: " .. tostring(SHOW_NEXT_TECH) explaination = explaination .. "\n" .. "Show next tech: " .. tostring(SHOW_NEXT_TECH):upper() .. " Hide Group C: " .. tostring(HIDE_CATEGORY_C):upper() explaination = explaination .. "\n" .. "Show absolute space instead of cost: " .. tostring(SHOW_ABSOLUTE_SPACE_INSTEAD_OF_COST):upper() if SHOW_ABSOLUTE_SPACE_INSTEAD_OF_COST == true then local ship_size_to_string = {'Frigate', 'Destroyer', 'Cruiser', 'Battleship', 'Titan', 'Doomstar'} explaination = explaination .. "\n" .. "Beam multiplier: " .. tostring(BEAM_SPACE_MULTIPLIER_TIMES_100) .. "% Ship size: " .. ship_size_to_string[SHIP_SIZE_USED_FOR_SHIELD_AND_SPECIAL_SYSTEM_SPACE] explaination = explaination .. "\n" .. "Missile multiplier: " .. tostring(MISSILE_SPACE_MULTIPLIER_TIMES_100) .. "% Ammo: " .. AMMO_USED_FOR_MISSILE_SPACE end msgbox(explaination) end local function gui_location(branch_name) for index, value in pairs(BRANCH_SORT_ORDER) do if value == branch_name then return index end end end local function go() local weapons = get_conf("weapon") local specials = get_conf("special") local shields = get_conf("shield") local computers = get_conf("computer") local tech_mini = get_conf("tech_mini") local miniaturization = get_conf("miniaturization") local cost = { [0] = miniaturization.level_0_cost, miniaturization.level_1_cost, miniaturization.level_2_cost, miniaturization.level_3_cost, miniaturization.level_4_cost, miniaturization.level_5_cost } local a_space = { [0] = get_rounded_percent(miniaturization.level_0_size_groups_1_and_2, 1000), get_rounded_percent(miniaturization.level_1_size_groups_1_and_2, 1000), get_rounded_percent(miniaturization.level_2_size_group_1, 1000), get_rounded_percent(miniaturization.level_3_grp_1_and_level_4_grp_2, 1000), get_rounded_percent(miniaturization.level_4_size_group_1, 1000), get_rounded_percent(miniaturization.level_5_size_group_1, 1000) } local b_space = { [0] = get_rounded_percent(miniaturization.level_0_size_groups_1_and_2, 1000), get_rounded_percent(miniaturization.level_1_size_groups_1_and_2, 1000), get_rounded_percent(miniaturization.level_2_size_group_2, 1000), get_rounded_percent(miniaturization.level_3_size_group_2, 1000), get_rounded_percent(miniaturization.level_3_grp_1_and_level_4_grp_2, 1000), get_rounded_percent(miniaturization.level_5_size_group_2, 1000) } local cost_at_5 = cost[5] local a_space_at_5 = a_space[5] local b_space_at_5 = b_space[5] local c_space_at_5 = 100 --apparently hardcoded local missile_x3_chost = get_conf("missile_x3_shot") local missile_space_and_cost = get_conf("missile_space_and_cost") config = nil collectgarbage() local techs = rget_techs() local player_techs = get_player_techs() local player_fields = get_player_fields() local fields = rget_fields() set_id(fields, "name") local branches = make_branches(fields, 1) local branch_id_to_name = {} local branch_techs = {} local highest_tiers_for_players_branches = {} local hyper_advanced_progress = {} local adv_tech_to_branch_name = { advf_biology = "BIOLOGY", advf_power = "POWER", advf_physics = "PHYSICS", advf_construction = "CONSTRUCTION", advf_fields = "FIELDS", advf_chemistry = "CHEMISTRY", advf_computers = "COMPUTERS", advf_sociology = "SOCIOLOGY" } local player_hyper_advanced_progress = get_player_hyper_advanced_progress() for i, branch in ipairs(branches) do local branch_name = branch.name branch_id_to_name[i] = branch_name highest_tiers_for_players_branches[branch_name] = 0 hyper_advanced_progress[branch_name] = player_hyper_advanced_progress["adv_" .. branch_name:lower()] end player_hyper_advanced_progress = nil highest_tiers_for_players_branches["TECH WITHOUT CATEGORY"] = 0 hyper_advanced_progress["TECH WITHOUT CATEGORY"] = 0 if player_fields ~= nil then local field_to_check for field_name, status in pairs(player_fields) do if status == NEXT_TO_RESEARCH_IN_BRANCH_STATUS then field_to_check = fields[field_name] local branch_name_of_field = branch_id_to_name[field_to_check.branch] if branch_name_of_field == nil then branch_name_of_field = adv_tech_to_branch_name[field_to_check.name] end if field_to_check.tier ~= nil then highest_tiers_for_players_branches[branch_name_of_field] = max(highest_tiers_for_players_branches[branch_name_of_field], field_to_check.tier - 1) -- -1 because it is not reached yet end end end end for i, branch in ipairs(branches) do local branch_name = branch.name highest_tiers_for_players_branches[branch_name] = highest_tiers_for_players_branches[branch_name] + hyper_advanced_progress[branch_name] end branches = nil collectgarbage() if SHOW_ABSOLUTE_SPACE_INSTEAD_OF_COST == true then local missile_space_string = AMMO_USED_FOR_MISSILE_SPACE if missile_x3_shot == 1 then if missile_space_string == 'x3' then missile_space_string = 'x5' elseif missile_space_string == 'x5' then missile_space_string = 'x10' elseif missile_space_string == 'x10' then missile_space_string = 'x15' elseif missile_space_string == 'x15' then msgbox('ERROR: missile_x3_shot = 1 so AMMO_USED_FOR_MISSILE_SPACE may not use x15.') end elseif missile_space_string == 'x3' then msgbox('ERROR: missile_x3_shot = 0 so AMMO_USED_FOR_MISSILE_SPACE may not use x3.') end if missile_space_and_cost[missile_space_string] == nil then msgbox('ERROR: AMMO_USED_FOR_MISSILE_SPACE must be a valid ammo value e.g. x2, also ensure it is put in quotes.') missile_space = 0 else missile_space = missile_space_and_cost[missile_space_string].space end end local tech_cost = {} local tech_tiers = {} local upcoming_tech_per_branch = {} local upcoming_tech_details = {} local upcoming_field_names = {} if player_techs ~= nil then for tech_name, status in pairs(player_techs) do if status == OWNED_STATUS then local field = fields[techs[tech_name].field] local branch_id = field.branch local branch_name = nil -- handle starting tech edge-case if branch_id == nil then local two_fields_ahead = fields[fields[field.next_field].next_field] branch_id = two_fields_ahead.branch end branch_name = tostring(branch_id_to_name[branch_id]) -- starting tech and antaran tech; not miniaturizable anyway if branch_id == nil then branch_name = "TECH WITHOUT CATEGORY" end if branch_name ~= nil then local field_tier = field.tier if field_tier == nil then field_tier = 0 end if branch_techs[branch_name] == nil then branch_techs[branch_name] = {} end if is_miniaturizable_tech_name(tech_name, weapons, specials, shields, computers) then table.insert(branch_techs[branch_name], tech_name) tech_cost[tech_name] = field.cost tech_tiers[tech_name] = field_tier end end end if SHOW_NEXT_TECH == true then local field_name = techs[tech_name].field if player_fields[field_name] == NEXT_TO_RESEARCH_IN_BRANCH_STATUS and player_techs[tech_name] == RESEARCHABLE_STATUS then local field = fields[techs[tech_name].field] local branch_id = field.branch local branch_name = nil -- handle starting tech edge-case if branch_id == nil then local two_fields_ahead = fields[fields[field.next_field].next_field] branch_id = two_fields_ahead.branch end branch_name = tostring(branch_id_to_name[branch_id]) if upcoming_tech_per_branch[branch_name] == nil then upcoming_tech_per_branch[branch_name] = {} end table.insert(upcoming_tech_per_branch[branch_name], tech_name) upcoming_field_names[branch_name] = field_name if is_miniaturizable_tech_name(tech_name, weapons, specials, shields, computers) then local type = tech_group_to_type_char(tech_name, tech_mini, computers) if SHOW_ABSOLUTE_SPACE_INSTEAD_OF_COST == true then local space = 100 if SHOW_ABSOLUTE_SPACE_INSTEAD_OF_COST == true then space = space_absolute(tech_name, 100, weapons, specials, shields, computers, missile_space, false) end upcoming_tech_details[tech_name] = ' (' .. tostring(type) .. ', ' .. tostring(space) .. ' Space)' else upcoming_tech_details[tech_name] = ' (' .. tostring(type) .. ')' end else upcoming_tech_details[tech_name] = '' end end end end end fields = nil techs = nil player_techs = nil player_fields = nil branch_id_to_name = nil adv_tech_to_branch_name = nil if SHOW_ABSOLUTE_SPACE_INSTEAD_OF_COST ~= true then weapons = nil specials = nil shields = nil end -- computers are still needed below collectgarbage() if SHOW_EXPLANATIONS == true then explaination_message(cost_at_5, a_space_at_5, b_space_at_5, c_space_at_5) end cost_at_5 = nil a_space_at_5 = nil b_space_at_5 = nil c_space_at_5 = nil collectgarbage() local is_b_cheaper_than_a = function(a, b) a_cost = tech_cost[a] b_cost = tech_cost[b] local is_cheaper = b_cost < a_cost if a_cost == b_cost then --fallback: sort by name is_cheaper = a < b end return is_cheaper end local branch_tech_array = {} if SHOW_NEXT_TECH == true then for i, branch_name in ipairs(BRANCH_SORT_ORDER) do if branch_techs[branch_name] == nil then --ensures we iterate through all branches in to show upcmong tech even if theres no miniaturizable one branch_techs[branch_name] = {} end end end for i in pairs(branch_techs) do table.insert(branch_tech_array, i) end table.sort(branch_tech_array, function(a,b) return gui_location(a) < gui_location(b) end) local any_result = false for i, branch_name in ipairs(branch_tech_array) do local any_result_in_field = false local player_branch_tier = highest_tiers_for_players_branches[branch_name] local output = "Available tech in " if branch_name == "FIELDS" then output = output .. "FORCE " end output = output .. branch_name if branch_name == "TECH WITHOUT CATEGORY" then output = output .. ":\n\n" else output = output .. " (Tier " .. tostring(player_branch_tier) .. "):\n\n" if SHOW_EXPLANATIONS == true then output = output .. "GM stands for Group and Miniaturization level. N. refers to values at the next level.\n\n" if SHOW_ABSOLUTE_SPACE_INSTEAD_OF_COST == true then output = output .. "GM, Space, Space -> N.Space, N.Space - Name\n\n" else output = output .. "GM, Space, Cost -> N.Space, N.Cost - Name\n\n" end end end if branch_techs[branch_name] == nil then branch_techs[branch_name] = {} end local single_branch_techs = branch_techs[branch_name] table.sort(single_branch_techs, is_b_cheaper_than_a) for j, b_tech in pairs(single_branch_techs) do local miniaturization_level = player_branch_tier - tech_tiers[b_tech] local tiers_ahead = 0 if (miniaturization_level > 5) then miniaturization_level = 5 elseif miniaturization_level < 0 then --edge case: already acquired tech that comes later in tree tiers_ahead = -miniaturization_level miniaturization_level = 0 end local type = tech_group_to_type_char(b_tech, tech_mini, computers) local current_space = 100 --fallback for type C local current_cost = cost[miniaturization_level] if type == 'A' then current_space = a_space[miniaturization_level] elseif type == 'B' then current_space = b_space[miniaturization_level] end if type ~= 'C' or HIDE_CATEGORY_C == false then any_result_in_field = true output = output .. tostring(type) .. tostring(miniaturization_level) .. "," --if miniaturization_level == 1 then -- 1 is less wide than other letters -- output = output .. ' ' --end output = output .. format_positive_percentage(current_space) .. "," if SHOW_ABSOLUTE_SPACE_INSTEAD_OF_COST == true then output = output .. space_absolute(b_tech, current_space, weapons, specials, shields, computers, missile_space, true) else output = output .. format_positive_percentage(current_cost) end if (miniaturization_level >= 5 or branch_name == "TECH WITHOUT CATEGORY") then output = output .. " limit reached" elseif tiers_ahead > 0 then output = output .. " tiers ahead:" .. tostring(tiers_ahead) else local next_miniaturization_level = miniaturization_level + 1 local next_space = 100 --fallback for type C if type == 'A' then next_space = a_space[next_miniaturization_level] elseif type == 'B' then next_space = b_space[next_miniaturization_level] end local next_cost = cost[next_miniaturization_level] output = output .. " - " .. format_positive_percentage(next_space) .. "," if SHOW_ABSOLUTE_SPACE_INSTEAD_OF_COST == true then output = output .. space_absolute(b_tech, next_space, weapons, specials, shields, computers, missile_space, true) else output = output .. format_positive_percentage(next_cost) end end output = output .. " - " .. format_tech_string(b_tech, true) .. "\n" end collectgarbage() end collectgarbage() local any_upcoming_tech = false if SHOW_NEXT_TECH == true then output = output .. "\nUpcoming" -- tech tree display apparently sorts them alphabetically as well local upcoming_field_name = upcoming_field_names[branch_name] if upcoming_field_name ~= nil then output = output .. " in " .. format_field_string(upcoming_field_name) end output = output .. ": " local upcoming_tech = upcoming_tech_per_branch[branch_name] any_upcoming_tech = false if upcoming_tech ~= nil then table.sort(upcoming_tech, function(a, b) return format_tech_string(a) < format_tech_string(b) end) for i, tech_name in pairs(upcoming_tech) do any_upcoming_tech = true output = output .. "\n - " .. format_tech_string(tech_name, false) .. upcoming_tech_details[tech_name] end end if any_upcoming_tech == false then output = output .. "None." end end if any_result_in_field == true or (SHOW_NEXT_TECH == true and any_upcoming_tech == true) then any_result = true msgbox(output) end end if not any_result then msgbox("No relevant tech available yet.") end end go() miniaturizable_tech_with_deviating_variable_name = nil collectgarbage()